SAX IncrementalParser в Jython

Стандартная библиотека Python предоставляет xml.sax.xmlreader.IncrementalParser интерфейс, который имеет метод feed(). Jython также предоставляет пакет xml.sax, который использует реализацию парсера Java SAX под капотом, но, похоже, не предоставляет IncrementalParser.

Есть ли способ инкрементного разбора кусков XML в Jython? На первый взгляд я думал, что это может быть достигнуто с помощью сопрограммы типа greenlet, но я сразу понял, что ее нельзя использовать в Jython.

Ответ 1

Вы можете использовать StAX. Тег StAX parser, как SAX, но поддерживает курсор и позволяет извлекать содержимое с помощью hasNext() и next().

Следующий код адаптирован из этого примера Java. Обратите внимание, что это моя первая попытка когда-либо с jython, так что не вешайте меня, если я что-то делаю нетрадиционно, но пример работает.

http://www.javacodegeeks.com/2013/05/parsing-xml-using-dom-sax-and-stax-parser-in-java.html

from javax.xml.stream import XMLStreamConstants, XMLInputFactory, XMLStreamReader
from java.io import ByteArrayInputStream;
from java.lang import String

xml = String(
"""<?xml version="1.0" encoding="ISO-8859-1"?>
<employees>
  <employee id="111">
    <firstName>Rakesh</firstName>
    <lastName>Mishra</lastName>
    <location>Bangalore</location>
  </employee>
  <employee id="112">
    <firstName>John</firstName>
    <lastName>Davis</lastName>
    <location>Chennai</location>
  </employee>
  <employee id="113">
    <firstName>Rajesh</firstName>
    <lastName>Sharma</lastName>
    <location>Pune</location>
  </employee>
</employees>
""")

class Employee:
    id = None
    firstName = None
    lastName = None
    location = None

    def __str__(self):
        return self.firstName + " " + self.lastName + "(" + self.id + ") " + self.location

factory = XMLInputFactory.newInstance();
reader = factory.createXMLStreamReader(ByteArrayInputStream(xml.getBytes()))
employees = []
employee = None
tagContent = None

while reader.hasNext():
    event = reader.next();

    if event == XMLStreamConstants.START_ELEMENT:
        if "employee" == reader.getLocalName():
            employee = Employee()
            employee.id = reader.getAttributeValue(0)
    elif event == XMLStreamConstants.CHARACTERS:
        tagContent = reader.getText()
    elif event == XMLStreamConstants.END_ELEMENT:
        if "employee" == reader.getLocalName():
            employees.append(employee)
        elif "firstName" == reader.getLocalName():
            employee.firstName = tagContent
        elif "lastName" == reader.getLocalName():
            employee.lastName = tagContent
        elif "location" == reader.getLocalName():
            employee.location = tagContent

for employee in employees:
    print employee

Ответ 2

Вы можете напрямую использовать сакс-парсер Java.

from javax.xml.parsers import SAXParserFactory
factory = SAXParserFactory.newInstance()
xmlReader = XMLReaderFactory.createXMLReader()

from org.xml.sax.helpers import DefaultHandler
handler = DefaultHandler() # or use your own handler
xmlReader.setContentHandler(handler)
xmlReader.parse(new InputSource(streamReader))