2010-11-05 3 views
3

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

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

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

ответ

2

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

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

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

+0

Спасибо, я пришел к выводу, что мне нужно будет сделать что-то подобное. Тем не менее, это означает, что я, по сути, должен сделать двойной проход, и, таким образом, он влияет на производительность. – DrewEaster

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}" 
     } 
    } 
} 
+0

Я ответил на это в Твиттере некоторое время назад https://twitter.com/lhotari/status/694002023562416128, поэтому я решил добавить ответ и к SO. –