Можно ли анализировать поддеревья с помощью Groovy XMLSlurper - PullRequest
3 голосов
/ 05 ноября 2010

Кто-нибудь знает, возможно ли использовать XMLSlurper таким образом, чтобы отдельные поддеревья можно было извлечь из очень большого XML-документа и обработать по отдельности?

Представьте, что у вас огромный XML-каналсодержащий корневой элемент, имеющий тысячи прямых дочерних элементов, которые вы можете обрабатывать по отдельности.Очевидно, что чтение всего документа в память - нет-нет, но, поскольку каждый дочерний элемент корня сам по себе имеет скромный размер, было бы неплохо выполнить потоковую передачу по документу, но поочередно применять правильность XMLSlurper к каждому дочернему элементу.Поскольку каждый дочерний элемент обрабатывается, сборщик мусора может очищать память, используемую для его обработки.Таким образом, мы получаем простоту XMLSlurper (такой краткий синтаксис) с низким объемом памяти для потоковой передачи (например, SAX).

Мне было бы интересно узнать, есть ли у кого-нибудь идеи по этому поводу и / или есть лиВы сами сталкивались с этим требованием.

Ответы [ 2 ]

2 голосов
/ 09 февраля 2016

Вы можете использовать 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}"
        }
    }
}
2 голосов
/ 05 ноября 2010

Инициализация экземпляра XmlSlurper означает вызов одного из его перегруженных методов parse(..) (или метода parseText(String)).После этого вызова XmlSlurper будет (по крайней мере, использовать события SAX) создавать в памяти GPathResult, который содержит полную информацию об элементах и ​​атрибутах XML и их структуре.

Итак, нет,XmlSlurper не не предоставляет API для анализа только частей XML-документа.

Что можно сделать, extend ing XmlSlurper, переписав parse*(..) методы,предварительно обработав XML с помощью , используя пользовательский обработчик SAX , собрав нужные части XML и перенаправив их в один из XmlSlurper.parse*(..) методов.

...