add namespace + prefix to XML using XSL
Asked Answered
I

3

19

I hope you can help... Let's assume I have following XML:

<data>
   <token>
      <sessionId>12345</sessionId>         
      <userId>john</userId>
      <moreInfo>
         <bla> .....
         </bla>
      </moreInfo>
   </token>
</data>

And I need this to become

<login:data xmlns:login="http://my.ns.uri">
       <login:token>
          <login:sessionId>12345</sessionId>         
          <login:userId>john</userId>
          <login:moreInfo>
             <login:bla> .....
             </login:bla>
          </login:moreInfo>
       </login:token>
    </login:data>

Can I do this with XSL? I did try but failed miserably ... Any help would be greatly appreciated!

Thanks, Jan

Interrupt answered 10/5, 2010 at 13:49 Comment(3)
Actually, what you produced is bad XML. You want xmlns:login="http://my.ns.uri".Flitter
you are right, that is what I want. xmlns:login="my.ns.uri" but what woud be the XSL to do something like that?Interrupt
Good question (+1). See my answer for a complete and correct solution. :)Musicology
M
19

Use:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:login="http://my.ns.uri">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*">
  <xsl:element name="login:{name()}" namespace="http://my.ns.uri">
    <xsl:copy-of select="namespace::*"/>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document, the wanted, correct result is produced:

<login:data xmlns:login="http://my.ns.uri">
   <login:token>
      <login:sessionId>12345</login:sessionId>
      <login:userId>john</login:userId>
      <login:moreInfo>
         <login:bla> .....
         </login:bla>
      </login:moreInfo>
   </login:token>
</login:data>
Musicology answered 10/5, 2010 at 14:5 Comment(0)
B
0
<xsl:template match="*">
  <xsl:element name="{local-name()}" namespace="http://my.ns.uri">
    <xsl:apply-templates />
  </xsl:element>
</xsl:template>
Bar answered 10/5, 2010 at 13:54 Comment(2)
All right, I understand this. But how can I change the prefixes of all the elements?Interrupt
Prefixes are something, that is quite fluid in XML. I mean, that the spec says explicitly, that they are arbitrary. So, your XSLT processor would be free to change them to whatever it likes. However, every (known to me) XSLT engine re-uses the prefixes that you wrote in your opening <xsl:stylesheet> tag, if there aren't reasons to not do this (like XSLT's exclude-result-prefix).Bar
N
0

XSLT 2.0 is more efficient and compact. It supports to add namespaces to node directly. We don't need to define anything in the starting of stylesheet as well.

Here is the spec : creating namespace prefix

Use :

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:template match="*">
  <xsl:element name="login:{name()}" xmlns:login="http://my.ns.uri">
   <xsl:namespace name="login">http://my.ns.uri</xsl:namespace>
   <xsl:value-of select="node()"/>
   <xsl:apply-templates select="*"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

It will give the output :

<login:data xmlns:login="http://my.ns.uri">
   <login:token>
      <login:sessionId>12345</login:sessionId>
      <login:userId>john</login:userId>
      <login:moreInfo>
         <login:bla> .....
         </login:bla>
      </login:moreInfo>
   </login:token>
</login:data>
Naresh answered 27/8, 2016 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.