Groovy XmlParser / XmlSlurper:node.localText()位置?

时间:2015-09-12 17:01:00

标签: groovy html-parsing xmlslurper

我对此问题有一个后续问题:Groovy XmlSlurper get value of the node without children

它解释了为了获得(HTML)节点的本地内部文本而不递归地获取潜在内部子节点的嵌套文本,必须使用#localText()而不是#text()

例如,原始问题的一个稍微增强的例子:

<html>
    <body>
        <div>
            Text I would like to get1.
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </div>
        <span>
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </span>
    </body>
</html>

应用解决方案:

def tagsoupParser = new org.ccil.cowan.tagsoup.Parser()
def slurper = new XmlSlurper(tagsoupParser)
def htmlParsed = slurper.parseText(stringToParse)

println htmlParsed.body.div[0].localText()[0]

将返回:

[Text I would like to get1., Text I would like to get2., Text I would like to get3.]

但是,解析此示例中的<span>部分

println htmlParsed.body.span[0].localText()

输出

[Text I would like to get2., Text I would like to get3.]

我现在面临的问题是,显然无法确定文本的位置(“在哪个子节点之间”)。我本来期望第二次调用产生

[, Text I would like to get2., Text I would like to get3.]

这可以说清楚:位置0(在孩子0之前)是空的,位置1(在孩子0和1之间)是“文本我想得到2”。和位置2(在孩子1和2之间)是“我希望获得的文字3”。但是,鉴于API的工作原理,显然无法确定在索引0处返回的文本是否实际位于索引0或任何其他索引处,并且对于所有其他索引也是如此。

我已经使用XmlSlurperXmlParser进行了尝试,结果相同。

如果我没有弄错,那么使用解析器中的信息完全重新创建原始HTML文档也是不可能的,因为这个“文本索引”信息会丢失。

我的问题是:有没有办法找出这些文字位置?要求我更改解析器的答案也是可以接受的。

更新/解决方案:

为了进一步参考,这里是Will P的答案,适用于原始代码:

def tagsoupParser = new org.ccil.cowan.tagsoup.Parser()
def slurper = new XmlParser(tagsoupParser)
def htmlParsed = slurper.parseText(stringToParse)

println htmlParsed.body.div[0].children().collect {it in String ? it : null}

这会产生:

[Text I would like to get1., null, Text I would like to get2., null, Text I would like to get3.]

必须使用 XmlParser 代替 XmlSlurper node.children()

1 个答案:

答案 0 :(得分:1)

我不知道jsoup,我希望它不会干扰解决方案,但是使用纯XmlParser,你可以得到一个包含原始字符串的children()数组:

html = '''<html>
    <body>
        <div>
            Text I would like to get1.
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </div>
        <span>
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </span>
    </body>
</html>'''

def root = new XmlParser().parseText html

root.body.div[0].children().with {
    assert get(0).trim() == 'Text I would like to get1.'
    assert get(0).getClass() == String

    assert get(1).name() == 'a'
    assert get(1).getClass() == Node

    assert get(2) == '''
            Text I would like to get2.
            '''
}