XML mit Unix-Terminal analysieren
Frage
Manchmal muss ich schnell beliebige Daten aus XML-Dateien extrahieren, um sie in ein CSV-Format umzuwandeln.Was sind Ihre Best Practices dafür im Unix-Terminal?Ich würde mich über einige Codebeispiele freuen. Wie kann ich beispielsweise das folgende Problem lösen?
Beispiel-XML-Eingabe:
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
Meine gewünschte CSV-Ausgabe:
Foo,
Bar,
Lösung
Wenn Sie nur die Namensattribute eines Elements benötigen, finden Sie hier eine schnelle, aber unvollständige Lösung.
(Ihr Beispieltext befindet sich in der Datei Beispiel)
Grep "Name" Beispiel | Schnitt -d "" "-F2,2 | xargs -i {} echo" {}, "
Andere Tipps
Peters Antwort ist korrekt, aber es wird ein nachgestellter Zeilenvorschub ausgegeben.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="root">
<xsl:for-each select="myel">
<xsl:value-of select="@name"/>
<xsl:text>,</xsl:text>
<xsl:if test="not(position() = last())">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Führen Sie einfach z.B.
xsltproc stylesheet.xsl source.xml
um die CSV-Ergebnisse in die Standardausgabe zu generieren.
Verwenden Sie einen Befehlszeilen-XSLT-Prozessor wie z xsltproc, sächsisch oder xalan um das XML zu analysieren und CSV zu generieren.Hier ist ein Beispiel, was in Ihrem Fall das Stylesheet ist:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="root">
<xsl:apply-templates select="myel"/>
</xsl:template>
<xsl:template match="myel">
<xsl:for-each select="@*">
<xsl:value-of select="."/>
<xsl:value-of select="','"/>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
XMLStarlet ist ein Befehlszeilen -Toolkit zum Abfragen/Bearbeiten/Überprüfen/Überprüfen/Transformationen von XML -Dokumenten (weitere Informationen finden Sie unter http://xmlstar.sourceforge.net/)
Es müssen keine Dateien geschrieben werden. Leiten Sie Ihre Datei einfach an xmlstarlet weiter und wenden Sie einen XPath-Filter an.
cat file.xml | xml sel -t -m 'xpathExpression' -v 'elemName' 'literal' -v 'elname' -n
-M Expression -v -Wert '' beinhaltete buchstäbliche -n Newline
Für Ihren XPath wäre der XPath -Ausdruck // myel/@name, der die beiden Attributwerte angibt.
Sehr praktisches Werkzeug.
Hier ist ein kleines Ruby-Skript, das das tut genau was Ihre Frage verlangt (ziehen Sie ein Attribut namens „name“ aus Elementen namens „myel“).Sollte leicht zu verallgemeinern sein
#!/usr/bin/ruby -w
require 'rexml/document'
xml = REXML::Document.new(File.open(ARGV[0].to_s))
xml.elements.each("//myel") { |el| puts "#{el.attributes['name']}," if el.attributes['name'] }
Bei der Beantwortung der ursprünglichen Frage wird davon ausgegangen, dass die XML-Datei „test.xml“ lautet und Folgendes enthält:
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}'
Ihre Testdatei befindet sich in test.xml.
sed -n 's/^\s`*`<myel\s`*`name="\([^"]`*`\)".`*`$/\1,/p' test.xml
Es hat seine Tücken, zum Beispiel wenn es nicht strikt gegeben ist, dass jeder myel steht in einer Zeile, Sie müssen zuerst die XML-Datei „normalisieren“ (also jede myel steht in einer separaten Zeile)