savruk
savruk

Reputation: 545

Calling template from inside <xsl:for-each>

I have an xsl like below:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:nsm="http://192.137.81.132/deneme/sample.xsd"
               exclude-result-prefixes="nsm">

    <xsl:output method="text"/>
    <xsl:param name="fieldOf">address</xsl:param>
    <xsl:param name="inputId" select="concat($fieldOf,'/value')"/>

    <xsl:variable name="vXpathExpression" select="concat('global/fieldset/field/', $inputId)"/>
    <!-- these fields are from xml file-->

    <xsl:template match="/">
        <xsl:value-of select="$vXpathExpression"/>: <xsl:text/>
        <xsl:for-each select="document('sample.xsd')/xs:schema/xs:complexType[@name='fieldtype']/xs:choice/child::*">

        </xsl:for-each>

        <xsl:call-template name="getNodeValue">
            <xsl:with-param name="pExpression" select="$vXpathExpression" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="getNodeValue">
        <xsl:param name="pExpression"/>
        <xsl:param name="pCurrentNode" select="."/>

        <xsl:choose>
            <xsl:when test="not(contains($pExpression, '/'))">
                <xsl:value-of select="$pCurrentNode/*[name()=$pExpression]"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="getNodeValue">
                    <xsl:with-param name="pExpression" select="substring-after($pExpression, '/')"/>
                    <xsl:with-param name="pCurrentNode" select="$pCurrentNode/*[name()=substring-before($pExpression, '/')]"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

In this case it works. But i cannot run it when I call template from inside of for-each. It gives nothing, no error, no values. Is there a way to solve this problem? Thanks

Edit: You can wonder if for-each works. It does. I can get attributes within for-each.

Upvotes: 5

Views: 6967

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243529

The problem is that:

<xsl:for-each select=
"document('sample.xsd')/xs:schema
          /xs:complexType[@name='fieldtype']/xs:choice/child::*">

changes the current document.

Trying to evaluate an XPath expression for the source XML while the current document is not the source XML does not produce the wanted result, because the current document has no such named elements.

The solution is simple:

<xsl:variable name="vSourceDoc" select="/"/>

<xsl:for-each select=
"document('sample.xsd')/xs:schema
              /xs:complexType[@name='fieldtype']/xs:choice/child::*">

    <xsl:call-template name="getNodeValue">                    
     <xsl:with-param name="pCurrentNode" select="$vSourceDoc" />                  
     <xsl:with-param name="pExpression" select="$vXpathExpression" />                  
   </xsl:call-template>            
</xsl:for-each> 

Upvotes: 6

Related Questions