2013-10-16 16 views
10

Python-Standardbibliothek bietet xml.sax.xmlreader.IncrementalParser Schnittstelle, die feed() Methode hat. Jython bietet auch xml.sax Paket, das Java SAX Parser-Implementierung unter der Haube verwendet, aber es scheint IncrementalParser nicht bereitzustellen.SAX IncrementalParser in Jython

Gibt es any Weg, inkrementelle Teile von XML in Jython zu analysieren? Auf den ersten Blick dachte ich, es kann mit Coroutine wie greenlet erreicht werden, aber ich erkannte sofort, dass es nicht in Jython verwendet werden kann.

Antwort

3

Sie können StAX verwenden. Der StAX Parser streamt wie SAX, behält aber einen Cursor bei und ermöglicht es Ihnen, Inhalt am Cursor mit hasNext() und next() zu extrahieren.

Der folgende Code wurde aus diesem Java-Beispiel übernommen. Beachten Sie, das ist mein erster Versuch jemals mit Jython, also hänge mich nicht an, wenn ich etwas unkonventionell gemacht habe, aber das Beispiel funktioniert.

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 
1

Sie können den Sax Parser von Java direkt verwenden.

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)) 
+0

Es ist eigentlich kein _incremental_ Parser, sondern ein gewöhnlicher ereignisgesteuerte Parser. Was ich wirklich brauche, ist die Möglichkeit, Teile von XML zu füttern, ohne die Steuerung zu invertieren (was einen Leser-Rückruf ermöglicht). Beispiel: 'parser.feed (" "); do_something_other(); parser.feed ("") ' – minhee