0

将动态 xml 数据解析为 html 表时出现问题。XML如下。

<results>
  <result id="1" desc="Voltage and current">
    <measure desc="VOLT" value="1.0" />
    <measure desc="AMPERE" value="2.0" />
  </result>
  <result id="2" desc="Current-1">
    <measure desc="AMPERE" value="5.0" />
  </result>
</results>

我想要一个像这样的html表:

ID   DESC                VOLT   AMPERE
1    Voltage and current 1.0    2.0
2    Current-1                  5.0

注意第二个电压列的空单元格。ID 和 DESC 取自 result/@id 和 result/@desc,其余列名应来自 measure/@desc

列名不应该重复,我设法编写了这么远的代码,但是当我开始添加我的度量时,我需要匹配每个度量/@desc 以更正表中的列。我尝试了双嵌套循环来首先匹配所有唯一的列名,然后再次循环所有度量以匹配列标题。但是 xslt 解析器向我抛出了 NPE!抱歉,我无法在未连接的计算机上显示任何代码。

我在 SO 上浏览了很多 Q/A,但对我的具体问题没有帮助。

提前致谢

注意:如果有人提出更简洁的格式,我可以以任何方式更改 XML 格式以使解析更容易。

4

1 回答 1

1

如果您使用的是 XSLT1.0,您可以使用一种称为“Muenchian”分组的技术来获取不同的度量描述,这将构成您的头行的基础,也可用于输出每一行的值。

首先,您定义一个键来通过它们的@desc属性查找度量元素

<xsl:key name="measures" match="measure" use="@desc" />

然后,要获得不同的度量描述,您可以遍历组中首先出现的度量元素,以获取它们的给定@desc属性

<xsl:apply-templates 
   select="result/measure[generate-id() = generate-id(key('measures', @desc)[1])]"
   mode="header" />

然后,对于您的标题,您只需有一个模板来输出描述。

<xsl:template match="measure" mode="header">
   <th>
      <xsl:value-of select="@desc" />
   </th>
</xsl:template>

对于每个结果行,都会做类似的事情,并遍历所有不同的度量值,但唯一的区别是您必须将当前结果元素作为参数传递,以供以后使用。

<xsl:apply-templates 
   select="/results/result/measure[generate-id() = generate-id(key('measures', @desc)[1])]" 
   mode="data">
  <xsl:with-param name="result" select="." />
</xsl:apply-templates>

然后,在这次与度量匹配的模板中,您可以使用匹配的@desc属性访问结果元素中的度量并且 id 没有这样的属性,单元格不输出任何内容)

<xsl:template match="measure" mode="data">
   <xsl:param name="result" />
   <td>
      <xsl:value-of select="$result/measure[@desc = current()/@desc]/@value" />
   </td>
</xsl:template>

这是完整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="measures" match="measure" use="@desc" />

   <xsl:template match="/results">
      <table>
         <tr>
            <th>ID</th>
            <th>DESC</th>
            <xsl:apply-templates select="result/measure[generate-id() = generate-id(key('measures', @desc)[1])]" mode="header" />
         </tr>
         <xsl:apply-templates select="result" />
      </table>
   </xsl:template>

   <xsl:template match="result">
      <tr>
         <td><xsl:value-of select="@id" /></td>
         <td><xsl:value-of select="@desc" /></td>
         <xsl:apply-templates select="/results/result/measure[generate-id() = generate-id(key('measures', @desc)[1])]" mode="data">
            <xsl:with-param name="result" select="." />
         </xsl:apply-templates>
      </tr>
   </xsl:template>

   <xsl:template match="measure" mode="header">
      <th>
         <xsl:value-of select="@desc" />
      </th>
   </xsl:template>

   <xsl:template match="measure" mode="data">
      <xsl:param name="result" />
      <td>
         <xsl:value-of select="$result/measure[@desc = current()/@desc]/@value" />
      </td>
   </xsl:template>
</xsl:stylesheet>

请注意模式属性的使用,因为您有两个与度量元素匹配的模板,它们以不同的方式起作用。

当应用于您的输入 XML 时,将输出以下内容

<table>
   <tr>
      <th>ID</th>
      <th>DESC</th>
      <th>VOLT</th>
      <th>AMPERE</th>
   </tr>
   <tr>
      <td>1</td>
      <td>Voltage and current</td>
      <td>1.0</td>
      <td>2.0</td>
   </tr>
   <tr>
      <td>2</td>
      <td>Current-1</td>
      <td/>
      <td>5.0</td>
   </tr>
</table>
于 2012-11-02T15:43:54.113 回答