Roy van Marrewijk
Roy van Marrewijk

Reputation: 3

Recursively looping through XML using XSL

I would like to translate the following XML file to a HTML page using XSL:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Recursion.xsl"?>
<CompareResults hasChanges="true">
    <CompareItem name="Appel"  status="Identical">
        <Properties>
            <Property name="Abstract" model="false" baseline="false" status="Identical"/>
        </Properties>

        <CompareItem name="Banaan"  status="Identical">
            <Properties>
                <Property name="Abstract" model="false" baseline="false" status="Identical"/>
            </Properties>
        </CompareItem>

        <CompareItem name="Kiwi"  status="Identical">

            <CompareItem name="Peer"  status="Model only">
                <Properties>
                    <Property name="Abstract" model="false" baseline="false" status="Identical"/>
                    <Property name="Notes" model="PeerName" status="Model only"/>
                </Properties>
            </CompareItem>

            <Properties>
                <Property name="Abstract" model="false" baseline="false" status="Identical"/>
            </Properties>
        </CompareItem>
    </CompareItem>
</CompareResults>

The output should contain the elements that have the @status "Model only" and the whole path towards this element.
So, for this example:

My thought is that I should realize this by looping recursively through the XML, but the problem is that I can't figure out how templates can return a value. So, can anyone tell me if (and how) it is possible to return values or how to construct the XSL to comply to the required output?

This is my current XSL file:

<?xml version="1.0" encoding="UTF-8"?>

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

<xsl:template match="/">
  <html>
  <body>
        <xsl:apply-templates/>
  </body>
  </html>
</xsl:template>

<xsl:template match="/CompareResults">
    <xsl:apply-templates select="CompareItem"/>
</xsl:template>

<!--CompareItem -->
<xsl:template match="CompareItem">

    <xsl:value-of select="@name"/>

    <!-- Sub elements -->   
    <xsl:apply-templates select="CompareItem"/>
</xsl:template>

</xsl:stylesheet>

Upvotes: 0

Views: 414

Answers (2)

zx485
zx485

Reputation: 29052

Getting the @name attribute values of all elements that have the @status attribute with the value "Model only" as an ul list can be done without recursion.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:strip-space elements="*" />    

  <xsl:template match="/">
    <html>
      <body>
        <ul>
          <xsl:apply-templates select="//*[@status = 'Model only']" mode="xx" />
        </ul>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="*" mode="xx" >
    <li><xsl:value-of select="@name" /></li>
    <xsl:apply-templates />
  </xsl:template>

</xsl:stylesheet>

Result is:

<html>
    <body>
         <ul>
            <li>Peer</li>
            <li>Notes</li>
        </ul>
    </body>
</html>

This does work well in a browser.

Upvotes: 0

michael.hor257k
michael.hor257k

Reputation: 117165

If I am guessing (!) correctly, you want to do:

XSLT 1.0

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

<xsl:template match="/CompareResults">
    <html>
        <body>
            <xsl:apply-templates/>
        </body>
    </html>
</xsl:template>

<xsl:template match="*[@name and descendant-or-self::*/@status='Model only']">
    <p>
        <xsl:value-of select="@name" />
    </p>
    <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

This will output a p for every element that satisfies both:

  1. it has a name attribute;
  2. it or one of its descendants has a status attribute with the value of "Model only".

resulting in:

<html>
   <body>
      <p>Appel</p>
      <p>Kiwi</p>
      <p>Peer</p>
      <p>Notes</p>
   </body>
</html>

Upvotes: 1

Related Questions