Jak wykonać XPath one-liners z shella?
Czy istnieje pakiet, dla Ubuntu i / lub CentOS, który ma narzędzie wiersza poleceń, które może wykonać XPath jednowierszową jak foo //element@attribute filename.xml
lub foo //element@attribute < filename.xml
i zwracać wyniki linia po linii?
Szukam czegoś, co pozwoli mi po prostu apt-get install foo
lub yum install foo
i wtedy po prostu działa out-of-the-box, bez opakowań i innych niezbędnych adaptacji.
Oto kilka przykładów rzeczy, które zbliżają się:
Nokogiri. Jeśli napiszę ten wrapper, mogę nazwać wrapper w sposób opisane powyżej:
#!/usr/bin/ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML:: XPath. Działa z tym opakowaniem:
#!/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
z metody XML:: XPath zwraca zbyt wiele szumów, -- NODE --
i attribute = "value"
.
xml_grep
from XML:: Twig nie może obsługiwać wyrażeń, które nie zwracają elementów, więc nie może być używany do wyodrębniania wartości atrybutów bez dalszego przetwarzania.
EDIT:
echo cat //element/@attribute | xmllint --shell filename.xml
zwraca szum podobny do xpath
.
xmllint --xpath //element/@attribute filename.xml
zwraca attribute = "value"
.
xmllint --xpath 'string(//element/@attribute)' filename.xml
zwraca to, co chcę, ale tylko na pierwszy mecz.
Dla innego rozwiązania prawie spełniającego pytanie, tutaj jest XSLT, który może być używany do oceny dowolnych wyrażeń XPath (wymaga dyn: evaluate wsparcie w procesorze XSLT):
<?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>
Run with xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml
.
13 answers
Powinieneś wypróbować te narzędzia:
-
xmlstarlet
: może edytować, wybierać, przekształcać... Nie jest instalowany domyślnie, xpath1 -
xmllint
: często instalowane domyślnie zlibxml2
, xpath1 (sprawdź mój wrapper , aby mieć rozdzielane nowe linie wyjścia -
xpath
: zainstalowany przez moduł PerlaXML::XPath
, xpath1 - Po zainstalowaniu modułu Perla, xpath1 (ograniczone użycie xpath)
-
xidel
: xpath3 -
saxon-lint
: mój własny projekt, wrapper over @ Michael Kay ' s Saxon-HE Java library, xpath3
xmllint
zawiera libxml2-utils
(może być używany jako interaktywna powłoka z przełącznikiem --shell
)
xmlstarlet
is xmlstarlet
.
xpath
pochodzi z modułu PerlaXML::Xpath
xml_grep
pochodzi z modułu PerlaXML::Twig
xidel
jest xidel
saxon-lint
using SaxonHE 9.6 ,XPath 3.x (+kompatybilność retro)
Ex:
xmllint --xpath '//element/@attribute' file.xml
xmlstarlet sel -t -v "//element/@attribute" file.xml
xpath -q -e '//element/@attribute' file.xml
xidel -se '//element/@attribute' file.xml
saxon-lint --xpath '//element/@attribute' file.xml
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-25 17:16:31
Jednym pakietem, który najprawdopodobniej zostanie zainstalowany w systemie jest już python-lxml
. Jeśli tak, jest to możliwe bez instalowania dodatkowego pakietu:
python -c "from lxml.etree import parse; from sys import stdin; print '\n'.join(parse(stdin).xpath('//element/@attribute'))"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 07:53:00
Możesz również spróbować mojego Xidel . Nie znajduje się w pakiecie w repozytorium, ale można go po prostu pobrać ze strony internetowej(nie ma zależności).
Ma prostą składnię dla tego zadania:
xidel filename.xml -e '//element/@attribute'
I jest to jedno z rzadkich z tych narzędzi, które obsługuje XPath 2.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-15 19:38:01
Saxon zrobi to nie tylko dla XPath 2.0, ale także dla XQuery 1.0 i (w wersji komercyjnej) 3.0. Nie jest to pakiet Linuksowy, ale plik jar. Składnia (którą można łatwo zawinąć w prosty skrypt) to
java net.sf.saxon.Query -s:source.xml -qs://element/attribute
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-17 16:55:38
W moim poszukiwaniu do zapytania maven pom.pliki xml, które uruchomiłem na to pytanie. Miałem jednak następujące ograniczenia:
- musi działać na różnych platformach.
- musi istnieć na wszystkich głównych dystrybucjach Linuksa bez dodatkowej instalacji modułu
- musi obsługiwać złożone pliki xml, takie jak maven pom.pliki xml
- składnia prosta
Próbowałem wielu z powyższych bez powodzenia:
- python lxml.etree nie jest częścią standardowego Pythona Dystrybucja
- xml.etree jest, ale nie obsługuje złożonego maven pom.pliki xml dobrze, nie wykopali wystarczająco głęboko
- python xml.etree nie obsługuje maven pom.pliki xml z nieznanego powodu
- xmllint również nie działa, core dumps często na ubuntu 12.04 "xmllint: using libxml version 20708"
Jedynym rozwiązaniem, na które natknąłem się, które jest stabilne, krótkie i działa na wielu platformach i które jest Dojrzałe, jest lib rexml wbudowany w ruby:
ruby -r rexml/document -e 'include REXML;
p XPath.first(Document.new($stdin), "/project/version/text()")' < pom.xml
Co zainspirowały mnie do znalezienia tego były następujące artykuły:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-25 14:20:50
Możesz być również zainteresowany xsh . Posiada interaktywny tryb, w którym możesz robić co chcesz z dokumentem:
open 1.xml ;
ls //element/@id ;
for //p[@class="first"] echo text() ;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 09:50:43
Odpowiedź Clacke ' a jest świetna, ale myślę, że działa tylko wtedy, gdy źródłem jest dobrze uformowany XML, a nie normalny HTML.
Więc zrobić to samo dla normalnej zawartości WWW-dokumenty HTML, które niekoniecznie są dobrze uformowane XML:
echo "<p>foo<div>bar</div><p>baz" | python -c "from sys import stdin; \
from lxml import html; \
print '\n'.join(html.tostring(node) for node in html.parse(stdin).xpath('//p'))"
I zamiast tego użyj html5lib (aby zapewnić takie samo parsowanie jak przeglądarki internetowe - ponieważ podobnie jak parsery przeglądarek, html5lib jest zgodny z wymaganiami parsowania w specyfikacji HTML).
echo "<p>foo<div>bar</div><p>baz" | python -c "from sys import stdin; \
import html5lib; from lxml import html; \
doc = html5lib.parse(stdin, treebuilder='lxml', namespaceHTMLElements=False); \
print '\n'.join(html.tostring(node) for node in doc.xpath('//p'))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:41
Oprócz XML:: XSH i XML:: XSH2 istnieją pewne grep
- podobne narzędzia do App::xml_grep2
oraz XML::Twig
(który obejmuje xml_grep
zamiast xml_grep2
). Mogą one być bardzo przydatne podczas pracy na dużych lub licznych plikach XML dla szybkich onelinerów lub celów Makefile
. XML::Twig
jest szczególnie miły do pracy dla perl
podejście Skryptowe, gdy chcesz trochę więcej przetwarzania niż $SHELL
i xmllint
xstlproc
oferta.
Schemat numeracji w nazwy aplikacji wskazują, że " 2 " wersje są nowszymi / późniejszymi wersjami zasadniczo tego samego narzędzia, które może wymagać późniejszych wersji innych modułów (lub samego perl
).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-05 16:37:31
Podobnie jak odpowiedzi Mike 'a i clacke' a, tutaj jest python one-liner (używając Pythona >= 2.5), aby uzyskać wersję kompilacji z pom.plik xml, który obejdzie fakt, że pom.pliki xml zwykle nie mają dtd lub domyślnej przestrzeni nazw, więc nie są dobrze uformowane w libxml:
python -c "import xml.etree.ElementTree as ET; \
print(ET.parse(open('pom.xml')).getroot().find('\
{http://maven.apache.org/POM/4.0.0}version').text)"
Przetestowany na Macu i Linuksie i nie wymaga żadnych dodatkowych pakietów do zainstalowania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-20 23:53:24
Należy wspomnieć, że sama nokogiri jest dostarczana z narzędziem wiersza poleceń, które powinno być zainstalowane z gem install nokogiri
.
Możesz znaleźć ten wpis na blogu przydatny .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-23 07:29:57
Wypróbowałem kilka narzędzi XPath z linii poleceń i kiedy zdałem sobie sprawę, że spędzam zbyt dużo czasu na googlowaniu i zastanawianiu się, jak one działają, więc napisałem najprostszy możliwy parser XPath w Pythonie, który zrobił to, czego potrzebowałem.
Poniższy skrypt pokazuje wartość ciągu znaków, jeśli wyrażenie XPath jest przetwarzane na łańcuch znaków, lub pokazuje cały podnód XML, jeśli wynikiem jest węzeł:
#!/usr/bin/env python
import sys
from lxml import etree
tree = etree.parse(sys.argv[1])
xpath = sys.argv[2]
for e in tree.xpath(xpath):
if isinstance(e, str):
print(e)
else:
print((e.text and e.text.strip()) or etree.tostring(e))
Używa lxml
- szybkiego parsera XML napisanego w C, który nie jest zawarty w standardowym Pythonie biblioteka. Zainstaluj go za pomocą pip install lxml
. Na Linuksie / OSX może wymagać prefiksu z sudo
.
Użycie:
python xmlcat.py file.xml "//mynode"
Lxml może również akceptować URL jako wejście:
python xmlcat.py http://example.com/file.xml "//mynode"
Wyodrębnij atrybut url pod węzłem enclosure tj. <enclosure url="http:...""..>)
:
python xmlcat.py xmlcat.py file.xml "//enclosure/@url"
Xpath w Google Chrome
Jako niepowiązana uwaga: jeśli przypadkiem chcesz uruchomić wyrażenie XPath ze znacznikami strony internetowej, możesz to zrobić bezpośrednio z narzędzi DevTools Chrome: kliknij prawym przyciskiem myszy stronę w Chrome > wybierz Sprawdź, a następnie w konsoli DevTools wklej wyrażenie XPath jako $x("//spam/eggs")
.
Pobierz wszystkich autorów na tej stronie:
$x("//*[@class='user-details']/a/text()")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-05 00:37:56
Ponieważ ten projekt jest najwyraźniej całkiem nowy, sprawdź https://github.com/jeffbr13/xq w przeciwieństwie do lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a, lxml-a]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-20 00:06:40
Oto jeden przypadek użycia xmlstarlet do wyodrębniania danych z zagnieżdżonych elementów elem1, elem2 do jednego wiersza tekstu z tego typu XML (pokazującego również, jak obsługiwać przestrzenie nazw):
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<mydoctype xmlns="http://xml-namespace-uri" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml-namespace-uri http://xsd-uri" format="20171221A" date="2018-05-15">
<elem1 time="0.586" length="10.586">
<elem2 value="cue-in" type="outro" />
</elem1>
</mydoctype>
Wyjście będzie
0.586 10.586 cue-in outro
W tym fragmencie,- m dopasowuje zagnieżdżone elem2, - v wypisuje wartości atrybutów (z wyrażeniami i względną adresacją), - o dosłowny tekst, - N dodaje nową linię:
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2' \
-v ../@time -o " " -v '../@time + ../@length' -o " " -v @value -o " " -v @type -n file.xml
Jeśli potrzeba więcej atrybutów z elem1, można to zrobić w ten sposób (również pokazując concat() Funkcja):
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2/..' \
-v 'concat(@time, " ", @time + @length, " ", ns:elem2/@value, " ", ns:elem2/@type)' -n file.xml
Zwróć uwagę na (IMO niepotrzebne) komplikacje z przestrzeniami nazw (NS, zadeklarowane przez-N), które sprawiły, że prawie zrezygnowałem z XPath i xmlstarlet i pisałem szybki konwerter ad-hoc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-17 11:24:55