-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a2edb3b
commit 9a10c49
Showing
6 changed files
with
141 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
Mitori-Satori/src/main/kotlin/xyz/xasmc/mitori/satori/util/xmlParser/PlainTextElement.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package xyz.xasmc.mitori.satori.util.xmlParser | ||
|
||
class PlainTextElement(val text: String) : XmlElement("text", emptyMap(), emptyList()) { | ||
override fun toString(): String { | ||
return text | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
Mitori-Satori/src/main/kotlin/xyz/xasmc/mitori/satori/util/xmlParser/XmlDocument.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package xyz.xasmc.mitori.satori.util.xmlParser | ||
|
||
class XmlDocument( | ||
val elements: List<XmlElement>, | ||
) { | ||
override fun toString() = elements.joinToString("") | ||
|
||
companion object { | ||
fun fromString(str: String): XmlDocument { | ||
return XmlDocument(parseStr(str).first) | ||
} | ||
|
||
private fun parseStr(content: String, parentName: String? = null): Pair<MutableList<XmlElement>, Int> { | ||
val result = mutableListOf<XmlElement>() | ||
val sb = StringBuilder() | ||
var ptr = 0 | ||
while (ptr < content.length) { | ||
// 处理闭标签 | ||
if (content[ptr] == '<' && content[ptr + 1] == '/') { | ||
if (sb.isNotEmpty()) { | ||
result.add(PlainTextElement(sb.toString().trimEnd())) | ||
sb.clear() | ||
} | ||
val endIndex = content.indexOf(">", ptr) | ||
val closeTagStr = content.substring(ptr..endIndex) | ||
val closeTagName = closeTagStr.removeSurrounding("</", ">").trim() | ||
if (closeTagName == parentName) return Pair(result, endIndex + 1) // 正确的闭标签, 返回 | ||
throw IllegalArgumentException("Unknown CloseTag: $closeTagStr") | ||
} | ||
// 处理开标签 | ||
if (content[ptr] == '<') { | ||
if (sb.isNotEmpty()) { | ||
result.add(PlainTextElement(sb.toString().trimEnd())) | ||
sb.clear() | ||
} | ||
val endIndex = content.indexOf(">", ptr) | ||
if (content[endIndex - 1] == '/') { | ||
// 立即关闭 | ||
val openTagStr = content.substring(ptr..endIndex) | ||
val (name, attr) = parseOpenTag(openTagStr) | ||
result.add(XmlElement(name, attr, mutableListOf())) | ||
ptr = endIndex + 1 | ||
continue | ||
} | ||
val openTagStr = content.substring(ptr..endIndex) | ||
val (name, attr) = parseOpenTag(openTagStr) | ||
// 处理剩下的内容 | ||
ptr = endIndex + 1 | ||
val contentStr = content.substring(ptr..<content.length) | ||
val (child, read) = parseStr(contentStr, name) | ||
ptr += read | ||
result.add(XmlElement(name, attr, child)) | ||
continue | ||
} | ||
// 啥也不是,原始文本 | ||
if (sb.isNotEmpty() || (content[ptr] != '\n' && content[ptr] != ' ')) if (content[ptr] == '\n') { | ||
result.add(PlainTextElement(sb.toString().trimEnd())) | ||
sb.clear() | ||
result.add(XmlElement("br", emptyMap(), emptyList())) | ||
} else sb.append(content[ptr]) | ||
ptr++ | ||
} | ||
return Pair(result, content.length) | ||
} | ||
|
||
private fun parseOpenTag(str: String): Pair<String, MutableMap<String, String>> { | ||
val regex = Regex("""^< *([a-zA-Z0-9]+)(?: ((?: *[a-zA-Z0-9]+(?: *= *"[^"]*")? *)*))? */?>${'$'}""") | ||
val result = regex.find(str) ?: throw IllegalArgumentException("Can not parse tag: $str") | ||
val name = result.groupValues[1] | ||
|
||
val attr = mutableMapOf<String, String>() | ||
val attrStr = result.groupValues[2] | ||
val attrRegex = Regex("""([a-zA-Z0-9]+)(?: *= *"([^"]+)")?""") | ||
attrRegex.findAll(attrStr).forEach { | ||
val key = it.groupValues[1] | ||
val value = it.groupValues[2] | ||
attr[key] = value | ||
} | ||
return Pair(name, attr) | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
Mitori-Satori/src/main/kotlin/xyz/xasmc/mitori/satori/util/xmlParser/XmlElement.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package xyz.xasmc.mitori.satori.util.xmlParser | ||
|
||
open class XmlElement( | ||
val name: String, | ||
val attributes: Map<String, String>, | ||
val children: List<XmlElement>, | ||
) { | ||
override fun toString(): String { | ||
val sb = StringBuilder() | ||
sb.append("<").append(name) | ||
attributes.forEach { | ||
sb.append(" ").append(it.key) | ||
if (it.value.isNotEmpty()) sb.append("=\"").append(it.value).append("\"") | ||
} | ||
if (children.isNotEmpty()) { | ||
sb.append(">") | ||
children.forEach { sb.append(it.toString()) } | ||
sb.append("</").append(name).append(">") | ||
} else { | ||
sb.append("/>") | ||
} | ||
return sb.toString() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import org.junit.jupiter.api.Test | ||
import xyz.xasmc.mitori.satori.util.xmlParser.XmlDocument | ||
import kotlin.test.assertEquals | ||
|
||
class XmlParserTest { | ||
@Test | ||
fun testXmlParser() { | ||
val result = XmlDocument.fromString( | ||
""" | ||
<a href="awa" aaa>aLink</a> | ||
1145144<br/> | ||
1919810 | ||
awawawaw | ||
<p> | ||
awa | ||
<a href="/login">login</a> | ||
qwqwqwq | ||
</p> | ||
""".trimIndent() | ||
) | ||
assertEquals( | ||
result.toString(), | ||
"<a href=\"awa\" aaa>aLink</a>1145144<br/>1919810<br/>awawawaw<br/><p>awa<br/><a href=\"/login\">login</a>qwqwqwq<br/></p>" | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters