SpockJenkins
SpockJenkins

Reputation: 167

Create List with XSLT from two xml docs

I have the following xml file:

<root>
  <sub type="print">print</sub>
  <sub type="email">email</sub>
</root>

I want to match each type up against the following list:

<types>
  <type>email</type>
  <type>broadcast</type>
  <type>mobile</type>
  <type>print</type>
  <type>web</type>
</types>

Using this xslt with the "doc" being the xml and "types" the list above passed in as parameters:

<xsl:stylesheet 
  xmlns = "http://www.w3.org/1999/xhtml"
  xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" 
  version="2.0">

  <xsl:output method="xhtml" indent="yes" />

  <xsl:param name="doc"/>
  <xsl:param name="types"/>   

  <xsl:template match="/">
    <xsl:for-each select="$doc//sub">
      <xsl:variable name="count">
        <xsl:number value="position()" format="1"/>
      </xsl:variable>

      <ul>
        <xsl:for-each select="$types//type">
          <xsl:choose>
            <xsl:when test="$doc//sub[$count]/@type = text()">
              <li>
                <b>
                  <xsl:value-of select="$doc//sub[$count]/@type"/> - <xsl:value-of select="text()"/>
                </b>
              </li>
            </xsl:when>
            <xsl:otherwise>
              <li>
                <xsl:value-of select="$doc//sub[$count]/@type"/> - <xsl:value-of select="text()"/>
              </li>
            </xsl:otherwise>
          </xsl:choose> 
        </xsl:for-each>
      </ul>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

This should give me an unordered list for each sub in my xml printing the type from the sub and then each type. When the sub and the type match, it should be bold. I want this:

<ul>
  <li>print - email</li>
  <li>print - broadcast</li>
  <li>print - mobile</li>
  <li><b>print - print</b></li>
  <li>print - web</li>
</ul>
<ul>
  <li><b>email - email</b></li>
  <li>email - broadcast</li>
  <li>email - mobile</li>
  <li>email - print</li>
  <li>email - web</li>
</ul>

But I get this:

<ul>
  <li><b>print email - email</b></li>
  <li>print email - broadcast</li>
  <li>print email - mobile</li>
  <li><b>print email - print</b></li>
  <li>print email - web</li>
</ul>
<ul>
  <li><b>print email - email</b></li>
  <li>print email - broadcast</li>
  <li>print email - mobile</li>
  <li><b>print email - print</b></li>
  <li>print email - web</li>
</ul>

Thanks for any and all help.

Upvotes: 2

Views: 562

Answers (2)

David Carlisle
David Carlisle

Reputation: 5652

Given your sub file as main input and the types in subtypes.xml

<xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<xsl:template match="sub">
 <ul>
  <xsl:apply-templates select="doc('subtypes.xml')">
   <xsl:with-param name="this" select="." tunnel="yes"/>
  </xsl:apply-templates>
 </ul>
</xsl:template>

<xsl:template match="type">
 <xsl:param name="this" tunnel="yes"/>
 <li>
  <xsl:choose>
   <xsl:when test="$this/@type=.">
    <b><xsl:value-of select="$this/@type,' - ',."/></b>
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of select="$this/@type,' - ',."/>
   </xsl:otherwise>
  </xsl:choose>
 </li>
</xsl:template>

</xsl:stylesheet>

produces:

<?xml version="1.0" encoding="UTF-8"?>
  <ul>
  <li>print  -  email</li>
  <li>print  -  broadcast</li>
  <li>print  -  mobile</li>
  <li><b>print  -  print</b></li>
  <li>print  -  web</li>
</ul>
  <ul>
  <li><b>email  -  email</b></li>
  <li>email  -  broadcast</li>
  <li>email  -  mobile</li>
  <li>email  -  print</li>
  <li>email  -  web</li>
</ul>

Upvotes: 0

Daniel Haley
Daniel Haley

Reputation: 52888

I think it might have something to do with the multiple uses of //.

Try replacing your root template (match="/") with this:

  <xsl:template match="/">
    <html>
      <xsl:for-each select="$doc/root/sub">
        <xsl:variable name="vType" select="@type"/>
        <ul>
          <xsl:for-each select="$types/types/type">
            <li>
              <xsl:choose>
                <xsl:when test=".=$vType">
                  <b>
                    <xsl:value-of select="concat($vType,' - ',.)"/>
                  </b>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="concat($vType,' - ',.)"/>
                </xsl:otherwise>
              </xsl:choose>            
            </li>
          </xsl:for-each>
        </ul>
      </xsl:for-each>      
    </html>
  </xsl:template>

NOTE: I added the <html> tag to keep my output well-formed when testing.

Upvotes: 1

Related Questions