2

I would like to create a table structure that separates the header row by THEAD and the data rows by TBODY:

Input XML:

<Rowsets>
  <Rowset>
    <Columns>
      <Column Description="Date"/>
      <Column Description="Time"/>
    </Columns>
    <Row>
      <Date>DATA1</Date>
      <Time>DATA2</Time>
    </Row>
    <Row>
      <Date>DATA1</Date>
      <Time>DATA2</Time>
  </Rowset>
</Rowsets> 

The following XSLT does separates the header and body but I can't figure out how to wrap the tags between the data rows:

<xsl:strip-space elements="*"/>
<xsl:template match="/">
  <HTML>
    <BODY>
      <TABLE>
        <XSL:apply-templates/>
      </TABLE>
    </BODY>
  </HTML>
</xsl:template>

<xsl:template match="Columns|Row">
  <tr><xsl:apply-templates/></tr>
</xsl:template>

<xsl:template match="Columns">
  <thead><xsl:apply-templates/></thead>
</xsl:template>

<xsl:template match="Columns/*">
  <th><xsl:apply-templates select="@Description"/></th>
</xsl:template>

<xsl:template match="Row/*">
  <td><xsl:apply-templates/></td>
</xsl:template> 

Current HTML Output:

  <THEAD>
    <TR>
      <TH>Date</TH><TH>Time</TH>
    </TR>
  </THEAD>
    <TR>
      <TD>DATA1</TD><TD>DATA2</TD>
    </TR>
    <TR>
      <TD>DATA1</TD><TD>DATA2</TD>
    </TR>

How can I wrap the data rows with TBODY? Thanks!

1
  • 1
    Your template that matches "Columns|Row" will never apply to a "Columns" element, because your template that matches only "Columns" has a higher default priority (being more specific). So you might as well change match="Columns|Row" to match="Row" to make it less confusing to read. Commented Jan 12, 2012 at 18:10

2 Answers 2

3

The simplest solution is probably to add the following template to your stylesheet:

<xsl:template match="Rowset">
    <xsl:apply-templates select="Columns"/>
    <tbody>
        <xsl:apply-templates select="Row"/>
    </tbody>
</xsl:template>

Complete stylesheet (with a couple other minor changes):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="/">
        <HTML>
            <BODY>
                <TABLE>
                    <xsl:apply-templates/>
                </TABLE>
            </BODY>
        </HTML>
    </xsl:template>
    <xsl:template match="Rowset">
        <xsl:apply-templates select="Columns"/>
        <tbody>
            <xsl:apply-templates select="Row"/>
        </tbody>
    </xsl:template>
    <xsl:template match="Columns">
        <thead><tr><xsl:apply-templates/></tr></thead>
    </xsl:template>
    <xsl:template match="Columns/*">
        <th><xsl:apply-templates select="@Description"/></th>
    </xsl:template>
    <xsl:template match="Row">
        <tr><xsl:apply-templates/></tr>
    </xsl:template>
    <xsl:template match="Row/*">
        <td><xsl:apply-templates/></td>
    </xsl:template>
</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

Comments

3

You can restrict (select) what nodes shall be applyed by apply-templates. I'd use something like this:

<xsl:strip-space elements="*"/>
<xsl:template match="/">
  <HTML>
    <BODY>
      <TABLE>
        <THEAD>
          <xsl:apply-templates select="Columns"/>
        </THEAD>
        <TBODY>
          <xsl:apply-templates select="Row"/>
        </TBODY>
      </TABLE>
    </BODY>
  </HTML>
</xsl:template>

<xsl:template match="Columns|Row">
  <TR><xsl:apply-templates/></TR>
</xsl:template>

<xsl:template match="Columns/*">
  <TH><xsl:value-of select="@Description"/></TH>
</xsl:template>

<xsl:template match="Row/*">
  <TD><xsl:apply-templates/></TD>
</xsl:template> 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.