我有一些像这样的分层XML:
<node text="a" value="1">
<node text="gga" value="5">
<node text="dh" value="9">
<node text="tyfg" value="4">
</node>
</node>
</node>
<node text="dfhgf" value="7">
<node text="fdsg" value="2">
</node>
</node>
</node>
元素的名称一直向下(“节点”),并且层次的深度事先不知道 - 在上面的示例中,最深的叶子是四个向下,但它可以是任何深度。
我需要做的是将此XML并将其展平为HTML表格。表中的列数应等于最深元素的深度,以及每个元素的value属性的列。 “值”应出现在表的最右列,因此输出行不能有不规则的边。每个节点都应该有一行,无论它处于什么级别。上面的例子应该转换成:
<table>
<tr>
<td>a</td>
<td></td>
<td></td>
<td></td>
<td>1</td>
</tr>
<tr>
<td>a</td>
<td>gga</td>
<td></td>
<td></td>
<td>5</td>
</tr>
<tr>
<td>a</td>
<td>gga</td>
<td>dh</td>
<td></td>
<td>9</td>
</tr>
<tr>
<td>a</td>
<td>gga</td>
<td>dh</td>
<td>tyfg</td>
<td>4</td>
</tr>
<tr>
<td>a</td>
<td>dfhgf</td>
<td></td>
<td></td>
<td>7</td>
</tr>
<tr>
<td>a</td>
<td>dfhgf</td>
<td>fdsg</td>
<td></td>
<td>2</td>
</tr>
</table>
任何人都有一些聪明的XSLT可以实现这个目标吗?
答案 0 :(得分:3)
这不是你需要的(因为它留下了一个锯齿状的表),但它仍然可以用于html
<xsl:template match="/">
<html>
<head>
</head>
<body>
<table>
<xsl:apply-templates select="//node" mode="row" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="node" mode="row">
<tr>
<xsl:apply-templates select="ancestor-or-self::node" mode="popcell"/>
<xsl:apply-templates select="node[1]" mode="emptycell"/>
</tr>
</xsl:template>
<xsl:template match="node" mode="popcell">
<td><xsl:value-of select="@text"/></td>
</xsl:template>
<xsl:template match="node" mode="emptycell">
<td></td>
<xsl:apply-templates select="node[1]" mode="emptycell"/>
</xsl:template>
第2版:嗯,我对它的自我满足程度要低得多:P,但以下消除了锯齿状:
<xsl:variable name="depth">
<xsl:for-each select="//node">
<xsl:sort select="count(ancestor::node)" data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="count(ancestor::node)+1"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<html>
<head>
</head>
<body>
<table>
<xsl:apply-templates select="//node" mode="row" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="node" mode="row">
<tr>
<xsl:apply-templates select="ancestor-or-self::node" mode="popcell"/>
<xsl:call-template name="emptycells">
<xsl:with-param name="n" select="($depth)-count(ancestor-or-self::node)"/>
</xsl:call-template>
<td><xsl:value-of select="@value"/></td>
</tr>
</xsl:template>
<xsl:template match="node" mode="popcell">
<td><xsl:value-of select="@text"/></td>
</xsl:template>
<xsl:template name="emptycells">
<xsl:param name="n" />
<xsl:if test="$n > 0">
<td></td>
<xsl:call-template name="emptycells">
<xsl:with-param name="n" select="($n)-1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
答案 1 :(得分:0)
这个XSLT 1.0解决方案可以做到这一点。
XSLT代码:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<!-- some preparation -->
<xsl:variable name="vAllNodes" select="//node" />
<!-- find out the deepest nested node -->
<xsl:variable name="vMaxDepth">
<xsl:for-each select="$vAllNodes">
<xsl:sort
select="count(ancestor::node)"
data-type="number"
order="descending"
/>
<xsl:if test="position() = 1">
<xsl:value-of select="count(ancestor-or-self::node)" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<!-- select a list of nodes, merely to iterate over them -->
<xsl:variable name="vIteratorList" select="
$vAllNodes[position() <= $vMaxDepth]
" />
<!-- build the table -->
<xsl:template match="/">
<table>
<!-- the rows will be in document order -->
<xsl:apply-templates select="$vAllNodes" />
</table>
</xsl:template>
<!-- build the rows -->
<xsl:template match="node">
<xsl:variable name="self" select="." />
<tr>
<!-- iteration instead of recursion -->
<xsl:for-each select="$vIteratorList">
<xsl:variable name="vPos" select="position()" />
<td>
<!-- the ancestor axis is indexed the other way around -->
<xsl:value-of select="
$self/ancestor-or-self::node[last() - $vPos + 1]/@text
" />
</td>
</xsl:for-each>
<td>
<xsl:value-of select="@value" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
输出:
<table>
<tr>
<td>a</td>
<td></td>
<td></td>
<td></td>
<td>1</td>
</tr>
<tr>
<td>a</td>
<td>gga</td>
<td></td>
<td></td>
<td>5</td>
</tr>
<tr>
<td>a</td>
<td>gga</td>
<td>dh</td>
<td></td>
<td>9</td>
</tr>
<tr>
<td>a</td>
<td>gga</td>
<td>dh</td>
<td>tyfg</td>
<td>4</td>
</tr>
<tr>
<td>a</td>
<td>dfhgf</td>
<td></td>
<td></td>
<td>7</td>
</tr>
<tr>
<td>a</td>
<td>dfhgf</td>
<td>fdsg</td>
<td></td>
<td>2</td>
</tr>
</table>