Search code examples
xmlxsltxslt-1.0apply-templates

Use apply-template for each variable node-set XLST 1.0


I have this input:

<?xml version="1.0" encoding="utf-8"?>
        <Native xmlns="http://www.cargowise.com/Schemas/Native/2011/11" version="2.0">
                <Header>
                    <OwnerCode>VISSHIMEL</OwnerCode>
                </Header>
        </Native>

And I have a declared node-set in my xslt:

<xsl:variable name="SupplierSCAC">
           <m>Yellow</m>
           <m>Red</m>
           <m>Green</m>
         </xsl:variable>

I'm trying to do a for each for this node set and select OwnerCode value "VISSHIMEL" but for some reason my template call is not getting the value. Expected output is:

<TariffCollection>
Yellow
<test>VISSHIMEL</test>
</TariffCollection>
<TariffCollection>
Red
<test>VISSHIMEL</test>
</TariffCollection>
<TariffCollection>
Green
<test>VISSHIMEL</test>
</TariffCollection>**

However, <test> is always empty. Here is my code:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 s1 exsl" version="1.0" xmlns:s0="http://www.cargowise.com/Schemas/Native/2011/11" xmlns:s1="http://www.cargowise.com/Schemas/Universal/2011/11" xmlns:exsl="http://exslt.org/common" >
    <xsl:output omit-xml-declaration="yes" method="xml" version="1.0"/>
    <xsl:template match="/">
        <xsl:variable name="SupplierSCAC">
           <m>Yellow</m>
           <m>Red</m>
           <m>Green</m>
        </xsl:variable> 
        <xsl:for-each select="exsl:node-set($SupplierSCAC)/m">
            <xsl:call-template name="Test">
                <xsl:with-param name="SupplierSCAC" select="."/>
            </xsl:call-template>
            <!-- <xsl:apply-templates select="/s0:Native" > -->
                <!-- <xsl:with-param name="SupplierSCAC" select="."/> -->
            <!-- </xsl:apply-templates> -->
        </xsl:for-each> 
    </xsl:template>
        
    <xsl:template name="Test" match="/s0:Native">
    <xsl:param name="SupplierSCAC"/>
        <TariffCollection>
            <xsl:value-of select="$SupplierSCAC"/>
            <test>
                <xsl:value-of select="s0:Header/s0:OwnerCode"/>
            </test>
        </TariffCollection>
    </xsl:template>
</xsl:stylesheet>

I know the for-each and the parameter is successfully displayed in the output but I don't know why I can't access the value of the xpath OwnerCode. I tried using apply-template instead but it's worse because I have no output at all. Let me know if you need more information. Thanks!


Solution

  • When a template is invoked by an xsl:call-template instruction, the match attribute is ignored. Therefore, you are still in the context established by:

    <xsl:for-each select="exsl:node-set($SupplierSCAC)/m">
    

    and your instruction

    <xsl:value-of select="s0:Header/s0:OwnerCode"/>
    

    selects nothing because these nodes are in another document.

    Try something like:

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:s0="http://www.cargowise.com/Schemas/Native/2011/11" 
    xmlns:exsl="http://exslt.org/common" 
    exclude-result-prefixes="s0 exsl" >
    <xsl:output omit-xml-declaration="yes" method="xml" version="1.0"/>
        
    <xsl:template match="/">
        <xsl:variable name="SupplierSCAC">
            <m>Yellow</m>
            <m>Red</m>
            <m>Green</m>
        </xsl:variable> 
        <xsl:variable name="root" select="/s0:Native" />
        <xsl:for-each select="exsl:node-set($SupplierSCAC)/m">
            <TariffCollection>
                <xsl:value-of select="."/>
                <test>
                    <xsl:value-of select="$root/s0:Header/s0:OwnerCode"/>
                </test>
            </TariffCollection>
        </xsl:for-each> 
    </xsl:template>
            
    </xsl:stylesheet>
    

    Note that the result is an XML fragment, having no single root element.