我有一个非常具体(而且很怪异)的文本文件,它不是XML文件,而是包含一个XML文档。它的结构或多或少是这样的:
Some text that I am not interested in...
More text that I don't need.
<tagIWant>
<...>
<!-- A large XML document -->
<...>
</tagIwant>
Some more text...
我想在Scala中解析此文本文件,并从<tagIWant>
到</tagIWant>
提取XML文件。我知道XML解析器在Scala中非常强大,但是显然不能将其解析为XML。
答案 0 :(得分:2)
MIGHT可行的一种方法(用Java术语,您必须转换为Scala)是从您自己的Reader向解析器提供输入,在SAX ContentHandler中使用解析器的输出,并返回-从ContentHandler到Reader的通道,以便在报告最外面的元素的endElement事件后,立即通知Reader停止提供输入。
之所以可能不起作用,是因为解析器可能会缓冲来自阅读器的输入,因此,当ContentHandler告诉阅读器停止时,为时已晚。
可惜的是,XML解析器没有一个选项可以在检测到结束符时停止没有错误的解析,但是如果有一个带有该选项的解析器,我没有遇到。您可以随时尝试修改开放源代码解析器!
答案 1 :(得分:1)
val text = """
Some text that I am not interested in...
More text that I don't need.
<tagIWant>
<qqq>
<!-- A large XML document -->
</qqq>
</tagIWant>
Some more text...
"""
val pattern = "(?s).*(<tagIWant>.*</tagIWant>).*".r
val xml = pattern.findFirstMatchIn(text).map(m => m.group(1)).map(x => scala.xml.XML.loadString(x))
结果是Option[scala.xml.Elem]
包含您的XML或无。
另外,请考虑使用pattern.findAllMatchIn
。
答案 2 :(得分:0)
最好先对文件进行预处理,以除去非XML位,然后再将其传递给XML解析器。这段代码将去除所有没有XML标记的开头和结尾行:
val isTag = "<[^>]+>".r
val xml =
text.split("\n")
.dropWhile(isTag.findFirstMatchIn(_).isEmpty)
.reverse
.dropWhile(isTag.findFirstMatchIn(_).isEmpty)
.reverse
.mkString("\n")
您可以将text.split("\n")
替换为将文本文件读取为String
值列表的任何代码。
这假定开头标记是一行中的第一个文本,而结束标记是一行中的最后一个文本。