2

Below is my example xml:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:something-well-formed"> 
  <child1 attr1="a" attr2="b"> 
     <child1 attr1="a" attr2="b"/>
  </child1>
  <child3/>
  <child1 attr1="a" attr2="b"> 
     <child2 attr1="a" attr2="b"/> 
  </child1>
</root>

Question 1: How do you count the number of child1 nodes? Below I pass the string "child1" to my "element" parameter but what's the correct xslt syntax to achieve this?

Here is my example XSLT

<xsl:param name="element"/>
   <xsl:template match="@*|node()">
      <root>
        <name><xsl:value-of select="count(/root/*[local-name()='$element'])"/> 
         </name>
      </root>

Question 2: Given the same example xml, how do you access the Nth child1 element? I want to set its attributes to a specified value, but again, tripping up on syntax. Here's my example attempt:

<xsl:param name="element" />
<xsl:param name="attributes" />
<xsl:param name="nodeNumber" />


<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="*[local-name(.)=$element][count(preceding::*[local-name()='$element'] | ancestor::*[local-name()='$element'])=number($nodeNumber)]">
    <xsl:copy>
        <xsl:apply-templates select="@*" />

        <!-- Splits into separate key/value pairs elements -->
        <xsl:variable name="attributesSeq" select="tokenize($attributes, ';')" />
        <xsl:for-each select="$attributesSeq">
            <xsl:variable name="attributesSeq" select="tokenize(., ',')" />

            <xsl:variable name="key"
                select="replace($attributesSeq[1], '&quot;', '')" />
            <xsl:variable name="value"
                select="replace($attributesSeq[2], '&quot;', '')" />

            <xsl:attribute name="{$key}">
                <xsl:value-of select="$value" />
            </xsl:attribute>
        </xsl:for-each>
        <xsl:apply-templates select="node()[$nodeNumber]" /> 
    </xsl:copy>
</xsl:template>

Thanks for the help!

2
  • Are you looking for the nth element at any level in the document? Commented Apr 17, 2014 at 16:59
  • Yes - in fact - by "nth element" I mean in the order with which that element appears in the doc regardless of nesting. So in the above example, the top most "child1" would be 1st instance, the next nested child1 would be the 2nd instance, and the last child1 below it would 3rd instance. Order is determined from a top to bottom ordering. Thanks for the help! Commented Apr 17, 2014 at 18:10

2 Answers 2

3

To count the number of occurrences of a given element appearing anywhere in the document:

count(//*[local-name()=$element])

To select the nth occurrence:

(//*[local-name()=$element])[$n]

A full example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="element" />
    <xsl:variable name="n" select="2" />
    <xsl:template match="/">
        <xsl:value-of select="count(//*[local-name()=$element])" />
        <xsl:apply-templates select="(//*[local-name()=$element])[$n]" />
    </xsl:template>
    <xsl:template match="child1">
        [<xsl:value-of select="@attr1" />]
    </xsl:template>
</xsl:stylesheet>

Note that you cannot reference a parameter in a match pattern in XSLT 1.0, which is why I chose to select elements of the parameterized name, but was forced to use the literal name in the match.

Sign up to request clarification or add additional context in comments.

Comments

0

Would not the Xpath expression //child1 give you the node set of all of them regardless of hierarchy? And //child1[9] give you the one at a particular index position? I may be misunderstanding your question.

1 Comment

//child1[9] would give you a set of all child1 elements that are the 9th child1 in their respective parents. (//child1)[9] would give you the 9th child1 in the whole document. There is a note to this effect in the XPath spec

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.