user2962780
user2962780

Reputation: 35

XSL: issue with position() in xsl:if

My task is i have to display all the node labels, before displaying i need to check whether those node/label is there in the /Datum/DCR/Global/* if it is there then i want to display the value from the global elements child or else i want to display from the node elements label in my example node/label "home" is not there in global elements child nodes so i will display from /Result/site-map/segment/node[1]/label and "Inventory" is there in the Global elements Child node so i need to display inventory from /Datum/DCR/Global/Inventory.

XML file:-

<Properties>
    <Data>
        <Datum ID="D01" Type="DCR" Name="Global">
            <DCR Category="BAT" Type="global">
                <Global>
                    <FindaDealer>Find a Dealer</FindaDealer> 
                    <Tools>Tools</Tools> 
                    <Inventory>Inventory</Inventory> 
                    <ContactDealers>Contact Dealers</ContactDealers> 
                 </Global>
            </DCR>
        </Datum>
        <Result>
            <site-map id="hnh1clwg" >
                <segment id="0" >
                    <node id="hnhi" >
                        <label key="">home</label> 
                    </node>
                    <node id="hn4h">
                      <label key="">Offers</label>
                    </node>
                    <node id="hn4l">
                      <label key="">Tools</label>
                    </node>
                    <node id="hn62">
                      <label key="">Inventory</label>
                    </node>
                  </segment>
              </site-map>
        </Result>
    </Data>
</properties>

XSL code:-

<xsl:element name="ul">
        <xsl:for-each select="Properties/Data/Result/site-map/segment/node">
            <li>
                <a href="#"> 
                    <xsl:apply-templates select="/Properties/Data/Datum[@Name='Global']/DCR/Global/*">
                        <xsl:with-param name="nodelabel" select="label"/>
                    </xsl:apply-templates>          
                </a>
            </li>                                   
        </xsl:for-each>
    </xsl:element>          

<xsl:template name="Glossary" match="/Properties/Data/Datum[@Name='Global']/DCR/Global/*">
    <xsl:param name="nodelabel"/>
    <xsl:variable name="name" select="name(.)"/>
    <xsl:variable name="value" select="."/>

    <xsl:if test="($nodelabel = $value)">
        <xsl:text>From Global element : </xsl:text>                                             
    </xsl:if>
    <xsl:if test="not($nodelabel = $value) and position()=last()">
        <xsl:text>From Sitemap : </xsl:text>                                                
    </xsl:if>

</xsl:template>

Output i am getting:-

From Sitemap : 
From Sitemap : 
From Global element : From Sitemap : 
From Global element : From Sitemap : 

desired output :-

From Sitemap : 
From Sitemap : 
From Global element : 
From Global element :

any pointers would be helpfull.

Thanks

Upvotes: 2

Views: 378

Answers (1)

Ian Roberts
Ian Roberts

Reputation: 122374

I'm not sure I really understand your logic in this fragment, there seems to be no need to apply templates to all the Global/* elements for every site-map node. You could define a key on the global values to let you look up those nodes by value

<xsl:key name="globalValues" match="Global/*" use="." />

and now you can define two different templates for nodes, one that matches nodes that do have counterparts in the global list and another for nodes that don't:

<xsl:template match="node[key('globalValues', label)]" priority="10">
  <xsl:text>From Global element : </xsl:text>
  <!-- within this template you can use
         key('globalValues', label)
       to access the corresponding Global/* element -->
</xsl:template>

<xsl:template match="node" priority="5">
  <xsl:text>From Sitemap : </xsl:text>
</xsl:template>

(the explicit priorities aren't strictly necessary in this case as the default priorities will do the right thing, but I think they make the intention clearer). Now with these in place you simply apply-templates to all the node elements and the template matcher will pick the appropriate one for each node:

<xsl:element name="ul">
    <xsl:for-each select="Properties/Data/Result/site-map/segment/node">
        <li>
            <a href="#"> 
                <xsl:apply-templates select="." />
            </a>
        </li>                                   
    </xsl:for-each>
</xsl:element>

or more idiomatically, move the <li> and <a> into the target templates and get rid of the for-each, just

<xsl:apply-templates select="Properties/Data/Result/site-map/segment/node" />

Upvotes: 1

Related Questions