【问题标题】:How to extract CDATA without the GPath/node name如何在没有 GPath/节点名称的情况下提取 CDATA
【发布时间】:2018-09-17 16:31:15
【问题描述】:

我试图在不使用 GPath(或)节点名称的情况下从 XML 中提取 CDATA 内容。简而言之,我想从 XML 中查找并检索包含 CDATA 部分的 innerText。

我的 XML 看起来像:

def xml = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
    <Test1>This node contains some innerText. Ignore This.</Test1>
    <Test2><![CDATA[this is the CDATA section i want to retrieve]]></Test2>
</root>'''

从上面的 XML 中,我想单独获取 CDATA 内容,而不使用其节点名称“Test2”的引用。因为在我的场景中节点名称并不总是相同的。

另请注意,XML 可以在其他几个节点(Test1)中包含 innerText。我不想找回那个。我只需要整个 XML 中的 CDATA 内容。

我想要类似下面的东西(虽然下面的代码不正确)

def parsedXML = new xmlSlurper().parseText(xml)
def cdataContent = parsedXML.depthFirst().findAll { it.text().startsWith('<![CDATA')}  

我的输出应该是:

this is the CDATA section i want to retrieve

【问题讨论】:

  • 使用 groovy xml 解析器无法检测到 cdata。您必须使用 DOM 或其他 xml 解析器。

标签: groovy cdata xmlslurper


【解决方案1】:

正如@daggett 所说,您不能使用 Groovy slurper 或解析器来执行此操作,但下拉并使用 java 类来获取它也不错。

请注意,您必须将 CDATA 的属性设置为可见,因为默认情况下它只是被视为字符。

代码如下:

import javax.xml.stream.*

def xml = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
    <Test1>This node contains some innerText. Ignore This.</Test1>
    <Test2><![CDATA[this is the CDATA section i want to retrieve]]></Test2>
</root>'''

def factory = XMLInputFactory.newInstance()
factory.setProperty('http://java.sun.com/xml/stream/properties/report-cdata-event', true)

def reader = factory.createXMLStreamReader(new StringReader(xml))
while (reader.hasNext()) {
    if (reader.eventType in [XMLStreamConstants.CDATA]) {
        println reader.text
    }
    reader.next()
}

这将打印this is the CDATA section i want to retrieve

【讨论】:

  • 这是完美可靠的解决方案。谢谢!!
【解决方案2】:

考虑到您的 xml 中只有一个 CDATA split 可以在这里提供帮助

def xml = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
<Test1>This node contains some innerText. Ignore This.</Test1>
<Test2><![CDATA[this is the CDATA section i want to retrieve]]></Test2>
 </root>'''

 log.info xml.split("<!\\[CDATA\\[")[1].split("]]")[0]

所以在上面的逻辑中,我们在 CDATA 开始时拆分字符串并选择剩下的部分

xml.split("<!\\[CDATA\\[")[1]

一旦我们得到那部分,我们再次进行拆分,然后通过使用得到该模式之前的部分

.split("]]")[0] 

这是有效的证明

【讨论】:

  • 嗯...不喜欢这个,不应该鼓励字符串操作来解析 XML...
  • 确实它不是很合乎逻辑,但在某些自定义情况下,它似乎是最好的解决方案。
猜你喜欢
  • 2020-12-03
  • 2016-01-07
  • 2011-02-11
  • 2017-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
  • 1970-01-01
相关资源
最近更新 更多