Можно ли анализировать поддеревья с помощью Groovy XMLSlurper

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

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

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


person DrewEaster    schedule 05.11.2010    source источник


Ответы (2)


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

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

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

person robbbert    schedule 05.11.2010
comment
Спасибо - я пришел к выводу, что мне придется сделать что-то подобное. Однако это означает, что мне, по сути, придется выполнять двойной проход, и, таким образом, это влияет на производительность. - person DrewEaster; 05.11.2010

Вы можете использовать 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}"
        }
    }
}
person Lari Hotari    schedule 09.02.2016
comment
Я ответил на это в Твиттере некоторое время назад, twitter.com/lhotari/status/694002023562416128, поэтому я решил добавить ответ также в SO. - person Lari Hotari; 09.02.2016