How to apply an XSLT template to an element as many times as the number of another element in the document?

It is very difficult for me to express it in English, so an example can help. Say I have several elements called a multi-member proposal. In another part of XML there is a set of elements with language codes. I would like to apply a template for each sentence as many times as the number of languages ​​and call this template with the corresponding language code. From this:

<description>
    <sentences>
        <sentence>
            <term type="adjective">nice</term>
            <term type="tripType">cycling</term>
        </sentence>
        <sentence>
            <term type="adjective">boring</term>
            <term type="tripType">hike</term>
        </sentence>
    </sentences>
    <languages>
        <l>cs</l>
        <l>en</l>
    </languages>
</description>

I want to create something like this:

<div>
 <p><span>cs</span> nice cycling</p>
 <p><span>en</span> nice cycling</p>
</div>

<div>    
 <p><span>cs</span> boring hike</p>
 <p><span>en</span> boring hike</p>
</div>

I tried to use <xsl:for-each select="/description/languages/l">, but this sets the content las the current item, and I can no longer use this term.

Any idea would be greatly appreciated. Thanks

+3
source share
3

( ", " ) , for-each: <xsl:variable name="term" select="current()"/>

0
<xsl:template match="description">
  <xsl:apply-templates select="sentences/sentence" />
</xsl:template>

<xsl:template match="sentence">
  <xsl:variable name="terms" select="term" />
  <div>
    <xsl:for-each select="../../languages/l">
      <p>
        <span><xsl:value-of select="." /></span>
        <xsl:apply-templates select="$terms" />
      </p>
    <xsl:for-each>
  </div>
</xsl:template>

<xsl:template match="term">
  <xsl:apply-templates select="." />
  <xsl:if test="position() &lt; last()"> </xsl:if>
</xsl:template>
+1

This is a simple conversion (without explicit conditions) :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="sentence">
  <xsl:variable name="vSentence" select="."/>
  <div>
       <xsl:for-each select="/*/languages/l">
         <p>
           <span><xsl:value-of select="."/></span>
           <xsl:apply-templates select="$vSentence/term"/>
         </p>
       </xsl:for-each>
     </div>
 </xsl:template>

 <xsl:template match="term[position() > 1]">
  <xsl:text> </xsl:text>
  <xsl:value-of select="."/>
 </xsl:template>
 <xsl:template match="l"/>
</xsl:stylesheet>

when applied to the provided XML document :

<description>
    <sentences>
        <sentence>
            <term type="adjective">nice</term>
            <term type="tripType">cycling</term>
        </sentence>
        <sentence>
            <term type="adjective">boring</term>
            <term type="tripType">hike</term>
        </sentence>
    </sentences>
    <languages>
        <l>cs</l>
        <l>en</l>
    </languages>
</description>

creates the desired, correct result :

<div>
   <p><span>cs</span>nice cycling</p>
   <p><span>en</span>nice cycling</p>
</div>
<div>
   <p><span>cs</span>boring hike</p>
   <p><span>en</span>boring hike</p>
</div>
+1
source

All Articles