代码之家  ›  专栏  ›  技术社区  ›  J_Cus504

在单匹配语句中使用身份变换和多谓词来沉默节点

  •  1
  • J_Cus504  · 技术社区  · 4 月前

    我正在使用身份转换和模板匹配来重新映射XML元素。当满足两个谓词条件时,我需要这个元素来选择性地填充,并且我试图在同一个match语句中这样做。到目前为止,我只能找到一个谓词进行匹配,我怀疑我可能违反了过程控制顺序,但找不到解决方案。

    在下面的XML中,我需要更改节点内的文本值 CdtTrfTxInf/PmtTpInf/CtgyPurp/Cd “SALA”。但是,我只希望在以下两个条件都成立的情况下进行替换:

    • 子节点(来自CdtTrfTxInf) CalculatedField =“AD_HOC”

    以及

    • 子节点(来自CdtTrfTxInf) CdtrAgt/FinInstnId/PstlrAdr/Ctry =“NL”

    如果这两个条件都不成立,那么我想要整个 CtgyPurp 节点静音。

    我还需要删除 计算字段 节点完全是因为它纯粹是一个引用值,不属于输出。

    <?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>
    

    这是我迄今为止尝试过的XSL。它将在CtgyPurp/Cd级别进行“SALA”替换,但多谓词匹配无法使我在匹配语句中内置的两个谓词语句的节点静音。

    <?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>
    

    基于每个节点的这些条件

    1. Ctry=“NL”&计算字段=“AD_HOC”- 预期结果:将CtgryPurp/Cd更改为“SALA”
    2. Ctry=“NL”(Ctry=“US”)&计算字段=“AD_HOC”- 预期结果:删除整个CtgryPurp节点
    3. Ctry=“NL”&已计算字段!=“AD_HOC”(计算字段=“JUNK”)- 预期结果:删除整个CtgryPurp节点

    所需的XML输出如下:

    <?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>
    

    如果您能就如何更新我的谓词匹配或用更合适的技术替换它们提出任何建议,我们将不胜感激。提前感谢。

    2 回复  |  直到 4 月前
        1
  •  2
  •   michael.hor257k    4 月前

    AFAICT,这符合您的要求:

    XSL 2.0

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="CdtTrfTxInf[CdtrAgt/FinInstnId/PstlAdr/Ctry != 'NL' or CalculatedField != 'AD_HOC']/PmtTpInf/CtgyPurp"/>
    
    <xsl:template match="CtgyPurp/Cd/text()">SALA</xsl:template> 
    
    </xsl:stylesheet>
    

    请注意,两者都不是 CalculatedField 也没有 Ctry 是兄弟姐妹 Cd.

        2
  •  0
  •   Martin Honnen    4 月前

    我认为你描述的移除条件 CtgyPurp 将表示为

    <xsl:template match="CdtTrfTxInf[not(CdtrAgt/FinInstnId/PstlAdr/Ctry/text()='NL') or not(CalculatedField[@name='Payment_Category']='AD_HOC')]/PmtTpInf/CtgyPurp"/>