是否可以使用Groovy XMLSlurper解析子树

时间:2010-11-05 08:01:03

标签: groovy xmlslurper

是否有人知道是否可以以某种方式使用XMLSlurper,这意味着可以从非常大的XML文档中提取单个子树并单独处理?

想象一下,您有一个包含根元素的巨大XML Feed,该元素包含数千个可以单独处理的直接子元素。显然,将整个文档读入内存是一个禁忌,但是,因为根的每个子项本身都是适度的大小,所以流式传输文档但是依次将XMLSlurper的好处应用于每个子元素会更好。在处理每个子元素时,垃圾收集可以清理用于处理它的内存。通过这种方式,我们可以轻松获得XMLSlurper(这种简洁的语法),并且内存占用空间很小(例如SAX)。

我有兴趣知道是否有人有这方面的想法和/或你是否已经遇到过这个要求。

2 个答案:

答案 0 :(得分:2)

初始化XmlSlurper实例意味着调用其中一个重载的parse(..)方法(或parseText(String)方法)。在此调用之后,XmlSlurper将(至少使用SAX事件)构造一个内存中GPathResult,其中包含有关XML元素和属性及其结构的完整信息。

所以,不,XmlSlurper 只提供解析XML文档部分的API。

可以做的是extend XmlSlurper,覆盖parse*(..)方法,通过using a custom SAX handler预处理XML,收集所需的XML部分,以及将这些转发给XmlSlurper.parse*(..)方法之一。

答案 1 :(得分:2)

您可以将StAX API与XmlSlurper一起使用来解析子树。

// Example of using StAX to split a large XML document and parse a single element using XmlSlurper

import javax.xml.stream.XMLInputFactory
import javax.xml.stream.XMLStreamReader
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerFactory
import javax.xml.transform.sax.SAXResult
import javax.xml.transform.stax.StAXSource

def url = new URL("http://repo2.maven.org/maven2/archetype-catalog.xml")
url.withInputStream { inputStream ->
    def xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream)
    def transformer = TransformerFactory.newInstance().newTransformer()
    while (xmlStreamReader.hasNext()) {
        xmlStreamReader.next()
        if (xmlStreamReader.isStartElement() && xmlStreamReader.getLocalName() == 'archetype') {
            // Example of splitting a large XML document and parsing a single element with XmlSlurper at a time
            def xmlSlurper = new XmlSlurper()
            transformer.transform(new StAXSource(xmlStreamReader), new SAXResult(xmlSlurper))
            def archetype = xmlSlurper.document
            println "${archetype.groupId} ${archetype.artifactId} ${archetype.version}"
        }
    }
}