我正在使用包含嵌入式xml文档的CDATA字段解析XML文档,并且我想要解组所有这些文档。遗憾的是,DOM的scala xml解析器正在检索<。![CDATA []]> cdata字段中的标记。我如何接受它?到目前为止,我的尝试是尝试按以下方式对元素进行模式匹配:
node match {
case Elem(_, _, _, _, Text(text)) => {
if(text.startsWith("<") && text.endsWith(">")) map put(CDATA, fromXml(text))
else map put(TEXT, text)
}
case Elem(_, _, _, _, PCData(text)) => println(text) /* CDATA! */
case _ => map ++= seqLoop(node \ "_") /* Not element must call children recursively */
}
正如你所看到的那样,我试图用cdata对模式匹配元素,它完全落在Text上,我只能用那个丑陋的情况检测它。如果是这样的话。
任何帮助?
答案 0 :(得分:2)
<foo><bar/></foo>
和<foo><![CDATA[<bar/>]]></foo>
是等效的。这些只是逃避特殊字符的一些不同方法。您shouldn't depend在源上返回一个或另一个。
如果您可以控制架构,则应使用其他属性或元素来指定文本数据是XML格式。
也就是说,在解析XML字符串或文件时,似乎可以劫持scala XML库以生成CData部分的PCData
元素:
import scala.xml.{TopScope, InputSource, SAXParser, Elem, PCData}
import scala.xml.parsing.FactoryAdapter
import scala.xml.factory.XMLLoader
import org.xml.sax.ext.{LexicalHandler, DefaultHandler2}
object XMLLoaderWithCData extends XMLLoader[Elem] {
def lexicalHandler(adapter: FactoryAdapter): LexicalHandler =
new DefaultHandler2 {
def captureCData(): Unit = {
adapter.hStack push PCData(adapter.buffer.toString)
adapter.buffer.clear()
}
override def startCDATA(): Unit = adapter.captureText()
override def endCDATA(): Unit = captureCData()
}
override def loadXML(source: InputSource, parser: SAXParser): Elem = {
val newAdapter = adapter
val xmlReader = parser.getXMLReader
xmlReader.setProperty(
"http://xml.org/sax/properties/lexical-handler",
lexicalHandler(newAdapter))
newAdapter.scopeStack push TopScope
parser.parse(source, newAdapter)
newAdapter.scopeStack.pop()
newAdapter.rootElem.asInstanceOf[Elem]
}
}
您可以将此XMLLoaderWithCData
主要用作普通scala.xml.XML
对象:
scala> val x = "<foo><bar>aaa<![CDATA[<111/>]]>bbb</bar><![CDATA[<bar/>]]></foo>"
x: String = <foo><bar>aaa<![CDATA[<111/>]]>bbb</bar><![CDATA[<bar/>]]></foo>
scala> XMLLoaderWithCData.loadString(x)
res0: scala.xml.Elem = <foo><bar>aaa<![CDATA[<111/>]]>bbb</bar><![CDATA[<bar/>]]></foo>
此实现当然非常脆弱,取决于Scala库的实现细节,因此可能会在将来更新的情况下中断。
答案 1 :(得分:1)
var a = XML.loadString(xmlString)
var cdata=(a \\ "tagwithCdata").text
var b= XML.loadString(cdata)
现在您可以将b
解析为XML节点。