Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling template from inside <xsl:for-each>

Tags:

xml

xslt

xsd

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.

like image 597
savruk Avatar asked Mar 08 '11 11:03

savruk


People also ask

How do you call a template in XSLT?

By invoke, we mean that the named template is called and applied to the source document. If a template does not have a name, it cannot be called by this element. The xsl:template element is used to create a template. You can name a template by using the name attribute of the xsl:template element.

What is xsl for each select?

Definition and Usage. The <xsl:for-each> element loops through each node in a specified node set.

What does node () do in XSLT?

XSLT current() Function Usually the current node and the context node are the same. However, there is one difference. Look at the following XPath expression: "catalog/cd". This expression selects the <catalog> child nodes of the current node, and then it selects the <cd> child nodes of the <catalog> nodes.

What is xsl template match?

XSLT <xsl:template>The match attribute is used to associate the template with an XML element. The match attribute can also be used to define a template for a whole branch of the XML document (i.e. match="/" defines the whole document).


1 Answers

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> 
like image 181
Dimitre Novatchev Avatar answered Oct 20 '22 00:10

Dimitre Novatchev