使用XSLT在表中输出子节点名称

时间:2014-06-03 18:21:52

标签: xml xslt

示例XML:

<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
</catalog>

示例XSL:

<table summary="CD Summary" border="1">

            <tr>

                <td>
                    <xsl:for-each select="//cd[1]/node()">
                    <th><xsl:value-of select="name()"/></th>
                    </xsl:for-each>
                </td>

            </tr>
            <xsl:for-each select="//cd">

            <tr>
                <xsl:for-each select="//cd/node()">
                <td>

                    <xsl:value-of select="."/>

                </td>
                </xsl:for-each>

            </tr>
            </xsl:for-each>
        </table>

输出我得到:

  • Cell A1 nothing
  • A2-A7子节点名称(CDName,艺术家,国家,公司,价格,年份)
  • Cell B1 CD名称(第1张cd)
  • Cell B2 Artist(第1张CD)
  • Cell B3 Country(of 1st cd)
  • Cell B4 Company(第1张CD)
  • Cell B5价格(第1张cd)
  • Cell B6 Year(1st cd)
  • Cell B7 CD Name(第二张cd),然后对于B上的所有cds重复上述步骤 行。

我想要一个包含子节点名称标题的表(已完成,但第一个子节点在子节点第一列之前开始一个新列),然后每个cd列在正确的标题下的自己的行中。在现实世界中,我不知道在加载页面之前每个'cd'节点将有多少个子节点。

似乎它应该非常简单,我已经尝试了几种变化,我知道它位于for-each和值的某个位置,位于正确的位置。

请帮助。

1 个答案:

答案 0 :(得分:1)

我注意到一些阻碍你获得所需输出的东西:

  • node()选择的不仅仅是元素;请尝试使用*
  • 使用//cd选择文档中的每个cd元素。如果你注意上下文,就不需要它。 (提示:您的上下文在xsl:for-each中发生了变化。)
  • 您在第一个td中有一个额外的tr

尝试这样的事情:

<xsl:template match="/*">
    <table summary="CD Summary" border="1">
        <tr>
            <xsl:for-each select="cd[1]/*">
                <th>
                    <xsl:value-of select="name()"/>
                </th>
            </xsl:for-each>
        </tr>
        <xsl:for-each select="cd">
            <tr>
                <xsl:for-each select="*">
                    <td>
                        <xsl:value-of select="."/>
                    </td>
                </xsl:for-each>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

这是使用“推送”方法的另一种选择。它是在XSLT 2.0中完成的,因为你没有指定版本......

XSLT 2.0

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

    <xsl:template match="/*">
        <table summary="CD Summary" border="1">
            <xsl:apply-templates select="cd[1]" mode="header"/>
            <xsl:apply-templates select="cd"/>
        </table>
    </xsl:template>

    <xsl:template match="cd" mode="#all">
        <tr><xsl:apply-templates mode="#current"/></tr>
    </xsl:template>

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

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

</xsl:stylesheet>