Einfache XML Bearbeitung mit der Shell

W

Willy538

Grünschnabel
hallo Leute,

Ich hab mit Linux nicht so viel Erfahrung, aber ich kenne die Grundlagen, sed grep, reguläre Ausdrücke usw.. Hier mein Problem:

Ich hab ne xml Datei mit folgendem aufbau:
Code:
<export>
  <object id="IDdesÄußerstenObjects">
    ...
    ...
    <object>
    ...
    ...
    </object>
    <object>
    ...
    ...
    </object>
    ...
    ...
  </object>
  <object id="IDdesÄußerstenObjects">
    ...
    ...
    <object>
    ...
    ...
    </object>
    <object>
    ...
    ...
    </object>
    ...
    ...
  </object>
  ...
</export>

Ich will immer eine bestimmte Anzahl der äußersten Objekte in eine eigene Datei kopieren. Normalerweise wär das kein Problem, ich würd es einfach mit php z.b. simpleXML machen. Aber meine Datei ist 1.3 GB groß - das sprengt meine sämtlichen RAM Vorräte.

Hier ist mein Plan:

Schritt 1: Alle "\n" löschen
Das hab ich schon nicht hinbekommen. Meine Versuche:
1. sed /\n//g datei.xml (hat nicht funktioert)
2. tr '\n' '' < datei.xml > out.xml (hat auch nicht funktioert)
3. tr '\n' ' ' < datei.xml > out.xml (alle \n durch Leer ersetzen)(hat funktioniert)
sed / //g (alle leer löschen)(hat nicht funktioert)

Schritt 2:Mit sed Alle "<object id="IDdesÄußerstenObjects">" durch "\n<object id="IDdesÄußerstenObjects">" ersetzen
Das hab ich noch nicht ausprobiert (denke aber, dass das nicht so schwer sein sollte)

Schritt 3: Jede Zeile (oder immer 2 bzw. 3 usw.) in eine eigene Datei kopieren
Ich hab keine Ahnung wie das geht, aber ich denke, dass es auf jeden Fall möglich ist (oder?)

Schritt 4: Den Anfang jeder in schritt 3 erzeugen Datei durch <export> ersetzen, das Ende durch </export>

Das ist also mein Plan, was haltet ihr davon? zu umständlich, gehts auch einfacher? oder ganz andere Vorschläge?
Wenn mein Plan halbwegs durchführbar ist, wie genau sind die einzelnen Schritte umzusetzen?

mfg Willy
 
Wieso machst du das nicht über XSL? (mit z.B. xsltproc als Prozessor)
 
Hallo
Würdest du so nett sein, und mal deine verwendete Shell nebst verwendeten Unix/Linux nennen?
Desweiteren wär eine genaue Angabe, was du aus deinem Beispiel als Ergebnis in einer neuen Datei erwartest hilfreich.

Erwartest du, dass alles was hinter id="..." steht in einer neuen Datei landet?
Weil du schreibst vorher von einige...
Wenn ja, ungetesteter Schnellschuß:
GNU sed
Code:
sed -ne '1p;$p;/object id/{s/.*object id="\([^"]\+\)".*/\1/;p}' file >newfile

Um z.B. alle Newline mit tr zu löschen:
Code:
tr -d "\n" <input >output

Gruß Wolfgang
 
Zuletzt bearbeitet:
@slackfan

xslt zu verwenden ist ein guter Gedanke, daran hab ich noch gar ned gedacht. Ich seh dabei jedoch 2 Probleme:
1. xslt muss meine datei parsen, dabei sind 1.3 GB evtl. zu viel (das käme auf einen versuch an)
2. Ich glaube nicht, dass der XSLT Prozessor auch mehrere Ausgabe Dateien generieren kann, nur eine oder?

@Wolfgang

Meinst du damit welche distribution von linux installiert ist?
Das weiß ich leider nicht. Es handelt sich um einen server der weit weg ist, ich hab nur über ssh zugriff darauf.

In meinem export Element sind ca. 1500 object elemente, die die id=".." haben. ich will jetzt immer z.b. 6 solcher object elemente in eine eigene Datei kopieren, so erhielte ich ca. 250 dateien. Die struktur der 250 Dateien sollte genau so sein, wie meine 1.3 gb große Datei.
Ich brauche nicht eine Datei mit 1500 elementen sondern mehrere dateien mit je nur z.b. 6 elementen.
 
Zuletzt bearbeitet:
Evtl. kannst Du das mit

Code:
csplit file /object\ id/ {*}

lösen. Das zerlegt Dir file in Abschnitte mit den Namen xxnn.
 
Zuletzt bearbeitet:
Von csplit hab ich noch nie was gehört, finde die Idee jedoch ziemlich genial. ich versteh nur die syntax noch noch ned genau.
Wenn ich "csplit file /RA/ {*}" schreibe (RA steht für Regulärer Ausdruck) dann wird der Teil der Datei zwischen 2 Auftreten von RA in eine eigene Datei kopiert und zwar beliebig oft, oder? In deinem Bsp. müsste "object\ id" der RA sein, oder? Welche Bedautung hat "\ "? Wird dadurch das Leer-Zeichen escaped?
 
Lösung mit xsl

Hallo,


wie es aussieht, ünterstützt xsltproc im Moment (leider) diese Funktion noch nicht, weil diese wohl erst fester Bestandteil von xslt 2.0 ist. Mit Saxon funktioniert es aber mit dem von dir gezeigten Beispiel gut. Hier der im Kurztest funktionierende Stylesheet.

Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon">

<xsl:template match="export">

<xsl:for-each select="object">
    <saxon:output href="output/{@id}.xml">
        <xsl:copy-of select="." />
    </saxon:output>
</xsl:for-each>

</xsl:template>


</xsl:stylesheet>


Mich würde ein Performancevergleich zu csplit interessieren :) Ich verfüge leider nicht über solche Datenmengen.

cu
 
Zuletzt bearbeitet:
mit csplit hab ichs jetzt hinbekommen und es geht wirklich sehr schnell - dauert nur ca. 2 min.

mfg Willy
 
hast du mit xsl schon gearbeitet ? ...
also um deine datei zu filtern brauch ich nicht saxon °° ... ich kann dir jetzt keinen performance vergleich geben, aber ich würde die hand ins feuer legen, das xsl schneller als alles andere ist was du versuchen wirst :> aus dem grund ist xsl nämlich da ;)
 
@foexle
Es ging ja nicht um die Filterung, sondern um die Speicherung der Filterung in separaten Dateien. Bitte korrigiere mich, aber nach meinem aktuellen Wissen können das neben Saxon nur noch Xalan und XT.

cu
 

Ähnliche Themen

Hilfe für ein shell script

Zeilen löschen und ersetzen mit sed

bash: Fehlermeldung und Werte in Array sortieren?

Problem mit HSPA+ Modem Huawei E353 - Installation unmöglich?

[HowTo] Debian Installation mit Installer über SSH

Zurück
Oben