add namespace + prefix to XML using XSL

2019-01-26 04:40发布

问题:

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

回答1:

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>


回答2:

<xsl:template match="*">
  <xsl:element name="{local-name()}" namespace="http://my.ns.uri">
    <xsl:apply-templates />
  </xsl:element>
</xsl:template>


回答3:

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>