1

I have XSLT:

<xsl:template match="/">
    <!--<FLC_OKVEDCODE>-->
    <xsl:variable name="valArray" select="//NodeA | //NodeB | //NodeC"/>
    <xsl:variable name="valResArray">
        <result_value>TextA</result_value>
        <result_value>TextB</result_value>
        <result_value>TextC</result_value>
    </xsl:variable>
    <xsl:variable name="resArray" select="document('')//xsl:variable[@name= 'valResArray']/*"></xsl:variable>

    <xsl:for-each select="$valArray">
        <xsl:if test="string-length(normalize-space(text())) = 0">
            <ERROR>
                <Err1><xsl:value-of select="position()"></xsl:value-of></Err1>
                <Err2><xsl:value-of select="$resArray[1]"></xsl:value-of></Err2>
                <Err3><xsl:value-of select="$resArray[2]"></xsl:value-of></Err3>
                <Err4><xsl:value-of select="$resArray[3]"></xsl:value-of></Err4>
                <Err5><xsl:value-of select="$resArray[position()]"></xsl:value-of></Err5>
            </ERROR>
        </xsl:if>
    </xsl:for-each>
    <!--</FLC_>-->
</xsl:template>

It have to check NodeA, NodeB and NodeC if they are empty - create error XML. In my test NodeB is empty, but result is:

<ERROR>
    <Err1>2</Err1>
    <Err2>TextA</Err2>
    <Err3>TextB</Err3>
    <Err4>TextC</Err4>
    <Err5>TextA</Err5>
</ERROR>

Why Err5 is TextA, if position() return 2 and $resArray[2] (printed at ) is TextB??

2 Answers 2

2

After that problem ate my brain, solution was very simple:

Adding:

<xsl:variable name="temppos" select="position()"></xsl:variable>

between Err4 and Err5. It looks like it automatically puts array as parameter for such functions as "position", and do it with closest array. So, "position()" of "resArray" was still 1, and that is why there was this result.

That is explanation that I guess. Still, I disappointed with handling arrays in XSLT.

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

2 Comments

The issue is that a predicate changes the context - $resarray[position()] evaluates the position() predicate once in the context of each node in $resarray, whereas what you want to do is capture the position() value in the outer context (the for-each) and use that value inside the predicate. As you've discovered, the simplest way to do this is to use a variable.
A numeric predicate [N] is equivalent to [position() = N], so [position()] means [position() = position()] which is always true.
2

Why Err5 is TextA, if position() return 2

Why do you think that position() returns 2? The truth is that the expression:

$resArray[position()]

means "all nodes of $resArray that have a non-zero (i.e. true) position". Which is true of all nodes of $resArray.

Therefore the expression:

<xsl:value-of select="$resArray[position()]"/>

will return the value of the first node of the returned node-set (i.e. TextA) in XSLT 1.0, and the values of all matching nodes (i.e. TextA TextB TextC) in XSLT 2.0.

2 Comments

Because "position()" 3 lines above returned 2. And I need position of iterable array, but didn't know how to resolve it, where to read about it and etc.
@Arkady That's not how it works. The position() inside the predicate is the position of the node being tested. You can see this if you try $resArray[position() = 2], for example.

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.