¿Existe un paquete para Ubuntu y / o CentOS que tenga una herramienta de línea de comandos que pueda ejecutar un XPath de una línea como foo //element@attribute filename.xml
o foo //element@attribute < filename.xml
y devolver los resultados línea por línea?
Estoy buscando algo que me permita simplemente apt-get install foo
o yum install foo
simplemente funcionar de inmediato, sin envoltorios u otra adaptación necesaria.
Aquí hay algunos ejemplos de cosas que se acercan:
Nokogiri. Si escribo este contenedor, podría llamar al contenedor de la manera descrita anteriormente:
#!/usr/bin/ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML :: XPath. Funcionaría con este contenedor:
#!/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
de XML :: XPath devuelve demasiado ruido -- NODE --
y attribute = "value"
.
xml_grep
from XML :: Twig no puede manejar expresiones que no devuelven elementos, por lo que no se puede usar para extraer valores de atributos sin más procesamiento.
EDITAR:
echo cat //element/@attribute | xmllint --shell filename.xml
devuelve ruido similar a xpath
.
xmllint --xpath //element/@attribute filename.xml
vuelve attribute = "value"
.
xmllint --xpath 'string(//element/@attribute)' filename.xml
devuelve lo que quiero, pero solo para el primer partido.
Para otra solución que casi satisface la pregunta, aquí hay un XSLT que se puede usar para evaluar expresiones XPath arbitrarias (requiere dyn: evaluar el soporte en el procesador 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>
Corre con xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml
.
fuente
xpath
está en STDERR y no en STDOUT.Respuestas:
Deberías probar estas herramientas:
xmlstarlet
: puede editar, seleccionar, transformar ... No está instalado de forma predeterminada, xpath1xmllint
: a menudo se instala de forma predeterminada conlibxml2-utils
xpath1 (compruebe que mi contenedor tenga--xpath
activadas las versiones muy antiguas y la salida delimitada por líneas nuevas (v <2.9.9)xpath
: instalado a través del módulo de perlXML::XPath
, xpath1xml_grep
: instalado a través del módulo de PerlXML::Twig
, xpath1 (uso limitado de xpath)xidel
: xpath3saxon-lint
: mi propio proyecto, envoltorio sobre la biblioteca Java de Saxon-HE de @Michael Kay, xpath3xmllint
viene conlibxml2-utils
(se puede usar como shell interactivo con el--shell
interruptor)xmlstarlet
esxmlstarlet
.xpath
viene con el módulo de perlXML::Xpath
xml_grep
viene con el módulo de perlXML::Twig
xidel
esxidel
saxon-lint
utilizando SaxonHE 9.6 , XPath 3.x (+ compatibilidad retro)Ej:
.
fuente
xmlstarlet sel -T -t -m '//element/@attribute' -v '.' -n filename.xml
hace exactamente lo que quiero!xmllint
no admiten el argumento de la línea de comandos--xpath
, pero la mayoría parece admitirlo--shell
. Salida ligeramente más sucia, pero aún útil en un aprieto.sel -t -m ... -v ...
ejemplo de esta página: arstechnica.com/information-technology/2005 / 11 / linux-20051115/2 , haciendo coincidir todo menos el último nodo y guardando ese para la expresión de valor como mi caso de uso, todavía parece que no puedo obtenerlo, solo obtengo un resultado en blanco ...También puedes probar mi Xidel . No está en un paquete en el repositorio, pero puede descargarlo de la página web (no tiene dependencias).
Tiene una sintaxis simple para esta tarea:
Y es una de las pocas herramientas que admite XPath 2.
fuente
Un paquete que es muy probable que ya esté instalado en un sistema ya lo es
python-lxml
. Si es así, esto es posible sin instalar ningún paquete adicional:fuente
stdin
. Eso elimina la necesidad de incluiropen()
yclose()
en una línea bastante larga. Para analizar un archivo simplemente ejecutepython -c "from lxml.etree import parse; from sys import stdin; print '\n'.join(parse(stdin).xpath('//element/@attribute'))" < my_file.xml
y deje que su shell maneje la búsqueda, apertura y cierre del archivo.En mi búsqueda para consultar archivos maven pom.xml, me encontré con esta pregunta. Sin embargo, tenía las siguientes limitaciones:
He intentado muchas de las anteriores sin éxito:
La solución con la que me he encontrado que es estable, corta y que funciona en muchas plataformas y que es madura es el rexml lib incorporado en ruby:
Lo que me inspiró a encontrar este fue los siguientes artículos:
fuente
xmlstarlet
como la respuesta aceptada, porque se ajusta a mis criterios más amplios y es realmente ordenada . Pero probablemente tendré uso para su solución de vez en cuando.puts
lugar dep
en el comando Ruby.Saxon hará esto no solo para XPath 2.0, sino también para XQuery 1.0 y (en la versión comercial) 3.0. No viene como un paquete de Linux, sino como un archivo jar. La sintaxis (que puede ajustarse fácilmente en un script simple) es
ACTUALIZACIÓN 2020
Saxon 10.0 incluye la herramienta Gizmo, que se puede utilizar de forma interactiva o por lotes desde la línea de comandos. Por ejemplo
fuente
libsaxonb-java
, pero si ejecutosaxonb-xquery -qs://element/@attribute -s:filename.xml
me sale elSENR0001: Cannot serialize a free-standing attribute node
mismo problema que con egxml_grep
.-qs
desea:'-qs:declare namespace mets="http://www.loc.gov/METS/";/mets:mets/mets:dmdSec'
También te puede interesar xsh . Cuenta con un modo interactivo donde puede hacer lo que quiera con el documento:
fuente
cpan XML::XSH2
.cpan XML::XSH2
no puede instalar nada.La respuesta de Clacke es excelente, pero creo que solo funciona si su fuente es XML bien formado, no HTML normal.
Entonces, para hacer lo mismo con el contenido web normal: documentos HTML que no son necesariamente XML bien formado:
Y en su lugar, use html5lib (para asegurarse de obtener el mismo comportamiento de análisis que los navegadores web, porque, al igual que los analizadores de navegador, html5lib cumple con los requisitos de análisis de la especificación HTML).
fuente
Al igual que las respuestas de Mike y Clacke, aquí está la línea única de Python (usando python> = 2.5) para obtener la versión de compilación de un archivo pom.xml que evita el hecho de que los archivos pom.xml normalmente no tienen un dtd o espacio de nombres predeterminado, por lo que no parece estar bien formado para libxml:
Probado en Mac y Linux, y no requiere la instalación de ningún paquete adicional.
fuente
lxml
nixmllint
ni siquiera Ruby. En el espíritu del formato en mi propia respuesta , lo escribí comopython3 -c "from xml.etree.ElementTree import parse; from sys import stdin; print(parse(stdin).find('.//element[subelement=\"value\"]/othersubelement').text)" <<< "$variable_containing_xml"
en bash..getroot()
no parece necesarioAdemás de XML :: XSH y XML :: XSH2, existen algunas
grep
utilidades similares que succionan comoApp::xml_grep2
yXML::Twig
(que incluye enxml_grep
lugar dexml_grep2
). Estos pueden ser bastante útiles cuando se trabaja en archivos XML grandes o numerosos para líneas rápidas uMakefile
objetivos.XML::Twig
es especialmente agradable trabajar con unperl
enfoque de secuencias de comandos cuando desea un poco más de procesamiento que el suyo$SHELL
y laxmllint
xstlproc
oferta.El esquema de numeración en los nombres de las aplicaciones indica que las versiones "2" son versiones más nuevas / posteriores de esencialmente la misma herramienta que puede requerir versiones posteriores de otros módulos (o de
perl
sí misma).fuente
xml_grep2 -t //element@attribute filename.xml
funciona y hace lo que espero (xml_grep --root //element@attribute --text_only filename.xml
todavía no, devuelve un error de "expresión no reconocida"). ¡Excelente!xml_grep --pretty_print --root '//element[@attribute]' --text_only filename.xml
? No estoy seguro de lo que está sucediendo allí o de lo que XPath dice[]
en este caso, pero rodearlo@attribute
con corchetes funciona paraxml_grep
yxml_grep2
.//element/@attribute
no//element@attribute
. Aparentemente no puedo editarlo, pero dejarlo allí en lugar de eliminar + reemplazar para no confundir el historial de esta discusión.//element[@attribute]
selecciona elementos de tipoelement
que tienen un atributoattribute
. No quiero el elemento, solo el atributo.<element attribute='foo'/>
debería darmefoo
, no el completo<element attribute='foo'/>
.--text_only
en ese contexto me da la cadena vacía en el caso de un elemento como<element attribute='foo'/>
sin un nodo de texto dentro.Vale la pena mencionar que el propio nokogiri se envía con una herramienta de línea de comando, que debe instalarse con
gem install nokogiri
.Es posible que encuentre útil esta publicación de blog .
fuente
He probado un par de utilidades XPath de línea de comandos y cuando me di cuenta de que estoy pasando demasiado tiempo buscando en Google y descubriendo cómo funcionan, escribí el analizador XPath más simple posible en Python que hizo lo que necesitaba.
El siguiente script muestra el valor de la cadena si la expresión XPath se evalúa como una cadena, o muestra todo el subnodo XML si el resultado es un nodo:
Utiliza
lxml
: un analizador XML rápido escrito en C que no está incluido en la biblioteca estándar de Python. Instalarlo conpip install lxml
. En Linux / OSX podría necesitar prefijos consudo
.Uso:
lxml también puede aceptar una URL como entrada:
Extraiga el atributo url debajo de un nodo de caja, es decir
<enclosure url="http:...""..>)
:Xpath en Google Chrome
Como nota al margen no relacionada: si por casualidad desea ejecutar una expresión XPath contra el marcado de una página web, puede hacerlo directamente desde las herramientas de desarrollo de Chrome: haga clic con el botón derecho en la página en Chrome> seleccione Inspeccionar y luego en DevTools consola pegue su expresión XPath como
$x("//spam/eggs")
.Obtenga todos los autores en esta página:
fuente
lxml
ya se mencionó en otras dos respuestas años antes que la suya.Aquí hay un caso de uso de xmlstarlet para extraer datos de elementos anidados elem1, elem2 a una línea de texto de este tipo de XML (que también muestra cómo manejar espacios de nombres):
La salida será
En este fragmento, -m coincide con los elementos anidados elem2, -v genera valores de atributo (con expresiones y direccionamiento relativo), -o texto literal, -n agrega una nueva línea:
Si se necesitan más atributos de elem1, uno puede hacerlo así (también mostrando la función concat ()):
Tenga en cuenta la complicación (IMO innecesaria) con espacios de nombres (ns, declarados con -N), que casi me hizo renunciar a xpath y xmlstarlet, y escribir un convertidor ad-hoc rápido.
fuente
Mi script de Python xgrep.py hace exactamente esto. Para buscar todos los atributos
attribute
de los elementoselement
en los archivosfilename.xml ...
, debe ejecutarlo de la siguiente manera:Hay varios interruptores para controlar la salida, como
-c
para contar coincidencias,-i
para sangrar las partes coincidentes y-l
para generar solo nombres de archivo.El script no está disponible como paquete Debian o Ubuntu, pero todas sus dependencias sí lo están.
fuente
Dado que este proyecto es aparentemente bastante nuevo, consulte https://github.com/jeffbr13/xq , parece ser un envoltorio
lxml
, pero eso es todo lo que realmente necesita (y también publicó soluciones ad hoc usando lxml en otras respuestas)fuente
No estaba contento con Python one-liners para consultas HTML XPath, así que escribí el mío. Asume que instaló el
python-lxml
paquete o ejecutópip install --user lxml
:Una vez que lo tenga, puede usarlo como en este ejemplo:
fuente
Instale la base de datos BaseX , luego use su "modo de línea de comandos independiente" como este:
basex -i - //element@attribute < filename.xml
o
basex -i filename.xml //element@attribute
El lenguaje de consulta es en realidad XQuery (3.0), no XPath, pero dado que XQuery es un superconjunto de XPath, puede usar consultas XPath sin darse cuenta.
fuente