Search code examples
xsltxslt-2.0

Insert schemaLocation in the XML File using XSLT v2.0


I'm having a problem inserting a schemaLocation in the XML File. I almost got the expected output but the other elements populates the schemaLocation. Here is my sample file:

INPUT:

<Sync releaseID="9.2">
<Document>
    <Group>
        <Header>
            <Field1>232</Field1>
            <Field2>dfd</Field2>
        </Header>
    </Group>
</Document>

And, I want to add the namespace and schemalocation in <Document> tag. Here is my XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="*[ancestor-or-self::Document]">
    <xsl:element name="{name()}" namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
        <xsl:attribute name="xsi:schemaLocation">urn:iso:std:iso:20022:tech:xsd:pain.001.001.03</xsl:attribute>
        <xsl:apply-templates select="*"/>
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

GENERATED OUTPUT:

<Sync releaseID="9.2">
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
    <Group xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
        <Header xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
            <Field1 xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">232</Field1>
            <Field2 xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">dfd</Field2>
        </Header>
    </Group>
</Document>

EXPECTED OUTPUT:

<Sync releaseID="9.2">
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
    <Group>
        <Header>
            <Field1>232</Field1>
            <Field2>dfd</Field2>
        </Header>
    </Group>
</Document>

How can I remove the schemaLocation in the other elements?

Thanks.


Solution

  • You need to add a template matching Document only and add the attribute there (and only there). Then change your existing template so that it matches only descendants of Document:

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="*[ancestor::Document]">
        <xsl:element name="{name()}" namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
            <xsl:apply-templates select="*"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="Document">
        <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
            <xsl:apply-templates select="*"/>
        </Document>
    </xsl:template>
    
    </xsl:stylesheet>