title: How to execute XPath one-liners from shell?
body: <p>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 <code>foo //element@attribute filename.xml</code> or <code>foo //element@attribute &lt; filename.xml</code> and return the results line by line?</p>
  
  <p>I'm looking for something that would allow me to just <code>apt-get install foo</code> or <code>yum install foo</code> and then just works out-of-the-box, no wrappers or other adaptation necessary.</p>
  
  <p>Here are some examples of things that come close:</p>
  
  <p>Nokogiri. If I write this wrapper I could call the wrapper in the way described above:</p>
  
  <pre><code>#!/usr/bin/ruby
  
  require 'nokogiri'
  
  Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
    puts row
  end
  </code></pre>
  
  <p>XML::XPath. Would work with this wrapper:</p>
  
  <pre><code>#!/usr/bin/perl
  
  use strict;
  use warnings;
  use XML::XPath;
  
  my $root = XML::XPath-&gt;new(ioref =&gt; 'STDIN');
  for my $node ($root-&gt;find($ARGV[0])-&gt;get_nodelist) {
    print($node-&gt;getData, "\n");
  }
  </code></pre>
  
  <p><code>xpath</code> from XML::XPath returns too much noise, <code>-- NODE --</code> and <code>attribute = "value"</code>.</p>
  
  <p><code>xml_grep</code> from XML::Twig cannot handle expressions that do not return elements, so cannot be used to extract attribute values without further processing.</p>
  
  <p>EDIT:</p>
  
  <p><code>echo cat //element/@attribute | xmllint --shell filename.xml</code> returns noise similar to <code>xpath</code>.</p>
  
  <p><code>xmllint --xpath //element/@attribute filename.xml</code> returns <code>attribute = "value"</code>.</p>
  
  <p><code>xmllint --xpath 'string(//element/@attribute)' filename.xml</code> returns what I want, but only for the first match.</p>
  
  <p>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):</p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
      xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn"&gt;
    &lt;xsl:output omit-xml-declaration="yes" indent="no" method="text"/&gt;
    &lt;xsl:template match="/"&gt;
      &lt;xsl:for-each select="dyn:evaluate($pattern)"&gt;
        &lt;xsl:value-of select="dyn:evaluate($value)"/&gt;
        &lt;xsl:value-of select="'&amp;#10;'"/&gt;
      &lt;/xsl:for-each&gt; 
    &lt;/xsl:template&gt;
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>Run with <code>xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml</code>.</p>