1

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.

2 Answers 2

1

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>
Sign up to request clarification or add additional context in comments.

3 Comments

And there's one more subtlety which is that xsi:schemaLocation needs to be a pair of URIs: one for the namespace, and one for the actual location.
Thank you for your feedback. You're so great @michael.hor257k. By the way, can you tell me when I need to use the function <xsl:element name="Sample"> to the direct use of element name <Sample>? Is there a difference between the two?
@Charlotte Use the xsl:element instruction when the name or the namespace of the element must be determined at runtime. Otherwise it's better to use a literal result element.
1

You only want to do this special processing for the Document element, not for every element that has Document as an ancestor, so just change the match pattern from match="*[ancestor-or-self::Document]" to match="Document".

2 Comments

If you do that (and nothing else) it will keep the descendants of Document in no-namespace - which is not the expected output.
OK, I missed that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.