1

第一次来这里。我在这个网站上搜索了很多,但没有找到与我的问题类似的例子,所以我有机会发布我的问题。

我有以下 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 的同样问题应该只在第二列。

谢谢您的帮助,

问候

安德烈-克劳德

4

1 回答 1

3

这是一个分组问题。您需要按名称对测试结果进行分组。如何执行此操作取决于您使用的是 XSLT1.0 还是 XSLT2.0。我将向您展示 XSLT1.0 解决方案,它使用了一种称为Muenchian分组的技术。

您将首先定义一个保持来查找您的测试元素

<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来简化分组)

于 2012-04-23T22:17:40.990 回答