Gibt es ein Paket für Ubuntu und / oder CentOS, das über ein Befehlszeilentool verfügt, mit dem ein XPath-Einzeiler wie foo //element@attribute filename.xml
oder ausgeführt foo //element@attribute < filename.xml
und die Ergebnisse zeilenweise zurückgegeben werden können?
Ich bin auf der Suche nach etwas, das es mir ermöglicht, einfach apt-get install foo
oder yum install foo
sofort zu arbeiten, ohne dass Wrapper oder andere Anpassungen erforderlich sind.
Hier sind einige Beispiele für Dinge, die nahe kommen:
Nokogiri. Wenn ich diesen Wrapper schreibe, könnte ich den Wrapper wie oben beschrieben aufrufen:
#!/usr/bin/ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML :: XPath. Würde mit diesem Wrapper funktionieren:
#!/usr/bin/perl
use strict;
use warnings;
use XML::XPath;
my $root = XML::XPath->new(ioref => 'STDIN');
for my $node ($root->find($ARGV[0])->get_nodelist) {
print($node->getData, "\n");
}
xpath
von XML :: XPath gibt zu viel Rauschen zurück, -- NODE --
und attribute = "value"
.
xml_grep
from XML :: Twig kann keine Ausdrücke verarbeiten, die keine Elemente zurückgeben, und kann daher nicht zum Extrahieren von Attributwerten ohne weitere Verarbeitung verwendet werden.
BEARBEITEN:
echo cat //element/@attribute | xmllint --shell filename.xml
gibt Rauschen ähnlich wie zurück xpath
.
xmllint --xpath //element/@attribute filename.xml
kehrt zurück attribute = "value"
.
xmllint --xpath 'string(//element/@attribute)' filename.xml
gibt zurück, was ich will, aber nur für das erste Match.
Für eine andere Lösung, die die Frage fast befriedigt, ist hier ein XSLT, das zum Auswerten beliebiger XPath-Ausdrücke verwendet werden kann (erfordert dyn: evaluiere die Unterstützung im XSLT-Prozessor):
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn">
<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
<xsl:template match="/">
<xsl:for-each select="dyn:evaluate($pattern)">
<xsl:value-of select="dyn:evaluate($value)"/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Laufen Sie mit xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml
.
quelle
xpath
auf STDERR und nicht auf STDOUT ist.Antworten:
Sie sollten diese Tools ausprobieren:
xmlstarlet
: kann bearbeiten, auswählen, transformieren ... Nicht standardmäßig installiert, xpath1xmllint
: Häufig standardmäßig installiert mitlibxml2-utils
, xpath1 (check out my Wrapper haben--xpath
Schalter begrenzt die Ausgabe auf sehr alten Versionen und neue Zeilen (v <2.9.9)xpath
: installiert über das Perl-ModulXML::XPath
xpath1xml_grep
: installiert über das Perl-ModulXML::Twig
xpath1 (eingeschränkte xpath-Nutzung)xidel
: xpath3saxon-lint
: Mein eigenes Projekt, Wrapper über @Michael Kays Saxon-HE Java-Bibliothek, xpath3xmllint
kommt mitlibxml2-utils
(kann als interaktive Shell mit dem--shell
Schalter verwendet werden)xmlstarlet
istxmlstarlet
.xpath
kommt mit Perl-ModulXML::Xpath
xml_grep
kommt mit Perl-ModulXML::Twig
xidel
istxidel
saxon-lint
mit SaxonHE 9.6 , XPath 3.x (+ Retro-Kompatibilität)Ex :
.
quelle
xmlstarlet sel -T -t -m '//element/@attribute' -v '.' -n filename.xml
macht genau das was ich will!xmllint
unterstützen kein Befehlszeilenargument--xpath
, die meisten scheinen dies jedoch zu unterstützen--shell
. Etwas schmutzigere Ausgabe, aber dennoch nützlich beim Binden.sel -t -m ... -v ...
Beispiel auf dieser Seite: arstechnica.com/information-technology/2005 / 11 / linux-20051115/2 , der alle bis auf den letzten Knoten abgleichen und diesen für den Wertausdruck wie meinen Anwendungsfall speichern kann, kann ich immer noch nichtSie können auch meinen Xidel ausprobieren . Es befindet sich nicht in einem Paket im Repository, aber Sie können es einfach von der Webseite herunterladen (es hat keine Abhängigkeiten).
Es hat eine einfache Syntax für diese Aufgabe:
Und es ist eines der seltenen dieser Tools, das XPath 2 unterstützt.
quelle
Ein Paket, das sehr wahrscheinlich bereits auf einem System installiert ist, ist
python-lxml
. Wenn ja, ist dies möglich, ohne ein zusätzliches Paket zu installieren:quelle
stdin
. Dadurch entfällt die Notwendigkeit , einschließlichopen()
undclose()
in ein bereits recht lang Einzeiler. Um eine Datei zu analysieren, führen Sie sie einfach auspython -c "from lxml.etree import parse; from sys import stdin; print '\n'.join(parse(stdin).xpath('//element/@attribute'))" < my_file.xml
und lassen Sie Ihre Shell die Datei suchen, öffnen und schließen.Bei meiner Suche nach maven pom.xml-Dateien bin ich auf diese Frage gestoßen. Ich hatte jedoch die folgenden Einschränkungen:
Ich habe viele der oben genannten erfolglos ausprobiert:
Die Lösung, auf die ich gestoßen bin, die stabil, kurz und auf vielen Plattformen funktioniert und die ausgereift ist, ist die in Ruby integrierte rexml lib:
Was mich dazu inspirierte, diesen zu finden, waren die folgenden Artikel:
quelle
xmlstarlet
die akzeptierte Antwort bei, weil sie meinen umfassenderen Kriterien entspricht und wirklich ordentlich ist . Aber ich werde wahrscheinlich von Zeit zu Zeit Verwendung für Ihre Lösung haben.puts
anstattp
im Ruby-Befehl zu verwenden.Saxon wird dies nicht nur für XPath 2.0 tun, sondern auch für XQuery 1.0 und (in der kommerziellen Version) 3.0. Es kommt nicht als Linux-Paket, sondern als JAR-Datei. Syntax (die Sie leicht in ein einfaches Skript einbinden können) ist
2020 UPDATE
Saxon 10.0 enthält das Gizmo-Tool, das interaktiv oder stapelweise über die Befehlszeile verwendet werden kann. Beispielsweise
quelle
libsaxonb-java
, aber wenn ich laufe,saxonb-xquery -qs://element/@attribute -s:filename.xml
bekomme ich dasSENR0001: Cannot serialize a free-standing attribute node
gleiche Problem wie zBxml_grep
.-qs
:'-qs:declare namespace mets="http://www.loc.gov/METS/";/mets:mets/mets:dmdSec'
Sie könnten auch an xsh interessiert sein . Es verfügt über einen interaktiven Modus, in dem Sie mit dem Dokument beliebig viel tun können:
quelle
cpan XML::XSH2
.cpan XML::XSH2
nichts installiert werden kann.Die Antwort von clacke ist großartig, aber ich denke, sie funktioniert nur, wenn Ihre Quelle wohlgeformtes XML ist, nicht normales HTML.
Um dasselbe für normale Webinhalte zu tun - HTML-Dokumente, die nicht unbedingt gut geformtes XML sind:
Verwenden Sie stattdessen html5lib (um sicherzustellen, dass Sie dasselbe Parsing-Verhalten wie Webbrowser erhalten, da html5lib wie Browser-Parser den Parsing-Anforderungen in der HTML-Spezifikation entspricht).
quelle
Ähnlich wie bei Mike und Clacke gibt es hier den Python-Einzeiler (mit Python> = 2.5), um die Build-Version aus einer pom.xml-Datei abzurufen, die die Tatsache umgeht, dass pom.xml-Dateien normalerweise kein dtd oder haben Standard-Namespace, daher erscheint libxml nicht wohlgeformt:
Getestet auf Mac und Linux und erfordert keine Installation zusätzlicher Pakete.
quelle
lxml
nochxmllint
noch Ruby. Im Geiste des Formats in meiner eigenen Antwort schrieb ich es wiepython3 -c "from xml.etree.ElementTree import parse; from sys import stdin; print(parse(stdin).find('.//element[subelement=\"value\"]/othersubelement').text)" <<< "$variable_containing_xml"
in Bash..getroot()
scheint nicht notwendig.Zusätzlich zu XML :: XSH und XML :: XSH2 gibt es einige
grep
ähnliche Dienstprogramme, die alsApp::xml_grep2
und saugenXML::Twig
(wasxml_grep
eher beinhaltet alsxml_grep2
). Diese können sehr nützlich sein, wenn Sie an einer großen oder zahlreichen XML-Dateien für schnelle Oneliner oderMakefile
Ziele arbeiten.XML::Twig
Es ist besonders schön, mit ihm für einenperl
Scripting-Ansatz zu arbeiten, wenn Sie etwas mehr Verarbeitung als Ihre$SHELL
und Ihrxmllint
xstlproc
Angebot wünschen .Das Nummerierungsschema in den Anwendungsnamen gibt an, dass die "2" -Versionen neuere / spätere Versionen im Wesentlichen desselben Tools sind, für die möglicherweise spätere Versionen anderer Module (oder von sich
perl
selbst) erforderlich sind .quelle
xml_grep2 -t //element@attribute filename.xml
funktioniert und macht das, was ich erwarte (xml_grep --root //element@attribute --text_only filename.xml
immer noch nicht, gibt einen Fehler "nicht erkannter Ausdruck" zurück). Toll!xml_grep --pretty_print --root '//element[@attribute]' --text_only filename.xml
? Ich bin mir nicht sicher, was dort vor sich geht oder was XPath[]
in diesem Fall sagt , aber das Umgeben eines@attribute
mit eckigen Klammern funktioniert fürxml_grep
undxml_grep2
.//element/@attribute
nicht//element@attribute
. Ich kann es anscheinend nicht bearbeiten, aber lasse es dort, anstatt es zu löschen + zu ersetzen, um den Verlauf dieser Diskussion nicht zu verwirren.//element[@attribute]
Wählt Elemente vom Typ auselement
, die ein Attribut habenattribute
. Ich möchte nicht das Element, nur das Attribut.<element attribute='foo'/>
sollte mir gebenfoo
, nicht das volle<element attribute='foo'/>
.--text_only
in diesem Zusammenhang gibt mir die leere Zeichenfolge bei einem Element wie<element attribute='foo'/>
ohne Textknoten.Es ist zu erwähnen, dass Nokia selbst mit einem Befehlszeilen-Tool geliefert wird, mit dem installiert werden sollte
gem install nokogiri
.Möglicherweise finden Sie diesen Blog-Beitrag hilfreich .
quelle
Ich habe ein paar Befehlszeilen-XPath-Dienstprogramme ausprobiert und als mir klar wurde, dass ich zu viel Zeit damit verbringe, zu googeln und herauszufinden, wie sie funktionieren, habe ich den einfachsten XPath-Parser in Python geschrieben, der genau das tat, was ich brauchte.
Das folgende Skript zeigt den Zeichenfolgenwert an, wenn der XPath-Ausdruck eine Zeichenfolge ergibt, oder den gesamten XML-Unterknoten, wenn das Ergebnis ein Knoten ist:
Es verwendet
lxml
- einen schnellen XML-Parser, der in C geschrieben ist und nicht in der Standard-Python-Bibliothek enthalten ist. Installieren Sie es mitpip install lxml
. Unter Linux / OSX muss möglicherweise ein Präfix mit verwendet werdensudo
.Verwendung:
lxml kann auch eine URL als Eingabe akzeptieren:
Extrahieren Sie das URL-Attribut unter einem Gehäuseknoten, dh
<enclosure url="http:...""..>)
:Xpath in Google Chrome
Als nicht verwandte Randnotiz: Wenn Sie zufällig einen XPath-Ausdruck für das Markup einer Webseite ausführen möchten, können Sie dies direkt in den Chrome-Devtools tun: Klicken Sie mit der rechten Maustaste auf die Seite in Chrome, wählen Sie Inspizieren und dann in den DevTools Konsole fügen Sie Ihren XPath-Ausdruck ein als
$x("//spam/eggs")
.Holen Sie sich alle Autoren auf dieser Seite:
quelle
lxml
wurde bereits in zwei anderen Antworten Jahre vor Ihrer erwähnt.Hier ist ein Anwendungsfall für xmlstarlet, um Daten aus verschachtelten Elementen elem1, elem2 in eine Textzeile aus diesem XML-Typ zu extrahieren (und zeigt auch, wie mit Namespaces umgegangen wird):
Die Ausgabe wird sein
In diesem Snippet stimmt -m mit dem verschachtelten elem2 überein, -v gibt Attributwerte aus (mit Ausdrücken und relativer Adressierung), -o Literaltext, -n fügt eine neue Zeile hinzu:
Wenn mehr Attribute von elem1 benötigt werden, können Sie dies folgendermaßen tun (wobei auch die Funktion concat () angezeigt wird):
Beachten Sie die (IMO unnötig) Komplikation mit Namespaces (ns, deklariert mit -N), bei der ich xpath und xmlstarlet fast aufgegeben und einen schnellen Ad-hoc-Konverter geschrieben habe.
quelle
Mein Python-Skript xgrep.py macht genau das. Um nach allen Attributen
attribute
von Elementenelement
in Dateien zu suchenfilename.xml ...
, führen Sie diese wie folgt aus:Es gibt verschiedene Schalter zum Steuern der Ausgabe, z. B.
-c
zum Zählen von Übereinstimmungen,-i
zum Einrücken der übereinstimmenden Teile und-l
zum Ausgeben von Dateinamen.Das Skript ist nicht als Debian- oder Ubuntu-Paket verfügbar, aber alle seine Abhängigkeiten sind.
quelle
Da dieses Projekt anscheinend ziemlich neu ist, lesen Sie https://github.com/jeffbr13/xq , es scheint ein Wrapper zu sein
lxml
, aber das ist alles, was Sie wirklich brauchen (und Ad-hoc-Lösungen mit lxml auch in anderen Antworten zu veröffentlichen).quelle
Ich war mit Python-Einzeilern für HTML XPath-Abfragen nicht zufrieden, also habe ich meine eigenen geschrieben. Angenommen, Sie haben das
python-lxml
Paket installiert oder ausgeführtpip install --user lxml
:Sobald Sie es haben, können Sie es wie in diesem Beispiel verwenden:
quelle
Installieren Sie die BaseX- Datenbank und verwenden Sie dann den "Standalone-Befehlszeilenmodus" wie folgt :
basex -i - //element@attribute < filename.xml
oder
basex -i filename.xml //element@attribute
Die Abfragesprache ist eigentlich XQuery (3.0), nicht XPath. Da XQuery jedoch eine Obermenge von XPath ist, können Sie XPath-Abfragen verwenden, ohne es jemals zu bemerken.
quelle