XSL-копии узлов без xmlns

У меня есть конкретная проблема. Я должен преобразовать структуру XML в другую, где базовый XSD - тот же, различный только определение пространства имен. Первая часть проста, потому что здесь я должен использовать сопоставление полей. Вторая часть - простая копия. И вот проблема. Скопированный "основной" node содержит исходный атрибут xmlns. Мне нужно удалить этот "атрибут".

База xml:

<?xml version="1.0" encoding="UTF-8"?>
<S2SCTIcf:SCTIcfBlkCredTrf xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf SCTIcfBlkCredTrf.xsd">
    <S2SCTIcf:SndgInst>XXXXXXX0</S2SCTIcf:SndgInst>
    <S2SCTIcf:RcvgInst>YYYYYYY0</S2SCTIcf:RcvgInst>
    <S2SCTIcf:FileRef>2013111200800546</S2SCTIcf:FileRef>
    <S2SCTIcf:SrvcId>SCT</S2SCTIcf:SrvcId>
    <S2SCTIcf:TstCode>T</S2SCTIcf:TstCode>
    <S2SCTIcf:FType>ICF</S2SCTIcf:FType>
    <S2SCTIcf:FDtTm>2013-11-12T16:26:31</S2SCTIcf:FDtTm>
    <S2SCTIcf:NumCTBlk>1</S2SCTIcf:NumCTBlk>
    <S2SCTIcf:NumPCRBlk>0</S2SCTIcf:NumPCRBlk>
    <S2SCTIcf:NumRFRBlk>0</S2SCTIcf:NumRFRBlk>
    <S2SCTIcf:NumROIBlk>0</S2SCTIcf:NumROIBlk>
    <S2SCTIcf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
        <GrpHdr>
            <MsgId>xxddccxxaaa</MsgId>
            <CreDtTm>2013-11-12T16:26:31</CreDtTm>
            <NbOfTxs>1</NbOfTxs>
            <TtlIntrBkSttlmAmt Ccy="EUR">469.12</TtlIntrBkSttlmAmt>
            <IntrBkSttlmDt>2013-11-13</IntrBkSttlmDt>
            <SttlmInf>
                <SttlmMtd>CLRG</SttlmMtd>
                <ClrSys>
                    <Prtry>ST2</Prtry>
                </ClrSys>
            </SttlmInf>
            <InstgAgt>
                <FinInstnId>
                    <BIC>XXXXXXX0</BIC>
                </FinInstnId>
            </InstgAgt>
        </GrpHdr>
        <CdtTrfTxInf>
            <PmtId>
                <EndToEndId>1114405599,1114382976</EndToEndId>
                <TxId>F3232323232</TxId>
            </PmtId>
            <PmtTpInf>
                <SvcLvl>
                    <Cd>SEPA</Cd>
                </SvcLvl>
            </PmtTpInf>
            <IntrBkSttlmAmt Ccy="EUR">469.12</IntrBkSttlmAmt>
            <ChrgBr>SLEV</ChrgBr>
            <Dbtr>
                <Nm>ddffrrddsaasas</Nm>
                <PstlAdr>
                    <Ctry>HU</Ctry>
                    <AdrLine>dssdsdsdsdsdaas</AdrLine>
                </PstlAdr>
            </Dbtr>
            <DbtrAcct>
                <Id>
                    <IBAN>HU26XXXXXXXXXXXXXX</IBAN>
                </Id>
            </DbtrAcct>
            <DbtrAgt>
                <FinInstnId>
                    <BIC>CCCCHUH0</BIC>
                </FinInstnId>
            </DbtrAgt>
            <CdtrAgt>
                <FinInstnId>
                    <BIC>CVCVCVCVCVC</BIC>
                </FinInstnId>
            </CdtrAgt>
            <Cdtr>
                <Nm>XXXXX</Nm>
                <PstlAdr>
                    <Ctry>DE</Ctry>
                </PstlAdr>
            </Cdtr>
            <CdtrAcct>
                <Id>
                    <IBAN>DE12vvvvvvvhghhg</IBAN>
                </Id>
            </CdtrAcct>
            <RmtInf>
                <Ustrd>0000000000,0000000000 </Ustrd>
            </RmtInf>
        </CdtTrfTxInf>
    </S2SCTIcf:FIToFICstmrCdtTrf>
</S2SCTIcf:SCTIcfBlkCredTrf>

xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns0="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf"
    xmlns:sw8="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02"
    xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf" exclude-result-prefixes="xs ns0 ">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="var1_SCTIcfBlkCredTrf" select="ns0:SCTIcfBlkCredTrf"/>
        <S2SCTScf:SCTScfBlkCredTrf
            xsi:schemaLocation="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf SCTScfBlkCredTrf.xsd"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf">
            <xsl:for-each select="$var1_SCTIcfBlkCredTrf">
                <S2SCTScf:SndgInst>
                    <xsl:value-of select="string(ns0:RcvgInst)"/>
                </S2SCTScf:SndgInst>
            </xsl:for-each>
            <xsl:for-each select="$var1_SCTIcfBlkCredTrf">
                <S2SCTScf:RcvgInst>
                    <xsl:value-of select="string(ns0:SndgInst)"/>
                </S2SCTScf:RcvgInst>
            </xsl:for-each>
            <xsl:for-each select="$var1_SCTIcfBlkCredTrf">
                <S2SCTScf:SrvcId>
                    <xsl:value-of select="string(ns0:SrvcId)"/>
                </S2SCTScf:SrvcId>
            </xsl:for-each>
            <xsl:for-each select="$var1_SCTIcfBlkCredTrf">
                <S2SCTScf:TstCode>
                    <xsl:value-of select="string(ns0:TstCode)"/>
                </S2SCTScf:TstCode>
            </xsl:for-each>
            <S2SCTScf:FType>SCF</S2SCTScf:FType>
            <xsl:for-each select="$var1_SCTIcfBlkCredTrf">
                <S2SCTScf:FileRef>
                    <xsl:value-of select="string(ns0:FileRef)"/>
                </S2SCTScf:FileRef>
            </xsl:for-each>
            <S2SCTScf:RoutingInd>DIR</S2SCTScf:RoutingInd>
            <xsl:for-each select="$var1_SCTIcfBlkCredTrf">
                <S2SCTScf:FileBusDt>
                    <xsl:value-of select="string(ns0:FDtTm)"/>
                </S2SCTScf:FileBusDt>
            </xsl:for-each>
            <S2SCTScf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
                <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                    <GrpHdr>
                        <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                            <MsgId>
                                <xsl:value-of select="string(sw8:GrpHdr/sw8:MsgId)"/>
                            </MsgId>
                        </xsl:for-each>
                        <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                            <CreDtTm>
                                <xsl:value-of select="string(sw8:GrpHdr/sw8:CreDtTm)"/>
                            </CreDtTm>
                        </xsl:for-each>
                        <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                            <NbOfTxs>
                                <xsl:value-of select="string(sw8:GrpHdr/sw8:NbOfTxs)"/>
                            </NbOfTxs>
                        </xsl:for-each>
                        <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                            <xsl:variable name="var2_TtlIntrBkSttlmAmt"
                                select="sw8:GrpHdr/sw8:TtlIntrBkSttlmAmt"/>
                            <TtlIntrBkSttlmAmt>
                                <xsl:attribute name="Ccy" namespace="">
                                    <xsl:value-of select="string($var2_TtlIntrBkSttlmAmt/@Ccy)"/>
                                </xsl:attribute>
                                <xsl:value-of
                                    select="string(number(string($var2_TtlIntrBkSttlmAmt)))"/>
                            </TtlIntrBkSttlmAmt>
                        </xsl:for-each>
                        <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                            <IntrBkSttlmDt>
                                <xsl:value-of select="string(sw8:GrpHdr/sw8:IntrBkSttlmDt)"/>
                            </IntrBkSttlmDt>
                        </xsl:for-each>
                        <SttlmInf>
                            <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                                <SttlmMtd>
                                    <xsl:value-of
                                        select="string(sw8:GrpHdr/sw8:SttlmInf/sw8:SttlmMtd)"/>
                                </SttlmMtd>
                            </xsl:for-each>
                            <ClrSys>
                                <xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
                                    <Prtry>
                                        <xsl:value-of
                                            select="string(sw8:GrpHdr/sw8:SttlmInf/sw8:ClrSys/sw8:Prtry)"
                                        />
                                    </Prtry>
                                </xsl:for-each>
                            </ClrSys>
                        </SttlmInf>
                        <InstdAgt>
                            <FinInstnId>
                                <xsl:for-each
                                    select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:GrpHdr/sw8:InstgAgt">
                                    <BIC>
                                        <xsl:value-of select="string(sw8:FinInstnId/sw8:BIC)"/>
                                    </BIC>
                                </xsl:for-each>
                            </FinInstnId>
                        </InstdAgt>
                    </GrpHdr>
                    <xsl:copy-of select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />
                </xsl:for-each>
            </S2SCTScf:FIToFICstmrCdtTrf>
        </S2SCTScf:SCTScfBlkCredTrf>
    </xsl:template>
</xsl:stylesheet>

Неправильная часть вывода:

...
     </InstdAgt>
  </GrpHdr>
  <CdtTrfTxInf xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf">
     <PmtId>
        <EndToEndId>1114405599,1114382976</EndToEndId>
        <TxId>F3232323232</TxId>
 ...

Я не хочу, чтобы атрибут xmlns: S2SCTIcf = "urn: S2SCTIcf: xsd: $SCTIcfBlkCredTrf" .

Есть ли у кого-нибудь идеи?

Спасибо!

Фери

Ответ 1

Ваша проблема в том, что

<xsl:copy-of select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />

копирует node из исходного дерева, включая его "узлы пространства имен", т.е. объявления пространства имен, которые были в области видимости в этой точке исходного документа. Когда этот node сериализуется, любой из этих узлов пространства имен, которые еще не действуют в этой точке выходного документа, будет объявлен сериализатором.

Если вы смогли использовать XSLT 2.0, вы можете попробовать установить copy-namespaces="no" в copy-of, но это не вариант в XSLT 1.0. Поэтому вместо использования copy-of вам нужно использовать шаблоны для копирования этого node (и всех его потомков рекурсивно) без включения узлов пространства имен. Самый простой способ сделать это - объявить два дополнительных шаблона

<xsl:template match="*" mode="copy">
  <xsl:element name="{name()}" namespace="{namespace-uri()}">
    <xsl:apply-templates select="@*|node()" mode="copy" />
  </xsl:element>
</xsl:template>

<xsl:template match="@*|text()|comment()" mode="copy">
  <xsl:copy/>
</xsl:template>

а затем замените copy-of на

<xsl:apply-templates mode="copy"
   select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />

Трюк здесь заключается в том, что xsl:element создает новый элемент node, который имеет одно и то же имя и пространство имен, что и исходное, вместо копирования исходного node, поэтому он не копирует пространство имен узлы.

Ответ 2

Вы можете использовать вариант ответа здесь, чтобы получить то, что вы хотите.

В принципе, вы должны создать шаблон для восстановления этого элемента без каких-либо пространств имен. Таким образом, вы добавили бы следующие два шаблона в ваш текущий XSLT:

<xsl:template match="*" mode="copy-no-namespaces">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
    </xsl:element>
</xsl:template>

<xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
    <xsl:copy/>
</xsl:template>

И затем обновите свой copy-of до

<xsl:apply-templates select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" mode="copy-no-namespaces"/>