如何在xslt中只匹配一次节点并过滤掉它们



我有一个文件,里面有两种类型的"期刊来源";。下面是一个小样本文件

<File>   
<Record>
<employee>935388</employee>
<journal_source>Procurement_Card_Transaction_Verification</journal_source>
<amount>26.31</amount>
<wid>123</wid>
<concat_values>935388|Procurement_Card_Transaction_Verification|26.31</concat_values>
<Created_Moment>2020-12-31T20:45:45.415-08:00</Created_Moment>
<Accounting_Date>2020-12-31-08:00</Accounting_Date>
</Record>   
<Record>
<employee>935388</employee>
<journal_source>Credit_Card_Transaction_Load</journal_source>
<amount>-26.31</amount>
<wid>abc</wid>
<concat_values>935388|Credit_Card_Transaction_Load|26.31</concat_values>
<Created_Moment>2020-12-20T20:45:45.415-08:00</Created_Moment>
<Accounting_Date>2020-12-31-08:00</Accounting_Date>
</Record>
<Record>
<employee>935388</employee>
<journal_source>Credit_Card_Transaction_Load</journal_source>
<amount>-26.31</amount>
<wid>def</wid>
<concat_values>935388|Credit_Card_Transaction_Load|26.31</concat_values>
<Created_Moment>2020-12-20T20:45:45.415-08:00</Created_Moment>
<Accounting_Date>2020-12-31-08:00</Accounting_Date>
</Record>   
</File>

目标是仅输出具有journal_source类型"的节点;Credit_Card_Transaction_Load;不具有匹配的";Procurement_Card_Transaction_Verification;其还具有";Created_Moment";这大于信用卡交易的金额。通过匹配,我的意思是它们具有相同的"匹配"值;concat_values";除了一个是信贷,另一个是采购。

这里的棘手之处在于,我只能匹配一次采购交易。使用后,我无法将其考虑到其他信用卡交易中,即使它们也匹配。以下是之前提供的样本的输出需要是什么的示例(只对获得输出中的"wid"字段感兴趣(:

<File>   

<wid>def</wid>
</File>

我首先想到的是通过更新foreach循环中的映射或变量来跟踪已使用的采购事务。然后,我会确保检查该交易是否已经被用于匹配之前的另一笔信用卡交易。然而,这并不起作用,因为变量是不可变的。

我还考虑过探索XSLT3的特性,并尝试研究累加器,但没有走多远。

任何帮助都将不胜感激!

以下示例将采购交易分组到一个映射中,该映射从连接员工编号和绝对金额的字符串键到一系列Record元素,然后在信用卡交易的迭代中使用该映射来查找匹配项,如果没有,则输出信用卡交易,对于下一次迭代,匹配将从所用密钥的映射值中删除:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
expand-text="yes">

<xsl:function name="mf:get-key" as="xs:string">
<xsl:param name="record" as="element(Record)"/>
<xsl:sequence select="replace($record/concat_values, '|[^|]+|', '|')"/>
</xsl:function>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/File">
<xsl:copy>
<xsl:variable name="procurement-map" as="map(xs:string, element(Record)*)">
<xsl:map>
<xsl:for-each-group 
select="Record[journal_source = 'Procurement_Card_Transaction_Verification']" 
group-by="mf:get-key(.)">
<xsl:map-entry key="current-grouping-key()" select="current-group()"/>
</xsl:for-each-group>
</xsl:map>
</xsl:variable>
<xsl:iterate select="Record[journal_source = 'Credit_Card_Transaction_Load']">
<xsl:param name="procurement-map" select="$procurement-map"/>
<xsl:variable name="key" select="mf:get-key(.)"/>
<xsl:variable name="match" select="$procurement-map($key)[xs:dateTime(Created_Moment) gt xs:dateTime(current()/Created_Moment)][1]"/>
<xsl:if test="not($match)">
<xsl:copy>
<xsl:copy-of select="wid"/>
</xsl:copy>
</xsl:if>
<xsl:next-iteration>
<xsl:with-param name="procurement-map"
select="if (not($match)) 
then $procurement-map 
else map:put($procurement-map, $key,  $procurement-map($key) except $match)"/>
</xsl:next-iteration>
</xsl:iterate>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

最新更新