¿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.xmlo foo //element@attribute < filename.xmly devolver los resultados línea por línea?
Estoy buscando algo que me permita simplemente apt-get install fooo yum install foosimplemente 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");
}
xpathde 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.xmldevuelve ruido similar a xpath.
xmllint --xpath //element/@attribute filename.xmlvuelve 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

xpathestá 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-utilsxpath1 (compruebe que mi contenedor tenga--xpathactivadas 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, xpath3xmllintviene conlibxml2-utils(se puede usar como shell interactivo con el--shellinterruptor)xmlstarletesxmlstarlet.xpathviene con el módulo de perlXML::Xpathxml_grepviene con el módulo de perlXML::Twigxidelesxidelsaxon-lintutilizando SaxonHE 9.6 , XPath 3.x (+ compatibilidad retro)Ej:
.
fuente
xmlstarlet sel -T -t -m '//element/@attribute' -v '.' -n filename.xmlhace exactamente lo que quiero!xmllintno 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.xmly 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
xmlstarletcomo 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.putslugar depen 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.xmlme sale elSENR0001: Cannot serialize a free-standing attribute nodemismo problema que con egxml_grep.-qsdesea:'-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::XSH2no 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
lxmlnixmllintni 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
greputilidades similares que succionan comoApp::xml_grep2yXML::Twig(que incluye enxml_greplugar dexml_grep2). Estos pueden ser bastante útiles cuando se trabaja en archivos XML grandes o numerosos para líneas rápidas uMakefileobjetivos.XML::Twiges especialmente agradable trabajar con unperlenfoque de secuencias de comandos cuando desea un poco más de procesamiento que el suyo$SHELLy laxmllintxstlprocoferta.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
perlsí misma).fuente
xml_grep2 -t //element@attribute filename.xmlfunciona y hace lo que espero (xml_grep --root //element@attribute --text_only filename.xmltodaví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@attributecon corchetes funciona paraxml_grepyxml_grep2.//element/@attributeno//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 tipoelementque tienen un atributoattribute. No quiero el elemento, solo el atributo.<element attribute='foo'/>debería darmefoo, no el completo<element attribute='foo'/>.--text_onlyen 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
lxmlya 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
attributede los elementoselementen los archivosfilename.xml ..., debe ejecutarlo de la siguiente manera:Hay varios interruptores para controlar la salida, como
-cpara contar coincidencias,-ipara sangrar las partes coincidentes y-lpara 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-lxmlpaquete 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.xmlo
basex -i filename.xml //element@attributeEl 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