示例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>
输出我得到:
我想要一个包含子节点名称标题的表(已完成,但第一个子节点在子节点第一列之前开始一个新列),然后每个cd列在正确的标题下的自己的行中。在现实世界中,我不知道在加载页面之前每个'cd'节点将有多少个子节点。
似乎它应该非常简单,我已经尝试了几种变化,我知道它位于for-each和值的某个位置,位于正确的位置。
请帮助。
答案 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>