0

Does XMLStarlet let you use a less-than/greater-than operator to filter on an attribute value? For example, consider a document like this:

<xml>
<list>
    <node name="a" val="x" />
    <node name="b" val="y" />
    <node name="c" val="z" />
    etc.
</list>

{code}

Is there a way to select nodes whose value is greater than "x"? This XPath does not seem to work with XMLStarlet 1.5.0:

//node[@val > 'x']

Nor does this:

//node[@value gt 'x']
user100464
  • 17,331
  • 7
  • 32
  • 40
  • 2
    xmlstarlet only supports xpath 1.0, so string comparison is limited to `=` and `!=`. See http://stackoverflow.com/questions/11125944/how-to-compare-strings-with-xpath-1-0 – Daniel Haley Mar 01 '16 at 18:05

1 Answers1

1

Comparing Characters like they were numbers (ASCII values/UniCode codepoints) is (unfortunately) impossible in XPath 1.0, look at this SO question if interested in more details.

So if your @val attributes are sorted in the XML, you can achieve this with a simple XPath expression selecting all nodes after an 'equal' match:

//node[@val='x']/following-sibling::node

If not, you'd have to use an XSLT-Stylesheet. Luckily, XMLStarlet has the ability to apply XSL-Stylesheets. I cite from their overview:

  • Apply XSLT stylesheets to XML documents (including EXSLT support, and passing parameters to stylesheets)

So you have the possibility to apply an xsl:stylesheet to achieve the desired result using xsl:sort, which is capable of sorting by characters.

<xsl:template match="/list">
  <xsl:for-each select="//node">    <!-- all nodes sorted by 'val' attribute' -->
    <xsl:sort select="@val" data-type="text" order="ascending" case-order="upper-first"/>
    <xsl:value-of select="@name" /> <!-- or whatever output you desire -->
  </xsl:for-each>
</xsl:template>
Community
  • 1
  • 1
zx485
  • 28,498
  • 28
  • 50
  • 59