Frage

Ich suche nach der besten Methode zum Parsen verschiedener XML-Dokumente mithilfe einer Java-Anwendung.Ich mache das derzeit mit SAX und einem benutzerdefinierten Content-Handler und es funktioniert großartig – schnell und stabil.

Ich habe beschlossen, die Möglichkeit zu prüfen, mit demselben Programm, das derzeit ein XML-Dokument in einem einzigen Format empfängt, zwei zusätzliche XML-Dokumentformate mit verschiedenen Änderungen an XML-Elementen zu erhalten.Ich hatte gehofft, den ContentHandler einfach durch einen geeigneten ersetzen zu können, der auf dem ersten „startElement“ im Dokument basiert ...aber, ähm, der ContentHandler ist gesetzt und Dann Das Dokument wird analysiert!

... constructor ...
{
SAXParserFactory spf = SAXParserFactory.newInstance();

try {
SAXParser sp = spf.newSAXParser();
parser = sp.getXMLReader();
parser.setErrorHandler(new MyErrorHandler());
} catch (Exception e) {} 

... parse StringBuffer ...
try {
parser.setContentHandler(pP);
parser.parse(new InputSource(new StringReader(xml.toString())));
return true;
} catch (IOException e) {
    e.printStackTrace();
} catch (SAXException e) {
    e.printStackTrace();
}
...

Es scheint also nicht so zu sein, dass ich das so machen kann, wie ich es ursprünglich gedacht hatte.

Davon abgesehen sehe ich das völlig falsch?Was ist die beste Methode, um mehrere, diskrete XML-Dokumente mit demselben XML-Verarbeitungscode zu analysieren? Ich habe vorhin versucht, in einem allgemeineren Beitrag zu fragen ...aber ich glaube, ich war zu vage.Aus Geschwindigkeits- und Effizienzgründen habe ich mich nie wirklich mit DOM befasst, da diese XML-Dokumente ziemlich groß sind und das System alle paar Minuten etwa 1200 empfängt.Es handelt sich lediglich um eine einseitige Informationsübermittlung

Um diese Frage zu lang zu machen und meine Verwirrung zu verstärken;Im Folgenden finden Sie ein Modell einiger verschiedener XML-Dokumente, die ich gerne als einzelnes SAX, StAX oder ?? hätte.Parser sauber behandeln.

Produkte.xml:

<products>
<product>
  <id>1</id>
  <name>Foo</name>
<product>
  <id>2</id>
  <name>bar</name>
</product>
</products>

speichert.xml:

<stores>
<store>
  <id>1</id>
  <name>S1A</name>
  <location>CA</location>
</store>
<store>
  <id>2</id>
  <name>A1S</name>
  <location>NY</location>
</store>
</stores>

manager.xml:

<managers>
<manager>
  <id>1</id>
  <name>Fen</name>
  <store>1</store>
</manager>
<manager>
  <id>2</id>
  <name>Diz</name>
  <store>2</store>
</manager>
</managers>
War es hilfreich?

Lösung

Soweit ich weiß, besteht das Problem darin, dass Sie vor dem Parsen nicht wissen, welches Format das Dokument hat.Sie könnten ein Delegatenmuster verwenden.Ich gehe davon aus, dass Sie nicht anhand einer DTD/XSD/etcetera validieren und dass es in Ordnung ist, dass der DefaultHandler den Status hat.

public class DelegatingHandler extends DefaultHandler {

    private Map<String, DefaultHandler> saxHandlers;
    private DefaultHandler delegate = null;

    public DelegatingHandler(Map<String, DefaultHandler> delegates) {
        saxHandlers = delegates;
    }

    @Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
       if(delegate == null) {
           delegate = saxHandlers.get(name);
       }
       delegate.startElement(uri, localName, name, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        delegate.endElement(uri, localName, name);
    }

//etcetera...

Andere Tipps

Sie haben gut erklärt, was Sie tun möchten, aber nicht warum.Es gibt mehrere XML-Frameworks, die das Marshalling und Unmarshalling von Java-Objekten in/von XML vereinfachen.

Das einfachste ist Commons-Digester die ich normalerweise zum Parsen von Konfigurationsdateien verwende.Wenn Sie sich jedoch mit Java-Objekten befassen möchten, sollten Sie sich Folgendes ansehen Rolle, JiBX, JAXB, XMLBeans, XStream, oder etwas ähnliches.Castor oder JiBX sind meine beiden Favoriten.

Ich habe den SAXParser einmal ausprobiert, aber einmal habe ich ihn gefunden XStream Ich bin nie wieder darauf zurückgekommen.Mit XStream können Sie Java-Objekte erstellen und in XML konvertieren.Senden Sie sie rüber und verwenden Sie XStream, um das Objekt neu zu erstellen.Sehr einfach zu verwenden, schnell und erstellt sauberes XML.

In jedem Fall müssen Sie wissen, welche Daten Sie aus der XML-Datei erhalten.Sie können sie auf unterschiedliche Weise senden, um zu erfahren, welchen Parser Sie verwenden sollen.Oder Sie verfügen über ein Datenobjekt, das alles enthalten kann, aber nur eine Struktur gefüllt ist (Produkt/Geschäft/Manager).Vielleicht so etwas wie:

public class DataStructure {

    List<ProductStructure> products;

    List<StoreStructure> stors;

    List<ManagerStructure> managers;

    ...

    public int getProductCount() {
        return products.lenght();
    }

    ...
}

Und mit XStream in XML konvertieren, senden und dann das Objekt neu erstellen.Dann machen Sie damit, was Sie wollen.

Weitere Informationen finden Sie in der Dokumentation XMLReader.setContentHandler(), es sagt:

Anwendungen können während einer Analyse einen neuen oder anderen Handler registrieren, und der SAX-Parser muss sofort mit der Verwendung des neuen Handlers beginnen.

Daher sollten Sie in der Lage sein, eine zu erstellen SelectorContentHandler das verbraucht Ereignisse bis zum ersten startElement Ereignis, basierend darauf ändert sich die ContentHandler auf dem XML-Reader und übergibt das erste Startelementereignis an den neuen Inhaltshandler.Du musst nur bestehen XMLReader zum SelectorContentHandler im Konstruktor.Wenn Sie brauchen alle die zu verarbeitenden Ereignisse werden an den vokabularspezifischen Inhaltshandler übergeben, SelectorContentHandler muss die Ereignisse zwischenspeichern und dann übergeben, aber in den meisten Fällen ist dies nicht erforderlich.

Nebenbei bemerkt, ich habe es in letzter Zeit verwendet XOM In fast allen meinen Projekten zur Verarbeitung von XML war die Leistung bisher kein Problem.

JAXB.Die Java-Architektur für XML-Bindung.Im Grunde erstellen Sie eine XSD, die Ihr XML-Layout definiert (ich glaube, Sie könnten auch eine DTD verwenden).Anschließend übergeben Sie die XSD an den JAXB-Compiler und der Compiler erstellt Java-Klassen zum Marshallen und Unmarshalieren Ihres XML-Dokuments in Java-Objekte.Es ist wirklich einfach.

Übrigens gibt es Befehlszeilenoptionen für jaxb, um den Paketnamen anzugeben, in dem Sie die resultierenden Klassen platzieren möchten usw.

Wenn Sie ein dynamischeres Handling wünschen, würde der Stax-Ansatz wahrscheinlich besser funktionieren als der Sax-Ansatz.Das ist immer noch ein recht niedriges Niveau;Wenn Sie einen einfacheren Ansatz wünschen, sind XStream und JAXB meine Favoriten.Für die Zuordnung sind jedoch recht starre Objekte erforderlich.

Stimmen Sie StaxMan zu, der interessanterweise möchte, dass Sie Stax verwenden.Es handelt sich um einen Pull-basierten Parser anstelle des Push-Parsers, den Sie derzeit verwenden.Dies würde jedoch einige wesentliche Änderungen an Ihrem Code erfordern.

:-)

Ja, ich habe eine gewisse Vorliebe für Stax.Aber wie gesagt, oft ist die Datenbindung bequemer als eine Streaming-Lösung.Wenn Sie jedoch Streaming wünschen und kein Pipelining (mehrere Filterstufen) benötigen, ist Stax einfacher als SAX.

Eine Sache noch:So gut XOM auch ist (in Bezug auf Alternativen), oft ist Tree Model nicht das Richtige, wenn Sie nicht mit „dokumentzentriertem“ XML arbeiten (~= xhtml-Seiten, DocBook, Open-Office-Dokumente).Für den Datenaustausch, Konfigurationsdateien usw. ist die Datenbindung bequemer, effizienter und natürlicher.Sagen Sie einfach Nein zu Baummodellen wie DOM für diese Anwendungsfälle.JAXB, XStream und JibX sind also gut.Oder, für einen ausgeprägteren Geschmack, Digester, Castor, XMLBeans.

VTD-XML gilt als die beste XML-Verarbeitungstechnologie für die anspruchsvolle XML-Verarbeitung.Einen Beweis finden Sie in der Referenz unten

http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top