2 Stimmen

Wie würden Sie Java verwenden, um verschiedene XML-Dokumente zu verarbeiten?

Ich bin auf der Suche nach der besten Methode zum Parsen verschiedener XML-Dokumente mit einer Java-Anwendung. Ich tue dies derzeit mit SAX und einem benutzerdefinierten Content-Handler und es funktioniert großartig - zippy und stabil.

Ich habe beschlossen, die Option zu erkunden, die das gleiche Programm, das derzeit ein einzelnes Format XML-Dokument empfängt, zwei zusätzliche XML-Dokumentformate mit verschiedenen XML-Elementänderungen empfangen. Ich hatte gehofft, einfach den ContentHandler mit einem geeigneten auf der Grundlage der ersten "startElement" im Dokument austauschen... aber, uh-duh, der ContentHandler ist festgelegt und dann das Dokument wird geparst!

... 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 sieht also nicht so aus, als ob ich das so machen könnte, wie ich es ursprünglich dachte.

Sehe ich die Sache also völlig falsch? Was ist die beste Methode, um mehrere einzelne XML-Dokumente mit demselben XML-Verarbeitungscode zu parsen? Ich habe vorhin versucht, in einem allgemeineren Beitrag zu fragen, aber ich glaube, ich war zu vage. . Aus Geschwindigkeits- und Effizienzgründen habe ich DOM nie wirklich in Betracht gezogen, da diese XML-Dokumente ziemlich groß sind und das System alle paar Minuten etwa 1200 erhält. Es ist nur ein einseitiger Versand von Informationen

Um diese Frage zu lang und fügen Sie zu meiner Verwirrung; folgende ist ein Mockup von einigen verschiedenen XML-Dokumenten, die ich möchte eine einzelne SAX, StAX, oder ??

products.xml:

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

stores.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>

3voto

McDowell Punkte 105255

So wie ich es verstehe, besteht das Problem darin, dass Sie nicht wissen, welches Format das Dokument vor dem Parsen hat. Sie könnten ein Delegatenmuster verwenden. Ich gehe davon aus, dass Sie nicht gegen eine DTD/XSD/etcetera validieren und dass es OK ist für die DefaultHandler, Zustand zu haben.

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...

2voto

Brian Matthews Punkte 8225

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

Die einfachste ist Commons-Fermenter die ich normalerweise zum Parsen von Konfigurationsdateien verwende. Wenn Sie jedoch mit Java-Objekten arbeiten wollen, sollten Sie sich Castor , JiBX , JAXB , XMLBeans , XStream oder etwas Ähnliches. Castor oder JiBX sind meine beiden Favoriten.

2voto

Bernie Perez Punkte 12323

Ich habe den SAXParser einmal ausprobiert, aber sobald ich die XStream Ich habe es nie wieder benutzt. Mit XStream können Sie Java-Objekte erstellen und sie in XML konvertieren. Senden Sie sie und verwenden Sie XStream, um das Objekt neu zu erstellen. Sehr einfach zu bedienen, schnell und erzeugt sauberes XML.

In jedem Fall müssen Sie wissen, welche Daten Sie aus der XML-Datei empfangen wollen. Sie können sie auf unterschiedliche Weise senden, um zu wissen, welchen Parser Sie verwenden müssen. Oder Sie haben ein Datenobjekt, das alles aufnehmen kann, aber nur eine Struktur befüllt (Produkt/Lager/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, rüberschicken und dann das Objekt neu erstellen. Dann machen Sie damit, was Sie wollen.

2voto

jelovirt Punkte 5744

Siehe die Dokumentation für XMLReader.setContentHandler() heißt es:

Anwendungen können einen neuen oder anderen Handler in der Mitte eines Parses registrieren, und der SAX-Parser muss sofort mit der Verwendung des neuen Handlers beginnen.

So sollten Sie in der Lage sein, eine SelectorContentHandler die Ereignisse verbraucht, bis die erste startElement Ereignis, aufgrund dessen sich die ContentHandler auf dem XML-Reader und übergibt das erste Startelement-Ereignis an den neuen Content-Handler. Sie müssen nur das XMLReader a la SelectorContentHandler im Konstruktor. Wenn Sie benötigen todo die Ereignisse, die an den vokabelspezifischen Content-Handler weitergegeben werden sollen, SelectorContentHandler muss die Ereignisse zwischenspeichern und dann weitergeben, aber in den meisten Fällen ist dies nicht erforderlich.

Nebenbei bemerkt, habe ich in letzter Zeit XOM in fast allen meinen Projekten, um XML zu verarbeiten, aber bisher war die Leistung nicht das Problem.

1voto

Vinnie Punkte 11598

JAXB . Die Java-Architektur für XML-Bindung. Grundsätzlich erstellen Sie eine xsd, die Ihr XML-Layout definiert (ich glaube, Sie könnten auch eine DTD verwenden). Dann übergeben Sie die XSD an den JAXB-Compiler, und der Compiler erstellt Java-Klassen, um Ihr XML-Dokument in Java-Objekte zu marshalen und unmarshalen. Es ist wirklich einfach.

Es gibt übrigens Kommandozeilenoptionen für jaxb, mit denen Sie den Paketnamen angeben können, in den die resultierenden Klassen eingeordnet werden sollen, usw.

0 Stimmen

Der Poster hat bereits angedeutet, dass er wegen des zu erwartenden Volumens (1200 alle paar Minuten) lieber einen Stream-Parser wie SAX verwendet. Außerdem kennt er das Format der einzelnen XML-Dateien nicht, bevor er mit dem Parsen beginnt, so dass die DTD-basierte Lösung ungültig ist!

0 Stimmen

Ich stimme zu, dass DTD ein großes Nein ist, aber bedenken Sie, dass JAXB auch Teilbäume binden kann, wenn ein Stax XMLStreamReader vorhanden ist; außerdem sind Java POJOs viel speicherfreundlicher und benötigen im Allgemeinen viel weniger Platz als XML (oder DOM, das 3- bis 5-mal so groß ist wie XML selbst!). Die Verwendung von JAXB mit annotierten POJOs ist also ziemlich sinnvoll

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X