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