类似于这个问题(有多个相关条目,但作为一个新的用户,我只能发布一个URL): Xpath Get elements that are between 2 elements的XPath XSLT:选择两个其他元素之间的元素,第二部分
我对于选择“其他/定界”元素之间出现的元素集有一个疑问。尝试使用XSLT将平面HTML表格转换为层次结构的 时会出现这种情况。我尝试在模板中使用递归,但撒克逊拒绝接受,因为它导致死锁,很可能是我的错,但让我们从头开始。
第一源数据的HTML表:
<table >
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="3" >Group 1</th>
</tr>
<tr>
<td>attribute 1.1.1</td>
<td>attribute 1.1.3</td>
<td>attribute 1.1.2</td>
</tr>
<tr>
<td>attribute 1.2.1</td>
<td>attribute 1.2.2</td>
<td>attribute 1.2.3</td>
</tr>
<tr>
<td>attribute 1.3.1</td>
<td>attribute 1.3.2</td>
<td>attribute 1.3.3</td>
</tr>
<tr>
<th colspan="3" >Group 2</th>
</tr>
<tr>
<td>attribute 2.1.1</td>
<td>attribute 2.1.3</td>
<td>attribute 2.1.2</td>
</tr>
<tr>
<td>attribute 2.2.1</td>
<td>attribute 2.2.2</td>
<td>attribute 2.2.3</td>
</tr>
<tr>
<td>attribute 2.3.1</td>
<td>attribute 2.3.2</td>
<td>attribute 2.3.3</td>
</tr>
</tbody>
</table>
XML中的目标输出是:
<groups>
<group name="Group 1">
<item attribute1="attribute 1.1.1" attribute2="attribute 1.1.3" attribute3="attribute 1.1.2"/>
<item attribute1="attribute 1.2.1" attribute2="attribute 1.2.2" attribute3="attribute 1.2.3"/>
<item attribute1="attribute 1.3.1" attribute2="attribute 1.3.2" attribute3="attribute 1.3.3"/>
</group>
<group name="Group 2">
<item attribute1="attribute 2.1.1" attribute2="attribute 2.1.3" attribute3="attribute 2.1.2"/>
<item attribute1="attribute 2.2.1" attribute2="attribute 2.2.2" attribute3="attribute 2.2.3"/>
<item attribute1="attribute 2.3.1" attribute2="attribute 2.3.2" attribute3="attribute 2.3.3"/>
</group>
</groups>
所以我想将所有的项目条目,(TR元素)和将它们添加到一个组中。这基本上归结为选择所有后续兄弟TR元素,直到我们遇到一个具有TH元素作为孩子的元素。如果我只能确定有TH孩子,表示为一组一个新的标题这个第一TR的位置,这可能是与完成:
<xsl:for-each select="tbody/tr">
<xsl:if test="th">
<xsl:element name="group">
<xsl:attribute name="name"><xsl:value-of select="th"/></xsl:attribute>
<xsl:for-each select="following-sibling::tr[position() < $positionOfNextThElement]">
<xsl:call-template name="item"/>
</xsl:for-each>
</xsl:element>
</xsl:if>
</xsl:for-each>
不过,我不能确定的位置首先遇到TR/TH标签。
如上所述,我尝试使用模板中的递归:总是调用“item”模板,并在此模板中确定是否要在下一个项目上调用它。我认为问题出在模板中调用模板。上下文中的项目不会增加?我应该交出一个参数来确定我们正在处理的项目吗?
总之,这是我想出了:
<xsl:for-each select="tbody/tr">
<xsl:if test="th">
<xsl:element name="group">
<xsl:attribute name="name"><xsl:value-of select="th"/></xsl:attribute>
<xsl:call-template name="item"/>
</xsl:element>
</xsl:if>
</xsl:for-each>
<xsl:template name="item">
<xsl:element name="item">
<xsl:attribute name="attribute1"><xsl:value-of select="following-sibling::tr[1]/td[1]"/></xsl:attribute>
<xsl:attribute name="attribute2"><xsl:value-of select="following-sibling::tr[1]/td[2]"/></xsl:attribute>
<xsl:attribute name="attribute2"><xsl:value-of select="following-sibling::tr[1]/td[3]"/></xsl:attribute>
</xsl:element>
<!-- When the next element has not got a TH tag, continue with invoking this template -->
<xsl:if test="count(following-sibling::tr[1]/th) != 1">
<xsl:call-template name="item"/>
</xsl:if>
</xsl:template>
就如何实现这一欢迎任何建议!
竖起大拇指为您的答案!这样做的好处是,所幸属性的数量是静态的。我将查看参考文档,以了解将来的分组问题。 – Holtkamp 2009-10-10 15:11:18