首先,我知道这个SO question有点不同。
我有一个XML文件,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>123</MsgId>
<CreDtTm>321</CreDtTm>
<NbOfTxs>10</NbOfTxs>
<CtrlSum>18700.68</CtrlSum>
<InitgPty>
<Nm>some info</Nm>
</InitgPty>
</GrpHdr>
<PmtInf>
<!-- start -->
<PmtInfId>asd</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<PmtTpInf>
<InstrPrty>NORM</InstrPrty>
<SvcLvl>
<Prtry>test</Prtry>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>date</ReqdExctnDt>
<Dbtr>
<Nm>something</Nm>
<PstlAdr>
<AdrLine>addr 1</AdrLine>
</PstlAdr>
</Dbtr>
<!-- end -->
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
<PmtInf>
<!-- start -->
<PmtInfId>asd</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<PmtTpInf>
<InstrPrty>NORM</InstrPrty>
<SvcLvl>
<Prtry>test</Prtry>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>date</ReqdExctnDt>
<Dbtr>
<Nm>something</Nm>
<PstlAdr>
<AdrLine>addr 1</AdrLine>
</PstlAdr>
</Dbtr>
<!-- end -->
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
<PmtInf>
<!-- start -->
<PmtInfId>asd</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<PmtTpInf>
<InstrPrty>NORM</InstrPrty>
<SvcLvl>
<Prtry>test</Prtry>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>date</ReqdExctnDt>
<Dbtr>
<Nm>something</Nm>
<PstlAdr>
<AdrLine>addr 1</AdrLine>
</PstlAdr>
</Dbtr>
<!-- end -->
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
<PmtInf>
<!-- start -->
<PmtInfId>asd</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<PmtTpInf>
<InstrPrty>NORM</InstrPrty>
<SvcLvl>
<Prtry>test</Prtry>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>date</ReqdExctnDt>
<Dbtr>
<Nm>something</Nm>
<PstlAdr>
<AdrLine>addr 1</AdrLine>
</PstlAdr>
</Dbtr>
<!-- end -->
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
<PmtInf></PmtInf>
部分几乎相同的结构。我想做的是:
<PmtInfId>asd</PmtInfId>
的{{1}}与第二个PmtInf
的{{1}}进行比较。如果完全匹配(如同相同的标记和文字),请移至下一个标记元素并将其与第一个<PmtInfId>asd</PmtInfId>
中的PmtInf
与来自第二个<PmtMtd>TRF</PmtMtd>
的{{1}}进行比较PmtInf
...如果在我们到达<PmtMtd>TRF</PmtMtd>
标记之前总是完美匹配,请执行此操作。PmtInf
时,表示第一个<CdtTrfTxInf>
的第一部分与第二个<CdtTrfTxInf>
的第一部分相同。此时,从第一个PmtInf
的{{1}}部分后面的第二个PmtInf
移动<CdtTrfTxInf></CdtTrfTxInf>
。然后,删除第二个PmtInf
部分。所以,此时,xml看起来像这样:
<CdtTrfTxInf></CdtTrfTxInf>
PmtInf
部分和第三个部分重复此过程,然后使用第四个部分重复此过程。如果有几乎完美匹配,我们应该只有一个PmtInf
标记,其中包含4个<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>123</MsgId>
<CreDtTm>321</CreDtTm>
<NbOfTxs>10</NbOfTxs>
<CtrlSum>18700.68</CtrlSum>
<InitgPty>
<Nm>some info</Nm>
</InitgPty>
</GrpHdr>
<PmtInf>
<!-- start -->
<PmtInfId>asd</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<PmtTpInf>
<InstrPrty>NORM</InstrPrty>
<SvcLvl>
<Prtry>test</Prtry>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>date</ReqdExctnDt>
<Dbtr>
<Nm>something</Nm>
<PstlAdr>
<AdrLine>addr 1</AdrLine>
</PstlAdr>
</Dbtr>
<!-- end -->
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
<PmtInf>
<!-- start -->
<PmtInfId>qwe</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<PmtTpInf>
<InstrPrty>HIGH</InstrPrty>
<SvcLvl>
<Prtry>test</Prtry>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>date</ReqdExctnDt>
<Dbtr>
<Nm>something</Nm>
<PstlAdr>
<AdrLine>addr 1</AdrLine>
</PstlAdr>
</Dbtr>
<!-- end -->
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
<PmtInf>
<!-- start -->
<PmtInfId>asd</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<PmtTpInf>
<InstrPrty>NORM</InstrPrty>
<SvcLvl>
<Prtry>test</Prtry>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>date</ReqdExctnDt>
<Dbtr>
<Nm>something</Nm>
<PstlAdr>
<AdrLine>addr 1</AdrLine>
</PstlAdr>
</Dbtr>
<!-- end -->
<CdtTrfTxInf>
<PmtId>
<InstrId>16082672122</InstrId>
<EndToEndId>16082672122</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="RON">2159.41</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>some bic</BIC>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
标记。 PmtInf
中的PmtInf
与第三个CdtTrfTxInf
中的<InstrPrty>NORM</InstrPrty>
进行比较时,请保留PmtInf
部分原样并转到下一部分。<InstrPrty>HIGH</InstrPrty>
与其上方的所有PmtInf
进行比较后,将第二个PmtInf
与第三个PmtInf
进行比较并应用相同的规则,然后将第三个与{第一个......等等。现在我可能会问太多,但这可以用XSLT完成吗?我知道我没有尝试过一件事,但我只是花了太多精力来尝试通过简单的Python字符串操作实现这一点,看起来像XSLT转换文档需要一些时间来使用语法。
我这样调用脚本:
PmtInfs
答案 0 :(得分:2)
我对是否要发布此内容表示犹豫,因为您似乎是XSLT的初学者,这是解决复杂问题的复杂解决方案。你可能需要花些时间来解决这个问题。
这是如何运作的:
在第一遍中,我们为输入XML中的每个pmt
元素生成一个PmtInf
元素,并使用包含每个节点的名称/值对的字符串填充它(元素或属性) )当前PmtInf
的后代。在给定的示例中,每个此类pmt
元素看起来类似于:
<pmt id="idp1696">[PmtInfId:asd][PmtMtd:TRF][BtchBookg:false][PmtTpInf:NORMtest][InstrPrty:NORM][SvcLvl:test][Prtry:test][ReqdExctnDt:date][Dbtr:somethingaddr 1][Nm:something][PstlAdr:addr 1][AdrLine:addr 1]</pmt>
在下一步中,我们将Muenchian grouping应用于第一遍中生成的pmt
个节点。对于每个不同的pmt
节点,我们创建一个PmtInf
元素并用以下内容填充:
相应PmtInf
元素的内容,CdtTrfTxInf
除外;
来自该组所有成员的所有CdtTrfTxInf
元素的副本。
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="ns0"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="pmt" match="ns0:pmt" use="." />
<xsl:key name="PmtInf" match="ns0:PmtInf" use="generate-id()" />
<xsl:variable name="input" select="/" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns0:CstmrCdtTrfInitn">
<!-- first pass -->
<xsl:variable name="first-pass-rtf">
<xsl:apply-templates select="ns0:PmtInf" mode="gen-key"/>
</xsl:variable>
<xsl:variable name="first-pass" select="exsl:node-set($first-pass-rtf)" />
<!-- output -->
<xsl:copy>
<xsl:copy-of select="ns0:GrpHdr"/>
<!-- for each distinct pmt -->
<xsl:for-each select="$first-pass/ns0:pmt[count(. | key('pmt', .)[1]) = 1]">
<xsl:variable name="id" select="@id" />
<xsl:variable name="ids" select="key('pmt', .)/@id" />
<PmtInf>
<!-- switch context back to XML input -->
<xsl:for-each select="$input">
<xsl:copy-of select="key('PmtInf', $id)/*[not(self::ns0:CdtTrfTxInf)]"/>
<xsl:copy-of select="key('PmtInf', $ids)/ns0:CdtTrfTxInf"/>
</xsl:for-each>
</PmtInf>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="ns0:PmtInf" mode="gen-key">
<pmt id="{generate-id()}">
<xsl:apply-templates select="@*|*" mode="gen-key"/>
</pmt>
</xsl:template>
<xsl:template match="@*|node()" mode="gen-key">
<xsl:text>[</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="."/>
<xsl:text>]</xsl:text>
<xsl:apply-templates select="@*|*" mode="gen-key"/>
</xsl:template>
<xsl:template match="ns0:CdtTrfTxInf" mode="gen-key"/>
</xsl:stylesheet>