Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 返回节点和字符串列表的Groovy Node.depthFirst()?_Xml_Groovy_Xml Parsing_Xmlnode_Xmlslurper - Fatal编程技术网

Xml 返回节点和字符串列表的Groovy Node.depthFirst()?

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

我希望有人能指出我在这里遗漏的一些明显的东西。我觉得我已经做了一百次了,今晚出于某种原因,这种行为让我感到很困惑

我正在从公共API中读取一些XML。我想从某个节点(body中的所有内容)提取所有文本,该节点还包括各种子节点。简单的例子:


头衔

这包括
斜体字
和
外部参照
.

第二名
因此,最终我希望遍历所需节点(同样是“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