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.

zx485
  • 28,498
  • 28
  • 50
  • 59
PI2004
  • 3
  • 1
  • 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. – michael.hor257k Apr 23 '19 at 22:45
  • 1
    Possible duplicate of [How can I add namespaces to the root element of my XML using XSLT?](https://stackoverflow.com/questions/15981488/how-can-i-add-namespaces-to-the-root-element-of-my-xml-using-xslt) – Tom Blodget Apr 23 '19 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. – Michael Kay Apr 23 '19 at 23:15

4 Answers4

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.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
Alejandro
  • 1,882
  • 6
  • 13
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>
zx485
  • 28,498
  • 28
  • 50
  • 59
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::*"/>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
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>
PI2004
  • 3
  • 1