DaveF
DaveF

Reputation: 173

XSLT/Xpath Select elements based on the values of two attributes

I wish to return all <nodes> which have the tags with the attributes k=network & v=LU. Note LU could be part of a string. This XML just returns a list of <tag k="network" v="LU"/>

If there are any other improvements I can make, please note them.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="osm">
    <xsl:copy>
      <xsl:apply-templates select="node/tag[@k='network' and @v='LU']"/>
    </xsl:copy>
  </xsl:template>

Original XML:

<osm>
   <node>
      <tag k="railway" v="station"/>
      <tag k="network" v="LU"/>
   </node>
   <node>
      <tag k="railway" v="station"/>
      <tag k="network" v="NR"/>
      <tag k="operator" v="LU"/>
   </node>
   <node>
      <tag k="railway" v="station"/>
      <tag k="network" v="NR,LU"/>
      <tag k="operator" v="LU"/>
   </node>
     <...snip...>
</osm>

Desired output

<osm>
   <node>
      <tag k="railway" v="station"/>
      <tag k="network" v="LU"/>
   </node>
   <node>
      <tag k="railway" v="station"/>
      <tag k="network" v="NR,LU"/>
      <tag k="operator" v="LU"/>
   </node>
</osm>

Upvotes: 0

Views: 754

Answers (1)

Michael Kay
Michael Kay

Reputation: 163595

Am I right in thinking that your requirement is to select and copy all <node> elements that have a child <tag> element with attribute @k='network' and an attribute @v which is a list of tokens including the token LU?

I would do this simply as

<xsl:template match="osm">
  <osm>
    <xsl:copy-of select="node[tag[@k='network'][contains(@v,'LU')]]"/>
  </osm>
</xsl:template>

But the contains() test might need to be made more precise, for example if a value like v="LUCKY" can appear. With XSLT 2.0 I would use the predicate [tokenize(@v, ',')='LU']

Upvotes: 2

Related Questions