0

I am writing a XSLT script and my objective is to insert the namespace ( http://www.COMP.com/upp/readxml/09) with the root element. I wrote several variations and 2 of my codes partially resolves it.

  1. XSLT Code AB -- This one inserts the namespace but all the attribute values are concatenated and no tags are provided.
  2. XSLT Code PQ -- This one inserts the namespace but change the hierarchy of second node and put it as a root element.

CODE AB:

<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:tns="http://www.COMP.com/upp/readxml/09">
    <xsl:output method="xml"/>
    <xsl:template match="*">
        <xsl:variable name="elname">
            <xsl:text disable-output-escaping="yes">tns:</xsl:text>
            <xsl:value-of select="local-name()"/>
        </xsl:variable>     
                <xsl:element name="tns:{local-name()}">
                    <xsl:apply-templates select="@* | node()"/>             
                </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Code PQ:

<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
    <xsl:output method="xml"/>
    <xsl:template match="*" priority="1">
        <xsl:element name="{local-name()}" namespace="http://www.COMP.com/upp/readxml/09">
         <xsl:copy-of copy-namespaces="no" select="*[local-name() != 'RootDocument']"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

INPUT XML:

<?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<RootDocument xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
    <System Id="GOLD" />
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z" />
    <Timezone Id="UTC" />   
    <CorrelationID Id="" />
  </Header>
 <Channels> 
    <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A" />     
    </Channel>
  </Channels>
</RootDocument>

EXPECTED Output XML:

<?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<RootDocument xmlns="http://www.COMP.com/upp/readxml/09" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
    <System Id="GOLD" />
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z" />
    <Timezone Id="UTC" />   
    <CorrelationID Id="" />
  </Header>
 <Channels> 
    <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A" />     
    </Channel>
  </Channels>
</RootDocument>

OR

<?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<RootDocument xmlns="http://www.COMP.com/upp/readxml/09">
<Header>
    <System Id="GOLD" />
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z" />
    <Timezone Id="UTC" />   
    <CorrelationID Id="" />
  </Header>
 <Channels> 
    <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A" />     
    </Channel>
  </Channels>
</RootDocument>

Can you please suggest how to get the attribute correctly in XML or any other way to just insert namespace with keeping rest of the XML same.

3
  • What you show is far from "keeping rest of the XML same". In your expected output, all elements are in the same namespace as the root element - so all need to be processed alike. Commented Apr 23, 2019 at 22:45
  • 1
    Possible duplicate of How can I add namespaces to the root element of my XML using XSLT? Commented Apr 23, 2019 at 22:46
  • Note that in XSLT's data model (XDM), namespaces are not attributes; you need to think about how to give elements in the result tree the right expanded name (= uri / local name pair), not about how to generate namespace prefixes or namespace declarations. Commented Apr 23, 2019 at 23:15

4 Answers 4

0

You can use the following templates to get the second version of the desired outcome:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="*">
        <xsl:element name="{local-name()}" namespace="http://www.COMP.com/upp/readxml/09">
          <xsl:apply-templates select="node()|@*" />
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:copy select="@*" />
    </xsl:template>

</xsl:stylesheet>

The output is:

<?xml version="1.0"?>
<RootDocument xmlns="http://www.COMP.com/upp/readxml/09">
    <Header>
        <System Id="GOLD"/>
        <Creation_Datetime Datetime="2019-02-19T17:53:38Z"/>
        <Timezone Id="UTC"/>
        <CorrelationID Id=""/>
    </Header>
    <Channels>
        <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
            <ChannelID ID="LC:2A"/>
        </Channel>
    </Channels>
</RootDocument>
Sign up to request clarification or add additional context in comments.

Comments

0

You are transforming elements in the empty namespace to some fixed namespace. So this stylesheet

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[namespace-uri()='']">
        <xsl:element name="{name()}" namespace="http://www.COMP.com/upp/readxml/09">
            <xsl:copy-of select="namespace::*"/>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Output:

<RootDocument xmlns="http://www.COMP.com/upp/readxml/09"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Header>
    <System Id="GOLD"/>
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z"/>
    <Timezone Id="UTC"/>
    <CorrelationID Id=""/>
  </Header>
  <Channels>
    <Channel StartDate="2019-01-01T00:00:00-05:00" 
             EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A"/>
    </Channel>
  </Channels>
</RootDocument>

Do note: namespace axis is deprecated since XPath 2.0, meaning that "If XPath 1.0 compatibility mode is false, then support for the namespace axis is implementation-defined", so you might get the expected result in the second format instead. In practice, I'm only aware of one XSLT processor that doesn't handle namespace axis: Mozilla Firefox internal XSLT processor, wich it does not implement the namespace axis even when it's only an XSLT 1.0 processor.

Comments

0

The minimalist version:

XSLT 1.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="us-ascii" standalone="yes" indent="yes"/>

<xsl:template match="*">
    <xsl:element name="{local-name()}" namespace="http://www.COMP.com/upp/readxml/09">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

This will produce the 2nd result shown in your question. To get the 1st output (with its redundant namespace declarations), change:

<xsl:copy-of select="@*"/>

to:

<xsl:copy-of select="@* | namespace::*"/>

Comments

0

Thanks everyone for responding to my query. All of the above solutions are working and in the meantime i was also trying and this is what I developed which also gives the desired outcome.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*" priority="1">
        <xsl:element name="{local-name()}" namespace="http://www.COMP.com/upp/readxml/09">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Comments

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.