Xml 返回节点和字符串列表的Groovy Node.depthFirst()?
我希望有人能指出我在这里遗漏的一些明显的东西。我觉得我已经做了一百次了,今晚出于某种原因,这种行为让我感到很困惑 我正在从公共API中读取一些XML。我想从某个节点(body中的所有内容)提取所有文本,该节点还包括各种子节点。简单的例子:Xml 返回节点和字符串列表的Groovy Node.depthFirst()?,xml,groovy,xml-parsing,xmlnode,xmlslurper,Xml,Groovy,Xml Parsing,Xmlnode,Xmlslurper,我希望有人能指出我在这里遗漏的一些明显的东西。我觉得我已经做了一百次了,今晚出于某种原因,这种行为让我感到很困惑 我正在从公共API中读取一些XML。我想从某个节点(body中的所有内容)提取所有文本,该节点还包括各种子节点。简单的例子: 头衔 这包括 斜体字 和 外部参照 . 第二名 因此,最终我希望遍历所需节点(同样是“body”)内的树,并提取其自然顺序中包含的所有文本。很简单,所以我写了这个小的Groovy脚本 def xmlParser=new xmlParser() def
头衔
这包括
斜体字
和
外部参照
.
第二名
因此,最终我希望遍历所需节点(同样是“body”)内的树,并提取其自然顺序中包含的所有文本。很简单,所以我写了这个小的Groovy脚本
def xmlParser=new xmlParser()
def xml=xmlParser.parseText(rawXml)
xml.metadata.article.body[0].depthFirst().each{node->
if(node.children().size()==1){
println node.text()
}
}
…它继续爆炸,并显示“没有方法签名:java.lang.String.children()”。所以我在想“等等,什么?我疯了吗?”Node.depthFirst()应该只返回节点的列表。我添加了一点“instanceof”检查,果然得到了节点对象和字符串对象的组合。具体来说,不在同一行的实体中的行作为字符串返回,也称为“This contains”和“and”。其他所有内容都是一个节点(如预期的那样)
我可以很容易地解决这个问题。然而,这似乎不是正确的行为,我希望有人能给我指出正确的方向 我非常确定这是正确的行为(尽管我总是发现XmlSlurper和XmlParser的api非常糟糕)。您可以迭代的所有内容实际上都应该实现一个节点接口IMO,并且可能有一个
类型的文本,您可以使用它从中获取文本
这些文本节点是有效的节点,在许多情况下,在XML中进行深度优先遍历时,您会希望命中这些节点。如果它们没有返回,那么检查子节点大小是否为1的算法将不起作用,因为某些节点(如
标记)下面既有混合文本又有元素
此外,为什么depthFirst
不一致地返回文本为唯一子级的所有文本节点(例如上面的italic
),这会让事情变得更糟
我倾向于使用groovy方法的签名,让运行时找出处理每个节点的正确方法(而不是使用类似于instanceof
)的方法,如下所示:
def rawXml = """<xml>
<metadata>
<article>
<body>
<sec>
<title>A Title</title>
<p>
This contains
<italic>italics</italic>
and
<xref ref-type="bibr">xref's</xref>
.
</p>
</sec>
<sec>
<title>Second Title</title>
</sec>
</body>
</article>
</metadata>
</xml>"""
def processNode(String nodeText) {
return nodeText
}
def processNode(Object node) {
if(node.children().size() == 1) {
return node.text()
}
}
def xmlParser = new XmlParser()
def xml = xmlParser.parseText(rawXml)
def xmlText = xml.metadata.article.body[0].'**'.findResults { node ->
processNode(node)
}
println xmlText.join(" ")
或者,XmlSlurper
类可能会做更多您想要/期望它做的事情,并且从text()
方法得到一组更合理的输出。如果您真的不需要对结果进行任何类型的DOM遍历(什么是XmlParser
更好),我建议XmlSlurper
:
def xmlParser = new XmlSlurper()
def xml = xmlParser.parseText(rawXml)
def bodyText = xml.metadata.article.body[0].text()
println bodyText
印刷品:
A Title
This contains
italics
and
xref's
.
Second Title
最后一点是我真正想要的,也是我所期待的。我可以发誓我已经试过了,但每次我都必须把depthFirst()放在那里,这让我陷入了一个循环。哦,还有GPathResult.text()的行为与Node.text()非常不同的事实。我希望这些文档能提供更多的信息……你能解释一下Double“*”@Shashank.gupta40“**”的意思吗?
是depthFirst()的缩写。
据我所知,Node.depthFirst的行为与groovy 1.7中预期的一样。在groovy 2.0+中,我看到了节点/字符串的相同结果。
A Title
This contains
italics
and
xref's
.
Second Title