第一次来这里。我在这个网站上搜索了很多,并没有找到与我的问题类似的例子,所以我有机会发布我的问题。
我有以下XML文档,我想使用XSLT转换转换为XHTML。
XML输入:
<Procedure Analyse="MyAnalysis1">
<Identification Name="MetaTestA">
<Blah Name="TestA" Result="1" />
<Blah Name="TestB" Result="2" />
</Identification>
<Identification Name="MetaTestB">
<Blah Name="TestB" Result="3" />
<Blah Name="TestC" Result="4" />
</Identification>
</Procedure>
预期的XHTML输出:
<table>
<thead>
<tr>MyAnalysis1</tr>
<tr>
<td></td>
<td>MetaTestA</td>
<td>MetaTestB</td>
</tr>
</thead>
<tbody>
<tr>
<td>TestA</td>
<td>1</td>
<td></td>
</tr>
<tr>
<td>TestB</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>TestC</td>
<td></td>
<td>4</td>
</tr>
</tbody>
</table>
所以基本上我想让每一列成为MetaTest名称,将行作为MetaTestA和MetaTestB的Blah.Name和Blah.Result(可能有任意数量的列)
我很难弄清楚如何将两个表中的数据合并在一起(参见两个测试结果的TestB),这样它们就可以显示在同一行上。对于只应在第二列上的TestC也存在同样的问题。
感谢您的帮助,
此致
安德烈克劳德
答案 0 :(得分:3)
这是一个分组问题。您需要按名称对测试结果进行分组。如何执行此操作取决于您使用的是XSLT1.0还是XSLT2.0。我将向您展示XSLT1.0解决方案,它使用一种称为 Muenchian 分组的技术。
您首先要定义一个keep来查找您的测试元素
<xsl:key name="Tests" match="Blah" use="@Name"/>
然后,要在每个组中找到第一个测试结果(对应于输出表中的行),您可以这样做
<xsl:apply-templates
select="Identification/Blah[generate-id() = generate-id(key('Tests', @Name)[1])]"/>
即找到 Blah 元素,该元素恰好是该名称的键中的第一个元素。
然后,对于每个 Blah 元素,输出与标识元素对应的结果。
这是完整的XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="Tests" match="Blah" use="@Name"/>
<xsl:template match="Procedure">
<table>
<thead>
<tr>
<td rowspan="{count(Identification) + 1}">
<xsl:value-of select="@Analyse"/>
</td>
</tr>
<tr>
<td/>
<xsl:apply-templates select="Identification" mode="header"/>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="Identification/Blah[generate-id() = generate-id(key('Tests', @Name)[1])]"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="Identification" mode="header">
<td>
<xsl:value-of select="@Name"/>
</td>
</xsl:template>
<xsl:template match="Identification" mode="test">
<xsl:param name="Name"/>
<td>
<xsl:value-of select="Blah[@Name=$Name]/@Result"/>
</td>
</xsl:template>
<xsl:template match="Blah">
<tr>
<td>
<xsl:value-of select="@Name"/>
</td>
<xsl:apply-templates select="//Identification" mode="test">
<xsl:with-param name="Name" select="@Name"/>
</xsl:apply-templates>
</tr>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,输出以下内容
<table>
<thead>
<tr>
<td rowspan="3">MyAnalysis1</td>
</tr>
<tr>
<td/>
<td>MetaTestA</td>
<td>MetaTestB</td>
</tr>
</thead>
<tbody>
<tr>
<td>TestA</td>
<td>1</td>
<td/>
</tr>
<tr>
<td>TestB</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>TestC</td>
<td/>
<td>4</td>
</tr>
</tbody>
</table>
(在XSLT2.0中,您可以使用 xsl:for-each-group 来简化分组)