Is there a package out there, for Ubuntu and/or CentOS, that has a command-line tool that can execute an XPath one-liner like foo //element@attribute filename.xml
or foo //element@attribute < filename.xml
and return the results line by line?
I'm looking for something that would allow me to just apt-get install foo
or yum install foo
and then just works out-of-the-box, no wrappers or other adaptation necessary.
Here are some examples of things that come close:
Nokogiri. If I write this wrapper I could call the wrapper in the way described above:
#!/usr/bin/ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML::XPath. Would work with this wrapper:
#!/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
from XML::XPath returns too much noise, -- NODE --
and attribute = "value"
.
xml_grep
from XML::Twig cannot handle expressions that do not return elements, so cannot be used to extract attribute values without further processing.
EDIT:
echo cat //element/@attribute | xmllint --shell filename.xml
returns noise similar to xpath
.
xmllint --xpath //element/@attribute filename.xml
returns attribute = "value"
.
xmllint --xpath 'string(//element/@attribute)' filename.xml
returns what I want, but only for the first match.
For another solution almost satisfying the question, here is an XSLT that can be used to evaluate arbitrary XPath expressions (requires dyn:evaluate support in the XSLT processor):
<?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
.
You should try these tools :
xidel
(xidel): xpath3xmlstarlet
(xmlstarlet page) : can edit, select, transform... Not installed by default, xpath1xmllint
(man xmllint): often installed by default with libxml2-utils
, xpath1 (check my wrapper to have --xpath
switch on very old releases and newlines delimited output (v < 2.9.9)). Can be used as interactive shell with the --shell
switch.xpath
: installed via perl's module XML::Xpath
, xpath1xml_grep
: installed via perl's module XML::Twig
, xpath1 (limited xpath usage)saxon-lint
(saxon-lint): my own project, wrapper over @Michael Kay's Saxon-HE Java library, xpath3: using SaxonHE 9.6 ,XPath 3.x (+retro compatibility)Examples:
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