在特定的兄弟节点

时间:2017-12-05 21:14:46

标签: xml xslt xslt-2.0

我正在尝试使用Identity Transformation和上下文节点中子节点的谓词匹配在特定位置添加新的XML元素。我可以成功添加元素,但XML的顺序很重要,我当前的xsl脚本将新元素放在我的模板匹配语句的上下文节点中,实际上将新元素放置为'不按顺序' ;兄弟节点。以下是我的源XML:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
   <CstmrCdtTrfInitn>
      <PmtInf>
         <CdtTrfTxInf>
            <CdtrAgt>
               <FinInstnId>
                  <Nm>Exciting Place</Nm>
               </FinInstnId>
               <BrnchId>
                  <Nm>Big Building</Nm>
                  <PstlAdr>
                     <Ctry>BR</Ctry>
                  </PstlAdr>
               </BrnchId>
            </CdtrAgt>
            <Cdtr>
               <Nm>/POP:Other</Nm>
            </Cdtr>
            <CdtrAcct>
               <Id>
                  <IBAN>123456789123456789</IBAN>
               </Id>
               <Ccy>USD</Ccy>
               <Nm>Winston Churchill</Nm>
            </CdtrAcct>
            <Tax>
               <TaxId>100</TaxId>
            </Tax>
            <RmtInf>
               <Ustrd>Test</Ustrd>
            </RmtInf>
         </CdtTrfTxInf>
      </PmtInf>
   </CstmrCdtTrfInitn>
</Document>

我需要添加元素&#34; Purp / Cd&#34;在&#34; Tax&#34;之后的XML文档节点ONLY当&#34; CdtAgt / BrnchId / Ctry&#34;兄弟节点的值为&#34; BR&#34;。我尝试了以下XSL脚本,但它将元素放在错误的位置;我试图调整谓词[]匹配语句,没有任何运气。这是我的剧本:

<?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"
    xpath-default-namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
    exclude-result-prefixes="xs xsl"
    version="2.0">

    <xsl:output indent="yes"/>

    <!-- Generic identity template -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <!-- Copy the children of the current node -->
    <xsl:template name="copy-children">
        <xsl:copy-of select="./*"/>
    </xsl:template>

    <xsl:template match="*/CdtTrfTxInf[CdtrAgt/BrnchId/PstlAdr/Ctry[text() = 'BR']]">
        <xsl:copy>

            <xsl:element name="Purp" namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
                <xsl:element name="Cd" namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
                    <xsl:value-of select="'P1019'"/>
                </xsl:element>
            </xsl:element>
            <xsl:call-template name="copy-children"/>

        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

此样式表生成一个不正确对齐的XML文档,其中&#34; Purp / Cd&#34;节点紧跟在&#34; CstmrCdtTrfInitn / PmtInf&#34;节点而不是&#34; Tax&#34;之后的所需位置节点;以下不良输出:

 <?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
   <CstmrCdtTrfInitn>
      <PmtInf>
         <CdtTrfTxInf>
            <Purp>
               <Cd>P1019</Cd>
            </Purp>
            <CdtrAgt>
               <FinInstnId>
                  <Nm>Exciting Place</Nm>
               </FinInstnId>
               <BrnchId>
                  <Nm>Big Building</Nm>
                  <PstlAdr>
                     <Ctry>BR</Ctry>
                  </PstlAdr>
               </BrnchId>
            </CdtrAgt>
            <Cdtr>
               <Nm>/POP:Other</Nm>
            </Cdtr>
            <CdtrAcct>
               <Id>
                  <IBAN>123456789123456789</IBAN>
               </Id>
               <Ccy>USD</Ccy>
               <Nm>Winston Churchill</Nm>
            </CdtrAcct>
            <Tax>
               <TaxId>100</TaxId>
            </Tax>
            <RmtInf>
               <Ustrd>Test</Ustrd>
            </RmtInf>
         </CdtTrfTxInf>
      </PmtInf>
   </CstmrCdtTrfInitn>
</Document>

我需要在&#34; Tax&#34;之后放置新节点。节点但不知道如何在上下文节点级别使用谓词匹配时产生正确的结果;我想这是我的问题,但不知道如何调整我的脚本。非常感谢您的建议。

下面的所需输出:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
   <CstmrCdtTrfInitn>
      <PmtInf>
         <CdtTrfTxInf>
            <CdtrAgt>
               <FinInstnId>
                  <Nm>Exciting Place</Nm>
               </FinInstnId>
               <BrnchId>
                  <Nm>Big Building</Nm>
                  <PstlAdr>
                     <Ctry>BR</Ctry>
                  </PstlAdr>
               </BrnchId>
            </CdtrAgt>
            <Cdtr>
               <Nm>/POP:Other</Nm>
            </Cdtr>
            <CdtrAcct>
               <Id>
                  <IBAN>123456789123456789</IBAN>
               </Id>
               <Ccy>USD</Ccy>
               <Nm>Winston Churchill</Nm>
            </CdtrAcct>
            <Tax>
               <TaxId>100</TaxId>
            </Tax>
            <Purp>
               <Cd>P1019</Cd>
            </Purp>
            <RmtInf>
               <Ustrd>Test</Ustrd>
            </RmtInf>
         </CdtTrfTxInf>
      </PmtInf>
   </CstmrCdtTrfInitn>
</Document>

1 个答案:

答案 0 :(得分:1)

如果您想将新节点放在Tax元素之后,则应更改模板以匹配Tax元素....

 <xsl:template match="CdtTrfTxInf[CdtrAgt/BrnchId/PstlAdr/Ctry[text() = 'BR']]/Tax">

然后,在此内部,您可以完全复制Tax节点(使用xsl:next-match,因为您正在使用XSLT 2.0),然后在其后创建新节点。

试试这个XSLT,我通过使用默认命名空间来输出新元素,我已经简化了一些。

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
    xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
    exclude-result-prefixes="xs xsl"
    version="2.0">

    <xsl:output indent="yes"/>

    <!-- Generic identity template -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="CdtTrfTxInf[CdtrAgt/BrnchId/PstlAdr/Ctry[text() = 'BR']]/Tax">
        <xsl:next-match />
        <Purp>
            <Cd>
                <xsl:text>P1019</xsl:text>
            </Cd>
        </Purp>
    </xsl:template>
</xsl:stylesheet>