1

非常重要的注意事项:我正在使用 QtXmlPattern(一个未完全实现的 XSLT 2.0 处理器,在实现的内容中有一些错误......)

我有一个格式良好的 XML 文件,其中的数据定义在一个四级数组中,如下所示:

<a>
  <b>
    <c day="20150221">
      <d>...</d>
      <e>...</e>
    </c>
    <c day="20150222">
      <d>...</d>
      <e>...</e>
    </c>
    <c day="20150223">
      <d>...</d>
      <e>...</e>
    </c>
  </b>
  <b>
    <c day="20150219">
      <d>...</d>
      <e>...</e>
    </c>
    <c day="20150221">
      <d>...</d>
      <e>...</e>
    </c>
    <c day="20150223">
      <d>...</d>
      <e>...</e>
    </c>
  </b>
  ...
</a>

结果应该包括所有天数,但正如我们所见,每个<b>列表可能有不同的天数。然而,结果需要有所有<b>标签的所有天数。如果数据不可用,则结果可能保持为空或为零。

我找到了一种在变量中收集所有日子的方法:

<xsl:variable name="days" select="distinct-values(/a/b/c/@day)"/>

但我看不到如何生成看起来像这样的最终结果:

<table>
  <th>
    <td>20150219</td>
    <td>20150221</td>
    <td>20150222</td>
    <td>20150223</td>
  </th>
  <tr>
    <td>data from <d> tag on 20150219</td>
    <td>data from <d> tag on 20150221</td>
    <td>data from <d> tag on 20150222</td>
    <td>data from <d> tag on 20150223</td>
  </tr>
  ...[repeat for various data and calculation on the data]...
</table>

我的问题是变量不是节点列表,只是字符串列表,我不太确定如何循环遍历字符串列表。

以防万一,对于那些不了解 QXmlQuery 解析器的人,该xsl:for-each-group命令不存在。

4

2 回答 2

2

我不确定您需要什么,但有时评论尝试的解决方案比尝试解释更容易。您肯定必须使用来查找不同的属性值。

不要遍历字符串列表,而是遍历一系列c元素,这些元素的属性值是唯一的day(最终,它们是相同的)。Jeni Tennison在这里描述了我在下面使用的技术,因为它通常用于对问题进行分组。

XML 输入

在我看来,合理的输入包括d元素的实际值:

<?xml version="1.0" encoding="UTF-8"?>
<a>
  <b>
    <c day="20150221">
      <d>data from day 20150221</d>
      <e>...</e>
    </c>
    <c day="20150222">
      <d>data from day 20150222</d>
      <e>...</e>
    </c>
    <c day="20150223">
      <d>data from day 20150223</d>
      <e>...</e>
    </c>
  </b>
  <b>
    <c day="20150219">
      <d>data from day 20150219</d>
      <e>...</e>
    </c>
    <c day="20150221">
      <d>data from day 20150221</d>
      <e>...</e>
    </c>
    <c day="20150223">
      <d>data from day 20150223</d>
      <e>...</e>
    </c>
  </b>
  <!--...-->
</a>

样式表

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:key name="day-from-c" match="c" use="@day" />

    <xsl:template match="/">
      <hmtl>
        <xsl:apply-templates/>
      </hmtl>
    </xsl:template>

    <xsl:template match="a">
        <table>

            <xsl:variable name="days" select="b/c[generate-id() =
        generate-id(key('day-from-c', @day)[1])]"/>

            <xsl:for-each select="$days">
                <xsl:sort select="@day"/>
                <th>
                    <xsl:value-of select="@day"/>
                </th>
            </xsl:for-each>
            <tr>
                <xsl:for-each select="$days">
                    <xsl:sort select="@day"/>
                    <td>
                        <xsl:value-of select="/a/b/c[@day = current()/@day]/d"/>
                    </td>
                </xsl:for-each>
            </tr>
        </table>
    </xsl:template>

</xsl:transform>

HTML 输出

d如果同一天有多个元素,我仍然不清楚会发生什么。

<!DOCTYPE html
  PUBLIC "XSLT-compat">
<hmtl>
   <table>
      <th>20150219</th>
      <th>20150221</th>
      <th>20150222</th>
      <th>20150223</th>
      <tr>
         <td>data from day 20150219</td>
         <td>data from day 20150221 data from day 20150221</td>
         <td>data from day 20150222</td>
         <td>data from day 20150223 data from day 20150223</td>
      </tr>
   </table>
</hmtl>

在 xsltransform 上在线尝试此解决方案。

于 2015-02-24T09:42:50.623 回答
2

您可以(使用 XSLT 2.0,不确定您选择的处理器是否支持该功能)只需执行

<xsl:variable name="main-doc" select="/">

将主文档节点存储在稍后将要使用的变量中,然后定义一个键

<xsl:key name="by-date" match="a/b/c/d" use="../@day"/>

然后d在一天中引用项目

<xsl:for-each select="$days">
  <xsl:variable name="d-on-day" select="key('by-date', ., $main-doc)"/>

key()带有三个参数的调用在 XSLT 2.0 中是新的,如果不支持,请尝试

<xsl:for-each select="$days">
  <xsl:variable name="day" select="."/>
  <xsl:for-each select="$main-doc">
    <xsl:variable name="d-on-day" select="key('by-date', $day)"/>
    ...
  </xsl:for-each>
  ...
</xsl:for-each>

如果该key功能不可用,那么您需要将引用编写为例如

<xsl:variable name="d-elements" select="/a/b/c/d"/>

<xsl:for-each select="$days">
  <xsl:variable name="day" select="."/>
  <xsl:for-each select="$d-elements[../@day = $day]">...</xsl:for-each>
</xsl:for-each>
于 2015-02-24T09:32:05.290 回答