【问题标题】:Parsing html with cyberneko to find a 'div'-tag用cyberneko解析html以找到一个'div'-tag
【发布时间】:2009-12-29 13:26:51
【问题描述】:

我需要一个来自 html 站点的特定 'div'-tag(由 'id' 标识)。解析页面 我正在使用cyberneko。

    def doc = new XmlParser( new org.cyberneko.html.parsers.SAXParser() ).parse(htmlFile)
    divTag = doc.depthFirst().DIV.find{ it['@id'] == tagId  }

到目前为止没问题,但最后我不需要XML,而是整个'div'标签的原始内容。不幸的是,我无法弄清楚如何做到这一点......

【问题讨论】:

  • 你的意思是
    标签的文本形式的内容吗?
  • 不仅是找到的
    -tag中包含的标签。

标签: java xml groovy cyberneko


【解决方案1】:

编辑:回应第一条评论。

这行得通:

def html = """
  <body>
        <div id="breadcrumbs">
            <b>
            crumb1
            </b>
        </div>
</body>
"""

def doc = new XmlSlurper(new org.cyberneko.html.parsers.SAXParser()).parseText(html)
divTag = doc.BODY.DIV.find { it.@id == 'breadcrumbs'  }
println "" << new groovy.xml.StreamingMarkupBuilder().bind {xml -> xml.mkp.yield divTag}

看起来cyberneko 会返回一个格式良好的HTML 文档,不管原始标记是否是。即,文档的根将是一个 HTML 元素,并且还会有一个 HEAD 元素。整洁。

【讨论】:

  • 哇,这是一个非常酷/时髦的想法! :) 不幸的是,它似乎(还)不起作用——返回的“doc”不包含任何标签,而只包含原始内容的文本内容。因此,“doc.DIV.find{}”永远不会找到“DIV”。为了便于阅读,我将在新帖子/答案中添加一个简单的测试。
  • 诺亚:谢谢——这一切都成功了!但是我还有另一个问题:由于原始 HTML 页面定义了一个命名空间 (xmlns="w3.org/1999/xhtml"),结果中的所有标签也会有它。为了摆脱它,我不得不将它添加到bind{xml.mkp.declareNamespace(tag0:null); xml.mkp.yield divTag} 我确定这是一个hack,但不幸的是我找不到关于这个特殊命名空间'mkp'的好文档,也找不到任何其他解决方案。 ..
  • @domi 我相信是cyberneko添加了命名空间。你检查过文档吗?
  • Noah:你说得对,我现在找到了要在 org.cyberneko.html.parsers.SAXParser: 'parser.setFeature("xml.org/sax/features/namespaces", false)' 上设置的正确功能一切都很完美! :)
【解决方案2】:

这是一个基于诺亚回答的简单测试 - 不幸的是它(还)不起作用:(

    def html = """
      <body>
            <div id="breadcrumbs">
                <b>
                crumb1
                </b>
            </div>
    </body>
    """

    def doc = new XmlSlurper( new org.cyberneko.html.parsers.SAXParser() ).parseText(html)
    println "document: $doc"
    def htmlTag = doc.DIV.find {
        println "-> $it"
        it['@id'] == "breadcrumbs"
    }
    println htmlTag
    assert htmlTag

【讨论】:

  • 我已经编辑了我的答案以使用这个测试用例。需要注意的一点是 GPathResult 的 toString (文档是)不是它包含的 XML,它只是文本内容(我不知道为什么,这几乎没用)。这就是为什么 StreamingMarkupBuilder().bind {xml... 技巧是必要的。
猜你喜欢
相关资源
最近更新 更多
热门标签