仅对 XSLT 中节点上的第一次出现求和

Sum only first occurrence on a node in XSLT

我 运行 遇到了一些挑战。我正在努力在不使用递归模板的情况下对子节点中包含的值求和。我有一个与此类似的来源:

<root>
   <entry>
      <recordID>001</recordID>
      <amount>500</amount>
   </entry>
   <entry>
      <recordID>001</recordID>
      <amount>200</amount>
   </entry>
   <entry>
      <recordID>002</recordID>
      <amount>500</amount>
   </entry>
   <entry>
      <recordID>003</recordID>
      <amount>400</amount>
   </entry>
   <entry>
      <recordID>004</recordID>
      <amount>100</amount>
   </entry>
</root>

我想做的是仅对第一次出现的 recordID 求和并计算这些节点。 IE。我不想包括第二个节点。所以所需的输出将是

记录数:4 总量:1500

我试过这样做,但只有 returns 0。我不确定这是不是因为您只能在 a 中引用 for each 或不引用兄弟姐妹。但这是我的第一次尝试:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsl:template match='root'>

   <xsl:value-of select='"Record Count: "'/>
   <xsl:value-of select='count(entry[recordID != following-sibling::recordID])'/>

   <xsl:value-of select='"Total Amount: "'/>
   <xsl:value-of select='sum(entry[recordID != following-sibling::recordID]/amount)'/>

</xsl:template>

</xsl:stylesheet>

但是这个只是返回了0,我也试过这个,也是不成功

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsl:template match='root'>

   <xsl:value-of select='"Record Count: "'/>
   <xsl:for-each-group select='entry' group-by='.[recordID != following-sibling::recordID]'>
       <xsl:value-of select='count(current-group())'/>
   </xsl:for-each-group>

   <xsl:value-of select='"Total Amount: "'/>
   <xsl:for-each-group select='entry' group-by='.[recordID != following-sibling::recordID]'>
       <xsl:value-of select='sum(current-group()/amount)'/>
   </xsl:for-each-group>

</xsl:template>

</xsl:stylesheet>

如果有人可以提供一些关于我如何完成此操作的见解,或对我当前代码的更正 - 我将不胜感激!

提前感谢您的任何反馈

我已经更新了您的第一个 XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsl:template match='root'>

        <xsl:value-of select='"Record Count: "'/>
        <xsl:value-of select='count(entry[not(recordID = preceding::entry/recordID)])'/>

        <xsl:value-of select='"Total Amount: "'/>
        <xsl:value-of select='sum(entry[not(recordID = preceding::entry/recordID)]/amount)'/>

    </xsl:template>

</xsl:stylesheet>

您的 XPATH entry[recordID != following-sibling::recordID] 不会为您提供不同的 entry 元素(通过它们的 recordID 区分),但我的 XPATH 会。

原因, recordID != following-sibling::recordID 意味着您正在检查是否有任何 following-sibling recordIDs 具有与当前 recordID 不同的值(首先,没有 recordID 兄弟姐妹到您输入中的任何 recordID

另一方面,当 xpath 是:
entry[not(recordID = preceding::entry/recordID)]
当前recordID与前面任意一个recordID匹配,匹配的忽略。这样只有 entry 个元素按 recordID.

分组

我建议您阅读 != 运算符如何对抗 not():
a != (b,c,d)not(a = (b,c,d)) 不一样。

这是一个使用 Muechian grouping 的 XSLT 2.0 示例(假设 XSLT 2.0 时简单地使用 is 而不是 generate-id 稍作调整):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsl:key name="entry-by-id" match="entry" use="recordID"/>

<xsl:variable name="first-records" select="root/entry[. is key('entry-by-id', recordID)[1]]"/>

<xsl:template match='root'>

   <xsl:value-of select='"Record Count: "'/>
   <xsl:value-of select='count($first-records)'/>

   <xsl:value-of select='"Total Amount: "'/>
   <xsl:value-of select='sum($first-records/amount)'/>

</xsl:template>

</xsl:stylesheet>

有了 for-each-group,您可以使用类似

的方法
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsl:template match='root'>

   <xsl:variable name="first-entries" as="element(entry)*">
        <xsl:for-each-group select='entry' group-by='recordID'>
            <xsl:copy-of select='.'/>
        </xsl:for-each-group>
    </xsl:variable>

   <xsl:value-of select='"Record Count: "'/>
   <xsl:value-of select='count($first-entries)'/>


   <xsl:value-of select='"Total Amount: "'/>
   <xsl:value-of select='sum($first-entries/amount)'/>


</xsl:template>

</xsl:stylesheet>