I am using an identity transformation and template matching to remap an XML element. I need this element to selectively populate when two predicate conditions are met and I'm attempting to do so within the same match statement. So far I am only able to get one of the predicates to match, I suspect I may be violating the process order of control but cannot find a resolution.
In the below XML I need to change text value inside of the node CdtTrfTxInf/PmtTpInf/CtgyPurp/Cd
to "SALA". However, I only want this replacement to occur if both of the following conditions are true:
CalculatedField
= "AD_HOC"AND
CdtrAgt/FinInstnId/PstlrAdr/Ctry
= "NL"If both of those conditions are not true then instead I want the entire CtgyPurp
node silenced.
I also need to remove the CalculatedField
node entirely as it is purely a reference value and does not belong in the output.
<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn>
<HeaderInfo>
<Field1>Yes</Field1>
<Field2>No</Field2>
<Field3>No</Field3>
</HeaderInfo>
<PmtInf>
<CdtTrfTxInf>
<InstrId>Payment1</InstrId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<CtgyPurp>
<Cd>CASH</Cd>
</CtgyPurp>
</PmtTpInf>
<InstdAmt Ccy="EUR">11111</InstdAmt>
<CdtrAgt>
<FinInstnId>
<PstlAdr>
<Ctry>NL</Ctry>
</PstlAdr>
</FinInstnId>
</CdtrAgt>
<CalculatedField name="Payment_Category">AD_HOC</CalculatedField>
</CdtTrfTxInf>
<CdtTrfTxInf>
<InstrId>Payment2</InstrId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<CtgyPurp>
<Cd>CASH</Cd>
</CtgyPurp>
</PmtTpInf>
<InstdAmt Ccy="EUR">22222</InstdAmt>
<CdtrAgt>
<FinInstnId>
<PstlAdr>
<Ctry>US</Ctry>
</PstlAdr>
</FinInstnId>
</CdtrAgt>
<CalculatedField name="Payment_Category">AD_HOC</CalculatedField>
</CdtTrfTxInf>
<CdtTrfTxInf>
<InstrId>Payment3</InstrId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<CtgyPurp>
<Cd>CASH</Cd>
</CtgyPurp>
</PmtTpInf>
<InstdAmt Ccy="EUR">33333</InstdAmt>
<CdtrAgt>
<FinInstnId>
<PstlAdr>
<Ctry>NL</Ctry>
</PstlAdr>
</FinInstnId>
</CdtrAgt>
<CalculatedField name="Payment_Category">Junk</CalculatedField>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
Here is the XSL I have attempted so far. It will make the "SALA" replacement at the CtgyPurp/Cd level, but the multiple predicate matching is fails to silence the node for the two predicate statements I built in to the match statement.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
exclude-result-prefixes="xs"
xpath-default-namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
version="2.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/Document/CstmrCdtTrfInitn/PmtInf">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CdtTrfTxInf[CdtrAgt/FinInstnId/PstlAdr/Ctry/text()='NL'][CalculatedField[@name='Payment_Category']='AD_HOC']/PmtTpInf/CtgyPurp/Cd/text()">
<xsl:text>SALA</xsl:text>
</xsl:template>
<xsl:template match="CdtTrfTxInf[CalculatedField[@name='Payment_Category']!='AD_HOC'][CdtrAgt/FinInstnId/PstlAdr/Ctry/text()!='NL']/PmtTpInf/CtgyPurp"/>
<xsl:template match="CdtTrfTxInf/CalculatedField"/>
</xsl:stylesheet>
Based on these conditions at each node
The desired XML output would look like this:
<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn>
<HeaderInfo>
<Field1>Yes</Field1>
<Field2>No</Field2>
<Field3>No</Field3>
</HeaderInfo>
<PmtInf>
<CdtTrfTxInf>
<InstrId>Payment1</InstrId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<CtgyPurp>
<Cd>SALA</Cd>
</CtgyPurp>
</PmtTpInf>
<InstdAmt Ccy="EUR">11111</InstdAmt>
<CdtrAgt>
<FinInstnId>
<PstlAdr>
<Ctry>NL</Ctry>
</PstlAdr>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
<CdtTrfTxInf>
<InstrId>Payment2</InstrId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
<InstdAmt Ccy="EUR">22222</InstdAmt>
<CdtrAgt>
<FinInstnId>
<PstlAdr>
<Ctry>US</Ctry>
</PstlAdr>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
<CdtTrfTxInf>
<InstrId>Payment3</InstrId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
<InstdAmt Ccy="EUR">33333</InstdAmt>
<CdtrAgt>
<FinInstnId>
<PstlAdr>
<Ctry>NL</Ctry>
</PstlAdr>
</FinInstnId>
</CdtrAgt>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
Any suggestions on how to update my predicate matching or replace them with more appropriate techniques would be greatly appreciated.Thanks in advance.
I think your described conditions to remove CtgyPurp
would be expressed as
<xsl:template match="CdtTrfTxInf[not(CdtrAgt/FinInstnId/PstlAdr/Ctry/text()='NL') or not(CalculatedField[@name='Payment_Category']='AD_HOC')]/PmtTpInf/CtgyPurp"/>