我的XML结构看起来像这样:
<root>
<header>First header</header>
<type1>Element 1:1</type1>
<type2>Element 1:2</type2>
<header>Second header</header>
<type1>Element 2:1</type1>
<type3>Element 3:1</type3>
<header>Third header</header>
<type1>Element 3:1</type1>
<type2>Element 3:2</type2>
<type1>Element 3:3</type1>
<type2>Element 3:4</type2>
</root>
当然,标题数量未知。在每个标头下,都有未知数的元素(树不同类型)。每个标头下方的每种类型的许多元素可能为零。我无法控制这种结构,因此我无法更改/改进。
我要生成的是此html:
<h2>First header</h2>
<table>
<tr>
<th>Type 1</th>
<td>Element 1:1</td>
</tr>
<tr>
<th>Type 2</th>
<td>Element 1:2</td>
</tr>
</table>
<h2>Second header</h2>
<table>
<tr>
<th>Type 1</th>
<td>Element 2:1</td>
</tr>
<tr>
<th>Type 3</th>
<td>Element 2:2</td>
</tr>
</table>
<h2>third header</h2>
<table>
<tr>
<th>Type 1</th>
<td>Element 3:1</td>
</tr>
<tr>
<th>Type 2</th>
<td>Element 3:2</td>
</tr>
<tr>
<th>Type 1</th>
<td>Element 3:3</td>
</tr>
<tr>
<th>Type 2</th>
<td>Element 3:4</td>
</tr>
</table>
每个标头将是HTML标头(级别2),然后我希望所有其他元素直到下一个标头 。
我的第一个想法是制作与标题元素匹配的模板:
<xsl:template match="header">
<h2><xsl:value-of select="text()" /></h2>
<table>
???
</table>
</xsl:template>
我认为我可以替换"?"在兄弟姐妹之后的所有上进行代码迭代,直到下一个标头元素并将它们变成表行。
这是一个好主意吗?
如果是,我该怎么做?如果不是,什么是更好的解决方案?
我正在使用XSLT 1.0。
实现此目的的一种方法,将非头部元素通过其先前的header
元素
<xsl:key name="type" match="*[not(self::header)]" use="generate-id(preceding-sibling::header[1])" />
然后,您将仅选择header
Elements
<xsl:apply-templates select="header" />
以及与此header
元素匹配的模板中,您可以通过使用键
type
元素 <xsl:for-each select="key('type', generate-id())">
尝试此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" />
<xsl:key name="type" match="*[not(self::header)]" use="generate-id(preceding-sibling::header[1])" />
<xsl:template match="root">
<xsl:apply-templates select="header" />
</xsl:template>
<xsl:template match="header">
<h2><xsl:value-of select="." /></h2>
<table>
<xsl:for-each select="key('type', generate-id())">
<tr>
<th><xsl:value-of select="local-name()" /></th>
<th><xsl:value-of select="." /></th>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
请注意,这不包括将节点名称type1
转换为Type 1
的问题,但我将为您留下该练习....