1

This is an example of my xml code:

<db>
  <group>
  <name>Team1</name>
    <set num="1">AAA</set>
    <set num="2">BBB</set>
    <set num="3">CCC</set>
  </group>
  <group>
  <name>Team2</name>
    <set num="1">DDD</set>
    <set num="2">AAA</set>
    <set num="3">FFF</set>
    <set num="4">EEE</set>
  </group>
  <group>
  <name>Team3</name>
    <set num="1">AAA</set>
    <set num="2">GGG</set>
    <set num="3">FFF</set>
  </group>
  <group>
  <name>Team4</name>
    <set num="1">BBB</set>
    <set num="2">EEE</set>
    <set num="3">AAA</set>
  </group>
</db>

How would I use xslt to display the name and num of all instances where AAA has a num less than 3, so my output would look something like this:

<result value="AAA">
  <name num="1">Team1</name>
  <name num="2">Team2</name>
  <name num="1">Team3</name>
</result>

The code I have been trying to use is as follows:

...
<xsl:template match="/db">
  <result value="AAA">
    <xsl:for-each select="group[set/@num &lt; '3' and set='AAA']">
      <name num="{@num}">
        <xsl:value-of select="name" />
      </name>
    </xsl:for-each>
  </result>
</xsl:template>

But this give me all groups that contain "AAA" regardless of num, and the num always displays as "" no matter what.

Any help would be appreciated as I am new to XSLT. Thanks!

1 Answer 1

1

This should do it:

  <xsl:template match="/db">
    <result value="AAA">
      <xsl:for-each select="group[set[@num &lt; 3 and string(.)='AAA']]">
        <name num="{set[@num &lt; 3 and string(.)='AAA']/@num}">
          <xsl:value-of select="name" />
        </name>
      </xsl:for-each>
    </result>
  </xsl:template>

the problem is that set/@num &lt; '3' and set='AAA' tests separately @num and set, whereas what is needed is a set element that matches both conditions at the same time - that is done with the nested restriction [set[@num &lt; 3 and string(.)='AAA']] = all groups that have a set sub-element that has @num less than 3 and contains AAA.

The same test is repeated to get the value of @num from the correct set sub-element.

An alternative to avoid repeating the test:

  <xsl:template match="/db">
    <result value="AAA">
      <xsl:for-each select="group">
        <xsl:variable name="theSet" select="set[@num &lt; 3 and string(.)='AAA']"/>
        <xsl:if test="$theSet">
          <name num="{$theSet/@num}">
            <xsl:value-of select="name" />
          </name>
        </xsl:if>
      </xsl:for-each>
    </result>
  </xsl:template>
Sign up to request clarification or add additional context in comments.

1 Comment

Worked great! thanks so much. I knew that was the problem, but couldn't find how to match both conditions at the same time. I searched for a while and never saw "string(.)"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.