Konvertieren von XML-Datei in CSV-Format in java
@Vor Es werden wahrscheinlich einige doppelte Fragen, Anregungen, ich glaube nicht, dass das der Fall ist, vielleicht Lesen Sie dies zuerst, ich werde versuchen es so kurz wie möglich. Titel gibt die grundlegende Idee.
Hier ist ein Beispiel-XML(Fall 1) :
<root>
<Item>
<ItemID>4504216603</ItemID>
<ListingDetails>
<StartTime>10:00:10.000Z</StartTime>
<EndTime>10:00:30.000Z</EndTime>
<ViewItemURL>http://url</ViewItemURL>
....
</item>
Hier ist ein Beispiel-XML(Fall 2) :
<Item>
<ItemID>4504216604</ItemID>
<ListingDetails>
<StartTime>10:30:10.000Z</StartTime>
<!-- Start difference from case 1 -->
<averages>
<AverageTime>value1</AverageTime>
<category type="TX">9823</category>
<category type="TY">9112</category>
<AveragePrice>value2</AveragePrice>
</averages>
<!-- End difference from case 1 -->
<EndTime>11:00:10.000Z</EndTime>
<ViewItemURL>http://url</ViewItemURL>
....
</item>
</root>
Ich lieh mir dieses XML von google sowieso meine Objekte sind nicht immer gleich, manchmal gibt es zusätzliche Elemente, wie in case2. Jetzt würde ich gerne produzieren CSV-wie dies von beiden Fällen:
ItemID,StartTime,EndTime,ViewItemURL,AverageTime,AveragePrice
4504216603,10:00:10.000Z,10:00:30.000Z,http://url
4504216604,10:30:10.000Z,11:00:10.000Z,http://url,value1,value2
Diese 1. Zeile ist Kopfzeile sollte es auch aufgenommen werden im csv-Format. Ich habe einige nützliche links zu stax habe ich heute nicht wirklich weiß nicht, was ist der richtige/optimale Konzept für diese, ich bin mit diesen zu kämpfen, für 3 Tage jetzt, nicht wirklich aufgeben noch.
Sagen Sie mir, was Sie denken, wie würden Sie dies lösen,
Ich vergaß zu erwähnen, dies ist sehr großen xml-Datei bis zu 1gb
BOUNTY UPDATE :
Ich bin auf der Suche nach mehr Generischen Ansatz, was bedeutet, dass diese Arbeit sollte für eine beliebige Anzahl von Knoten mit beliebiger Tiefe, und manchmal, wie im Beispiel-xml ist, kann es passieren, dass man item
Objekt hat eine größere Anzahl von Knoten als die nächste/vorhergehende, so sollte es auch den Fall(also alle Spalten und Werte entsprechen in CSV).
Außerdem kann es passieren, daß Knoten, die den gleichen Namen haben/localName, aber unterschiedliche Werte und Attribute, wenn das der Fall ist, dann neue Spalte angezeigt werden soll in CSV mit den entsprechenden Wert. (Ich fügte hinzu, Beispiel diesem Fall innerhalb <averages>
tag aufgerufen category
)
<averages/>
element? Ist averages
das einzige element, das erscheinen könnte? Oder tun, Sie müssen flexibler sein, über das, was dort erscheint?Ich aktualisiert meine Frage
über Ihr "update": wenn nicht das erste element ist die mit den meisten Spalten, als Sie gerade zwei Pässe/Schritte für die transformation: in Schritt eins, die Sie nur sammeln Sie alle Spalten, die in Schritt 2 Verfahren Sie wie beschrieben. Wenn kein Wert Knoten zu einem bestimmten Knoten zu finden ist, als können Sie einen Wert ein, den Sie wünschen (null oder leer oder was auch immer-Konvention, die Sie mögen - siehe meine Beschreibung in die Antwort). Es ist nicht ein problem, dass die Knoten Ineinander verschachtelt sind, da für CSV-werden Sie rot flach.
Ionescu danke für deine Antwort, ich denke ich habe genug gesammelt algorithmen für die Lösung, ich habe sogar ein implementiert(funktioniert nicht richtig), aber jetzt ich bin auf der Suche nach etwas code, damit Sie das Kopfgeld.
InformationsquelleAutor ant | 2010-07-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den code bereitgestellt werden, sollte erwogen werden, eine Skizze eher als der definitive Artikel. Ich bin kein Experte auf SAX und die Umsetzung könnte noch verbessert werden für eine bessere performance, einfachere code etc. Das sagte SAX sollten in der Lage sein zu bewältigen, das streaming von großen XML-Dateien.
Ich würde nähern dieses problem mit 2 Pässen mit dem SAX-parser. (Übrigens, ich würde auch ein CSV erzeugen-Bibliothek, um die Ausgabe zu erstellen, dies würde sich mit all den vertrackten Charakter der Flucht, die CSV beinhaltet, aber das habe ich noch nicht implementiert, das in meiner Skizze).
Ersten Durchgang:
Etablieren Anzahl der header-Spalten
Zweiten Durchgang:
Ausgabe CSV -
Ich gehe davon aus, dass die XML-Datei wohlgeformt ist. Ich gehe davon aus, dass wir nicht in ein Schema/DTD-mit einer vorgegebenen Reihenfolge.
Im ersten Durchgang habe ich angenommen, dass Sie eine CSV-Spalte Hinzugefügt wird für jedes XML-element mit text-Inhalt oder für jedes Attribut (ich habe angenommen Attribute enthalten etwas!).
Den zweiten Durchgang, nachdem festgestellt wurde, die Anzahl der Ziel-Spalten, wird die CSV-Ausgabe.
Basierend auf deinem Beispiel-XML-mein-code-Skizze erzeugen würde:
Bitte beachten Sie ich habe die google-Sammlungen LinkedHashMultimap als dies ist hilfreich bei der Zuordnung mehrerer Werte mit einem einzigen Schlüssel. Ich hoffe, Sie finden diese nützlich!
Hi @toop Sie konnte immer tun, es basiert auf Baum-Tiefe, siehe z.B.: stackoverflow.com/questions/6248322/...
InformationsquelleAutor
Dieser sieht aus wie ein guter Fall für den Einsatz von XSL. Angesichts Ihrer grundlegenden Anforderungen kann es einfacher sein, um den rechten Knoten mit XSL-im Vergleich zu custom-Parser oder serialisierungsprogramme. Der Vorteil wäre, dass das XSL-Ziel könnte "//Item//AverageTime" oder was auch immer Knoten, die Sie benötigen, ohne sich Gedanken über die knotentiefe.
UPDATE: das folgende ist Die xslt ich warf zusammen, um sicherzustellen, das wie erwartet funktionierte.
XSL wäre die perfekte Wahl, wenn das war eine kleine Datei, aber der DOM für eine 1gb Datei nehmen könnte, eine riesige Menge an Speicher. Also ich könnte mir vorstellen eine Art von spezialisierten streaming-XSL angewandt werden müsste (in diesem thread bereits erwähnt Saxonica und VTD-XML) Siehe auch: stackoverflow.com/questions/2301926/xml-process-large-data
Das ist einige interessante Informationen. In diesem Fall, ein streaming-xsl-tech sinnvoll wäre. Danke für den link Daneben.
InformationsquelleAutor
Ich bin mir nicht sicher, ob ich verstehe, wie die generische Lösung sein soll. Wollen Sie wirklich zu analysieren, eine 1 GB Datei zweimal für eine generische Lösung? Und wenn Sie wollen, etwas generisch, warum hast du übersprungen
<category>
element in deinem Beispiel? Wie viel anderen format benötigen Sie zu handhaben? Tun Sie wirklich nicht wissen, was das format kann (auch wenn einige element kann weggelassen werden)? Können Sie das klären?Meiner Erfahrung ist es generell sinnvoller zu analysieren, bestimmte Dateien in einer bestimmten Art und Weise (dies schließt nicht die Verwendung eines generischen API). Meine Antwort in diese Richtung zu gehen (und ich werde es zu aktualisieren, nach der Klärung).
Wenn Sie sich nicht wohl fühlen mit XML, könnten Sie erwägen, einige der bestehenden (kommerziellen) Bibliotheken, zum Beispiel Ricebridge XML-Manager und CSV-Manager. Sehen Wie konvertieren von CSV in XML und XML in CSV mit Hilfe von Java für ein vollständiges Beispiel. Der Ansatz ist Recht einfach: Sie definieren die Daten, die Felder mithilfe von XPath-Ausdrücken (die perfekt ist in Ihrem Fall, da können Sie "extra" - Elemente), das Parsen der Datei und übergeben Sie das Ergebnis
List
zu der CSV-Komponente zum generieren der CSV-Datei. Die API sieht einfach, den code getestet (den Quellcode Ihrer Testfälle steht unter einer BSD-style license), Sie behaupten, die Unterstützung von gigabyte-großen Dateien.Erhalten Sie eine Entwickler-Lizenz für $170, die ist nicht sehr teuer im Vergleich zu Entwickler täglich Preisen.
Bieten Sie 30 Tage trial-Versionen, haben einen Blick.
Andere Möglichkeit wäre die Verwendung von Spring Batch. Spring batch bietet alles, was erforderlich ist, um XML-Dateien als Eingang oder Ausgabe (mit StAX und die XML-binding-framework Ihrer Wahl) und Flatfiles als Eingang oder Ausgabe. Siehe:
Könnten Sie auch Smooks zu tun, XML -, CSV -Transformationen. Siehe auch:
Eine andere option wäre, Rollen Sie Ihre eigene Lösung mit einem StAX-parser oder, warum nicht, mit VTD-XML und XPath. Haben Sie einen Blick auf:
InformationsquelleAutor
Der beste Weg, um code, basierend auf Ihrer beschriebenen Anforderung ist die Verwendung der easy-Funktion von FreeMarker und XML-Verarbeitung. Siehe die Dokumentation.
In diesem Fall brauchen Sie nur die Vorlage, erzeugt eine CSV-Datei.
Eine alternative dazu ist XMLGen, aber sehr ähnlich in der Herangehensweise. Schauen Sie das Diagramm und Beispiele, und anstelle von SQL-Anweisungen wird die Ausgangs-CSV.
Diese zwei ähnliche Ansätze werden nicht "herkömmlich", aber die Arbeit machen, die sehr schnell für Ihre situation, und Sie müssen nicht lernen, XSL (ziemlich schwer zu meistern wie ich finde).
InformationsquelleAutor
Hier einige code, der implementiert die Umwandlung von XML nach CSV mit StAX. Obwohl die XML-Ausgabe gab, ist nur ein Beispiel, ich hoffe, dass dies zeigt, Sie zu behandeln, wie die optionalen Elemente.
InformationsquelleAutor
Ich bin nicht davon überzeugt, dass SAX ist der beste Ansatz für Sie.
Es gibt verschiedene Möglichkeiten, die Sie nutzen könnten SAX hier, obwohl.
Wenn element-Reihenfolge ist nicht garantiert, innerhalb bestimmter Elemente, wie ListingDetails, dann müssen Sie proaktiv zu sein.
Wenn man ein ListingDetails, initialisieren einer Karte als eine member-variable an die Prozedur übergeben. In jedem Unterelement, legen Sie den entsprechenden Schlüssel-Wert dieser Karte. Wenn Sie fertig sind eine ListingDetails, untersuchen Sie die Karte und explizit mock Werte wie null-Werte für die fehlenden Elemente. Vorausgesetzt, Sie haben ein ListingDetails pro Element, speichern Sie es auf eine member-variable in der Prozedur.
Nun, wenn deine item-element ist über, eine Funktion haben, das schreibt die Zeile Wird basierend auf der Karte in der Reihenfolge, die Sie wollte.
Die Gefahr mit diesem ist wenn Sie haben beschädigte XML. Ich würde stark darüber nachdenken, die Einstellung aller dieser Variablen auf null, wenn ein Element beginnt, und dann die überprüfung für Fehler und kündigt Ihnen, wenn das Element endet.
InformationsquelleAutor
Beachten Sie, dass dies ein hervorragendes Beispiel für eine Verwendung von XSLT-außer, dass die meisten XSLT-Prozessoren Lesen die ganze XML-Datei in den Speicher, das ist nicht eine option, da es zu groß ist. Beachten Sie jedoch, dass die enterprise-version von Saxon können streaming-XSLT-Verarbeitung (wenn der XSLT-Skript hält sich an die Einschränkungen).
Möglicherweise möchten Sie auch auf die Verwendung eines externen XSLT-Prozessor außerhalb Ihrer JVM statt, falls zutreffend. Dies eröffnet mehrere Optionen.
Streaming in Saxon-EE: http://www.saxonica.com/documentation/sourcedocs/serial.html
Warum nur XSLT-wie statt eines XSLT-Teilmenge?
InformationsquelleAutor
Könnten Sie XStream (http://x-stream.github.io/) oder JOX (http://www.wutka.com/jox.html) zu erkennen, xml und konvertieren Sie Sie dann in einer Java-Bean. Ich denke, Sie können konvertieren Sie die Bohnen in das CSV automatisch, sobald man die Bohne.
InformationsquelleAutor