user69971
user69971

Reputation: 45

xslt: How can I create a dynamic table?

Given this xml

<Documents>
<Section>
<SectionName>Green</SectionName>
  <Document>
    <FileName>Tier 1 Schedules</FileName>     
  </Document>
  <Document>
    <FileName>Tier 3 Schedules</FileName>      
  </Document>
  <Document>
    <FileName>Setback Schedule</FileName>    
  </Document>
  <Document>
    <FileName>Tier 2 Governance</FileName>    
  </Document>
</Section>
<Section>
<SectionName>MRO/Refurb</SectionName>
  <Document>
    <FileName>Tier 2 Governance</FileName>    
  </Document>
</Section>
</Documents>

What would the xslt be to output this html

<table>
  <tr>
    <td>Green</td>
  </tr>
  <tr>
    <td>Tier 1 Schedules</td>
  </tr>
  <tr>
    <td>Tier 3 Schedules</td>
  </tr>
  <tr>
    <td>Setback Schedule</td>
  </tr>
  <tr>
    <td>Tier 2 Governance</td>
  </tr>
  <tr>
    <td>MRO/Refurb</td>
  </tr>
  <tr>
    <td>Tier 2 Governance</td>
  </tr>
</table>

I could do this in asp.net but not sure how to do the loops in xslt.

Thanks, Al

Upvotes: 1

Views: 1359

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243569

Actually, there is a slightly simpler solution than the one proposed by Tomalak:

<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="/">
        <table>
            <xsl:apply-templates/>
        </table>
    </xsl:template>

    <xsl:template match="SectionName | FileName">
        <tr>
            <td>
                <xsl:value-of select="." />
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the originally provided XML document, the wanted result is produced:

<table>
   <tr>
      <td>Green</td>
   </tr>
   <tr>
      <td>Tier 1 Schedules</td>
   </tr>
   <tr>
      <td>Tier 3 Schedules</td>
   </tr>
   <tr>
      <td>Setback Schedule</td>
   </tr>
   <tr>
      <td>Tier 2 Governance</td>
   </tr>
   <tr>
      <td>MRO/Refurb</td>
   </tr>
   <tr>
      <td>Tier 2 Governance</td>
   </tr>
</table>

Do note:

  1. The <xsl:apply-templates> instruction doesn't explicitly specify a nodelist that must be processed. Here we rely on the fact that the only non-white-space nodes in the document are the ones that are children of nodes for which we have a matching template.

  2. For this particular XML document we could even change the match pattern of <xsl:template match="SectionName | FileName"> to just: <xsl:template match="text()"> and the transformation would still produce the wanted result.

  3. The use of the <xsl:strip-space> directive.

Upvotes: 2

Tomalak
Tomalak

Reputation: 338336

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

  <xsl:template match="/">
    <table>
      <xsl:apply-templates select="//SectionName | //FileName" />
    </table>
  </xsl:template>

  <xsl:template match="SectionName | FileName">
    <tr>
      <td><xsl:value-of select="." /></td>
    </tr>
  </xsl:template>

</xsl:stylesheet>

Upvotes: 3

marc_s
marc_s

Reputation: 755217

Something like that should do the trick:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="html" indent="yes"/>

    <xsl:template match="/">
      <table>
        <xsl:copy>
            <xsl:apply-templates />
        </xsl:copy>
      </table>
    </xsl:template>

  <xsl:template match="SectionName">
    <tr>
      <td>
        <xsl:value-of select="."/>
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="Document">
    <tr>
      <td>
        <xsl:value-of select="FileName"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

Marc

Upvotes: 1

Related Questions