Existe-t-il un package, pour Ubuntu et / ou CentOS, qui dispose d’un outil de ligne de commande capable d’exécuter un one-liner XPath comme foo //element@atsortingbute filename.xml
ou foo //element@atsortingbute < filename.xml
et renvoyer les résultats ligne par ligne?
Je suis à la recherche de quelque chose qui me permettrait de simplement apt-get install foo
ou yum install foo
, puis de travailler immédiatement, sans encapsulation ou autre adaptation nécessaire.
Voici quelques exemples de choses qui se rapprochent:
Nokogiri. Si j’écris ce wrapper, je pourrais appeler le wrapper de la manière décrite ci-dessus:
#!/usr/bin/ruby require 'nokogiri' Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row| puts row end
XML :: XPath. Fonctionnerait avec ce wrapper:
#!/usr/bin/perl use ssortingct; 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
de XML :: XPath renvoie trop de bruit, -- NODE --
et atsortingbute = "value"
.
xml_grep
from XML :: Twig ne peut pas gérer les expressions qui ne renvoient pas d’éléments, et ne peuvent donc pas être utilisées pour extraire des valeurs d’atsortingbut sans traitement supplémentaire.
MODIFIER:
echo cat //element/@atsortingbute | xmllint --shell filename.xml
echo cat //element/@atsortingbute | xmllint --shell filename.xml
renvoie un bruit similaire à xpath
.
xmllint --xpath //element/@atsortingbute filename.xml
retourne atsortingbute = "value"
.
xmllint --xpath 'ssortingng(//element/@atsortingbute)' filename.xml
renvoie ce que je veux, mais uniquement pour la première correspondance.
Pour une autre solution presque satisfaisante pour la question, voici un XSLT qui peut être utilisé pour évaluer des expressions XPath arbitraires (requirejs dyn: évaluer le support dans le processeur XSLT):
Exécutez avec xsltproc --ssortingngparam pattern //element/@atsortingbute --ssortingngparam value . arbitrary-xpath.xslt filename.xml
xsltproc --ssortingngparam pattern //element/@atsortingbute --ssortingngparam value . arbitrary-xpath.xslt filename.xml
.
Vous devriez essayer ces outils:
xmlstarlet
: peut éditer, sélectionner, transformer … Non installé par défaut, xpath1 xmllint
: souvent installé par défaut avec libxml2
, xpath1 (vérifiez que mon wrapper a des sorties délimitées par des nouvelles lignes) xpath
: installé via le module XML::XPath
perl XML::XPath
, xpath1 xml_grep
: installé via le module XML::Twig
perl XML::Twig
, xpath1 (utilisation limitée de xpath) xidel
: xpath3 saxon-lint
: mon propre projet, enveloppe la bibliothèque Java Saxon-HE de @Michael Kay, xpath3 xmllint
est fourni avec libxml2-utils
(peut être utilisé comme shell interactif avec le commutateur --shell
)
xmlstarlet
est xmlstarlet
.
xpath
est fourni avec le module XML::Xpath
perl XML::Xpath
xml_grep
est livré avec le module XML::Twig
perl XML::Twig
xidel
est xidel
saxon-lint
utilisant SaxonHE 9.6 , XPath 3.x (+ compatibilité rétro)
Ex:
xmllint --xpath '//element/@atsortingbute' file.xml xmlstarlet sel -t -v "//element/@atsortingbute" file.xml xpath -q -e '//element/@atsortingbute' file.xml xidel -se '//element/@atsortingbute' file.xml saxon-lint --xpath '//element/@atsortingbute' file.xml
.
python-lxml
est un paquet très susceptible d’être installé sur un système. Si c’est le cas, cela est possible sans installer de paquet supplémentaire:
python -c "from lxml.etree import parse; from sys import stdin; print '\n'.join(parse(stdin).xpath('//element/@atsortingbute'))"
Vous pouvez aussi essayer mon Xidel . Il ne se trouve pas dans un package du référentiel, mais vous pouvez simplement le télécharger depuis la page Web (il ne comporte aucune dépendance).
Il a une syntaxe simple pour cette tâche:
xidel filename.xml -e '//element/@atsortingbute'
Et c’est l’un des rares de ces outils qui supporte XPath 2.
Saxon le fera non seulement pour XPath 2.0, mais aussi pour XQuery 1.0 et (dans la version commerciale) 3.0. Il ne s’agit pas d’un package Linux, mais d’un fichier jar. La syntaxe (que vous pouvez facilement envelopper dans un simple script) est
java net.sf.saxon.Query -s:source.xml -qs://element/atsortingbute
Dans ma recherche pour interroger les fichiers maven pom.xml, j’ai rencontré cette question. Cependant, j’avais les limitations suivantes:
J’ai essayé plusieurs des solutions ci-dessus sans succès:
La seule solution que j’ai trouvée qui soit stable, courte et fonctionne sur de nombreuses plates-formes et qui est mature est la bibliothèque intégrée rexml de ruby:
ruby -r rexml/document -e 'include REXML; p XPath.first(Document.new($stdin), "/project/version/text()")' < pom.xml
Ce qui m'a inspiré pour trouver celui-ci, ce sont les articles suivants:
Vous pourriez également être intéressé par xsh . Il comporte un mode interactif où vous pouvez faire ce que vous voulez avec le document:
open 1.xml ; ls //element/@id ; for //p[@class="first"] echo text() ;
La réponse de clacke est géniale, mais je pense que cela ne fonctionne que si votre source est du XML bien formé, pas du HTML normal.
Donc, pour faire la même chose pour le contenu Web normal – les documents HTML qui ne sont pas nécessairement des fichiers XML bien formés:
echo "foo
barbaz" | python -c "from sys import stdin; \ from lxml import html; \ print '\n'.join(html.tossortingng(node) for node in html.parse(stdin).xpath('//p'))"
Et à la place, utilisez html5lib (pour vous assurer d’avoir le même comportement d’parsing que les navigateurs Web, car, comme les parsingurs de navigateur, html5lib est conforme aux exigences d’parsing dans la spécification HTML).
echo "foo
barbaz" | python -c "from sys import stdin; \ import html5lib; from lxml import html; \ doc = html5lib.parse(stdin, treebuilder='lxml', namespaceHTMLElements=False); \ print '\n'.join(html.tossortingng(node) for node in doc.xpath('//p'))
En plus de XML :: XSH et XML :: XSH2, il existe des utilitaires similaires à grep
comme App::xml_grep2
et XML::Twig
(qui inclut xml_grep
plutôt que xml_grep2
). Celles-ci peuvent être très utiles lorsque vous travaillez sur un grand nombre de fichiers XML ou sur de nombreux oneliners rapides ou des cibles Makefile
. XML::Twig
est particulièrement xmllint
pour une approche de script perl
lorsque vous souhaitez un traitement un peu plus important que votre $SHELL
et xmllint
xstlproc
.
Le schéma de numérotation dans les noms d’application indique que les versions “2” sont des versions plus récentes ou plus récentes du même outil, ce qui peut nécessiter des versions ultérieures d’autres modules (ou de perl
lui-même).
Semblable aux réponses de Mike et de clacke, voici le one-liner de python (utilisant python> = 2.5) pour obtenir la version de compilation à partir d’un fichier pom.xml contournant le fait que les fichiers pom.xml n’ont normalement pas de dtd ou espace de noms par défaut, donc ne semble pas bien formé à 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)"
Testé sur Mac et Linux, ne nécessite aucun paquet supplémentaire pour être installé.
Il convient de mentionner que nokogiri lui-même est livré avec un outil de ligne de commande, qui devrait être installé avec gem install nokogiri
.
Vous pourriez trouver ce post de blog utile .
J’ai essayé quelques utilitaires XPath en ligne de commande et quand j’ai réalisé que je passais trop de temps à googler et à comprendre comment ils fonctionnaient, j’ai donc écrit l’parsingur XPath le plus simple possible en Python.
Le script ci-dessous montre la valeur de la chaîne si l’expression XPath évalue une chaîne ou affiche l’intégralité du sous-noeud XML si le résultat est un noeud:
#!/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.ssortingp()) or etree.tossortingng(e))
Il utilise lxml
– un parsingur XML rapide écrit en C qui n’est pas inclus dans la bibliothèque python standard. Installez-le avec pip install lxml
. Sous Linux / OSX, il peut être nécessaire de préfixer sudo
.
Usage:
python xmlcat.py file.xml "//mynode"
lxml peut également accepter une URL en entrée:
python xmlcat.py http://example.com/file.xml "//mynode"
Extrayez l’atsortingbut url sous un noeud de boîtier, à savoir
:
python xmlcat.py xmlcat.py file.xml "//enclosure/@url"
Remarque: Si par hasard vous souhaitez exécuter une expression XPath sur le balisage d’une page Web, vous pouvez le faire directement depuis Chrome devtools: cliquez avec le bouton droit de la souris sur Chrome> sélectionnez Inspecter, puis dans les DevTools. console collez votre expression XPath sous la forme $x("//spam/eggs")
.
Obtenez tous les auteurs sur cette page:
$x("//*[@class='user-details']/a/text()")
Étant donné que ce projet est apparemment assez récent, consultez https://github.com/jeffbr13/xq , semble être un wrapper autour de lxml
, mais c’est tout ce dont vous avez vraiment besoin (et des solutions ad hoc utilisant lxml dans d’autres réponses également) )
Voici un cas d’utilisation de xmlstarlet pour extraire des données d’éléments nesteds elem1, elem2 sur une ligne de texte de ce type de XML (montrant également comment gérer les espaces de noms):
La sortie sera
0.586 10.586 cue-in outro
Dans cet extrait de code, -m correspond aux valeurs d’atsortingbuts nestedes elem2, -v (avec expressions et adressage relatif), -o texte littéral, -n ajoute une nouvelle ligne:
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
Si plus d’atsortingbuts d’elem1 sont nécessaires, on peut le faire comme ça (montrant également la fonction concat ()):
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
Notez la complication (inutile de l’IMO) avec les espaces de noms (ns, déclarés avec -N), qui me laissait presque tomber sur xpath et xmlstarlet, et d’écrire un convertisseur ad hoc rapide.