带有动态标题的XSLT的XML到HTML表

时间:2011-11-21 13:15:27

标签: xslt

我的问题与XML to HTML table with XSLT有点类似。

我在XML中定义了如下字典:

<dictionary>
    <languages>
        <language>en</language>
        <language>ja</language>
    </languages>
    <entries>
        <entry id="1">
            <en>Test</en>
            <ja>テスト</ja>
        </entry>
        <entry id="2">
            <en>Test2</en>
            <ja>テスト2</en>
        </entry>
    </entries>
</dictionary>

我想在XHTML中输出以下内容:

<table>
    <thead>
        <tr>
            <th>en</th>
            <th>ja</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Test</td>
            <td>テスト</td>
        </tr>
        <tr>
            <td>Test2</td>
            <td>テスト2</td>
        </tr>
    </tbody>
</table>

我根据XML to HTML table with XSLT修改了答案如下:

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

 <xsl:template match="//dictionary/entries">
     <table><xsl:apply-templates select="entry"/></table>
 </xsl:template>

 <xsl:template match="entry[1]">
  <thead><tr><xsl:apply-templates select="*" mode="header"/></tr></thead>
  <xsl:call-template name="standardRow"/>
 </xsl:template>

 <xsl:template match="entry" name="standardRow">
  <tbody><tr><xsl:apply-templates select="*"/></tr></tbody>
 </xsl:template>

 <xsl:template match="entry/*">
  <td><xsl:apply-templates select="node()"/></td>
 </xsl:template>

 <xsl:template match="entry/*" mode="header">
  <th><xsl:value-of select="name()"/></th>
 </xsl:template>
</xsl:stylesheet>

问题是我可能有如下输入:

<dictionary>
    <languages>
        <language>en</language>
        <language>ja</language>
            <language>id</language>
    </languages>
    <entries>
        <entry id="1">
            <en>Test</en>
            <ja>テスト</ja>
        </entry>
        <entry id="2">
            <ja>テスト2</ja>
            <en>Test2</en>
            <id>uji2</id>
        </entry>
    </entries>
</dictionary>

您可能已经理解,XSLT使用第一个entry节点来定义列名,并且不生成列id。此外,如果在entry中更改了语言顺序,则<td>不会按顺序显示。

根据上面的输入,我想要以下输出:

<table>
    <thead>
        <tr>
            <th>en</th>
            <th>ja</th>
            <th>id</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Test</td>
            <td>テスト</td>
            <td></td>
        </tr>
        <tr>
            <td>Test2</td>
            <td>テスト2</td>
            <td>Uji2</td>
        </tr>
    </tbody>
</table>

这是我第一次使用XSLT而我真的不知道如何做到这一点。我想我可以使用languages节点。请注意,XML输入格式是灵活的,即使我需要更改格式,我也欢迎任何建议。

1 个答案:

答案 0 :(得分:1)

以下是样式表示例:

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

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

  <xsl:key name="k1" match="entry/*" use="concat(generate-id(..), '|', local-name())"/>

  <xsl:variable name="languages" select="/dictionary/languages/language"/>

  <xsl:template match="dictionary">
    <xsl:apply-templates select="entries"/>
  </xsl:template>

  <xsl:template match="entries">
    <table>
      <thead>
        <tr>
          <xsl:apply-templates select="$languages" mode="header"/>
        </tr>
      </thead>
      <tbody>
        <xsl:apply-templates/>
      </tbody>
    </table>
  </xsl:template>

  <xsl:template match="language" mode="header">
    <th>
      <xsl:value-of select="."/>
    </th>
  </xsl:template>

  <xsl:template match="entry">
    <tr>
      <xsl:apply-templates select="$languages">
        <xsl:with-param name="entry" select="current()"/>
      </xsl:apply-templates>
    </tr>
  </xsl:template>

  <xsl:template match="language">
    <xsl:param name="entry"/>
    <td>
      <xsl:value-of select="key('k1', concat(generate-id($entry), '|', .))"/>      
    </td>
  </xsl:template>
</xsl:stylesheet>