XSLT 2.0:通过匹配一个子节点并比较其他子节点来选取 XML 节点
XSLT 2.0 : picking up XML node by matching one child node and comparing other
我输入了 XML 如下:
<parent>
<payment>
<id>123456</id>
<type>CANCELLED</type>
<date>2020-12-03</date>
<amount>100</amount>
</payment>
<payment>
<id>234567</id>
<type>FORCE</type>
<date>2020-12-01</date>
<amount>200</amount>
</payment>
<payment>
<id>345678</id>
<type>CANCELLED</type>
<date>2020-12-01</date>
<amount>300</amount>
</payment>
<payment>
<id>456789</id>
<type>FORCE</type>
<date>2020-12-01</date>
<amount>400</amount>
</payment>
<payment>
<id>456788</id>
<type>CANCELLED</type>
<date>2020-12-01</date>
<amount>500</amount>
</payment>
</parent>
现在,我们需要 type = 'CANCELLED' 的节点,并且棘手的条件是在这些已取消的付款中,如果日期相等,那么我们需要选择具有最高 ID 的节点。因此,在上面的样本输入中,只应选择第 1 个和第 5 个节点。第一个节点的日期与任何其他节点都不匹配,因此它被选中。虽然第 5 个节点的日期与第 3 个节点匹配,但第 5 个节点被选中,因为它具有更高的 ID。
为了实现这一点,我尝试在 XSLT 下编写,
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="input" select="parent"/>
<xsl:template match="/">
<xsl:for-each select="parent/payment[type='CANCELLED']">
<xsl:choose>
<xsl:when test="date = $input/payment[type='CANCELLED']/date">
<xsl:message>
<xsl:value-of select="amount"/>
</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="amount"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
for-each 是必需的,因为在实际示例中我们正在提取一些值,因此我们需要调整 for-each 循环条件或在其中编写 if 条件。我尝试用整个输入 xml 声明变量输入,并将每次迭代中选择的节点与输入节点进行比较,但随后它也与自身匹配。我正朝着正确的方向前进吗?请指导。
提前致谢。
要识别具有相同 date
的 payment
使用分组,然后在每个组中 select 具有 highest/maximum id 的项目:
<xsl:for-each-group select="//payment[type = 'CANCELLED']" group-by="date">
<xsl:copy-of select="current-group()[id = max(current-group()/id)]"/>
</xsl:for-each-group>
我输入了 XML 如下:
<parent>
<payment>
<id>123456</id>
<type>CANCELLED</type>
<date>2020-12-03</date>
<amount>100</amount>
</payment>
<payment>
<id>234567</id>
<type>FORCE</type>
<date>2020-12-01</date>
<amount>200</amount>
</payment>
<payment>
<id>345678</id>
<type>CANCELLED</type>
<date>2020-12-01</date>
<amount>300</amount>
</payment>
<payment>
<id>456789</id>
<type>FORCE</type>
<date>2020-12-01</date>
<amount>400</amount>
</payment>
<payment>
<id>456788</id>
<type>CANCELLED</type>
<date>2020-12-01</date>
<amount>500</amount>
</payment>
</parent>
现在,我们需要 type = 'CANCELLED' 的节点,并且棘手的条件是在这些已取消的付款中,如果日期相等,那么我们需要选择具有最高 ID 的节点。因此,在上面的样本输入中,只应选择第 1 个和第 5 个节点。第一个节点的日期与任何其他节点都不匹配,因此它被选中。虽然第 5 个节点的日期与第 3 个节点匹配,但第 5 个节点被选中,因为它具有更高的 ID。
为了实现这一点,我尝试在 XSLT 下编写,
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="input" select="parent"/>
<xsl:template match="/">
<xsl:for-each select="parent/payment[type='CANCELLED']">
<xsl:choose>
<xsl:when test="date = $input/payment[type='CANCELLED']/date">
<xsl:message>
<xsl:value-of select="amount"/>
</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="amount"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
for-each 是必需的,因为在实际示例中我们正在提取一些值,因此我们需要调整 for-each 循环条件或在其中编写 if 条件。我尝试用整个输入 xml 声明变量输入,并将每次迭代中选择的节点与输入节点进行比较,但随后它也与自身匹配。我正朝着正确的方向前进吗?请指导。
提前致谢。
要识别具有相同 date
的 payment
使用分组,然后在每个组中 select 具有 highest/maximum id 的项目:
<xsl:for-each-group select="//payment[type = 'CANCELLED']" group-by="date">
<xsl:copy-of select="current-group()[id = max(current-group()/id)]"/>
</xsl:for-each-group>