FairyLiquid
FairyLiquid

Reputation: 11

Xslt to copy inner xml without unused namespaces

I wish to remove a couple of unused namespaces from a resulting output from an xslt stylesheet.

The xml to feed in is a wrapper around another xml message which is seen in the BodyMessage element. An example of the entire xml can bee seen below:

<?xml version="1.0" encoding="utf-8"?>
<ns0:Wrapper xmlns:ns0="http://ref.fairyliquidplc.ads/Schema/Fairy/Wrapper/1.0" xmlns:mco="http://ref.fairyliquidplc.ads/Schema/Fairy/Common/1.0">
  <TaskName>SomeTaskName</TaskName>
  <TaskStatus>Start</TaskStatus>
  <Id>Y/0070/0010</Id>
  <BodyMessage>
    <tva:TVAMain rightsOwner="FAIRY" xmlns:tva="urn:tva:metadata:2004">
        <tva:Colour>red</tva:Colour>
        <tva:Size>12</tva:Size>
        <tva:Style>Skinny</tva:Style>
        <tva:Fabric>Denim</tva:Fabric>
      </tva:TVAMain>
  </BodyMessage>
</ns0:Wrapper>

When I try to extract the xml out of the BodyMessage element I get unused namespaces returned

xmlns:ns0="http://ref.fairyliquidplc.ads/Schema/Fairy/Wrapper/1.0"
xmlns:mco="http://ref.fairyliquidplc.ads/Schema/Fairy/Common/1.0"  

These are not required but I do not understand how to remove them within my xslt.

Please note I DO want to keep

xmlns:tva="urn:tva:metadata:2004"

The stylesheet I used is:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tva="urn:tva:metadata:2004"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns="http://www.w3.org/1999/xhtml">

<xsl:output encoding="UTF-8" method="xml" omit-xml-declaration="no" version="1.0" />

<xsl:template match="/">

    <xsl:variable name="completeTva" select="//tva:TVAMain" />
    <xsl:copy-of select ="$completeTva"/>

</xsl:template>

The output of the stylesheet is:

<?xml version="1.0" encoding="utf-8"?>
<tva:TVAMain rightsOwner="FAIRY" xmlns:tva="urn:tva:metadata:2004" xmlns:ns0="http://ref.fairyliquidplc.ads/Schema/Fairy/Wrapper/1.0" xmlns:mco="http://ref.fairyliquidplc.ads/Schema/Fairy/Common/1.0">
<tva:Colour>red</tva:Colour>
<tva:Size>12</tva:Size>
<tva:Style>Skinny</tva:Style>
<tva:Fabric>Denim</tva:Fabric>

What I require is:

<?xml version="1.0" encoding="utf-8"?>
<tva:TVAMain rightsOwner="FAIRY" xmlns:tva="urn:tva:metadata:2004">
<tva:Colour>red</tva:Colour>
<tva:Size>12</tva:Size>
<tva:Style>Skinny</tva:Style>
<tva:Fabric>Denim</tva:Fabric>

Any help would be greatly appreciated. :)

Upvotes: 1

Views: 1742

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

This transformation (Sorry, this is a bug in the SO code-formatter!):

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:tva="urn:tva:metadata:2004"
  xmlns:ns0="http://ref.fairyliquidplc.ads/Schema/Fairy/Wrapper/1.0"
  xmlns:mco="http://ref.fairyliquidplc.ads/Schema/Fairy/Common/1.0"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vtoDiscard" select=
  "document('')
    /*/namespace::*[name()='ns0' or name()='mco']"/>


 <xsl:template match="tva:*">
  <xsl:element  name="{name()}"
                namespace="urn:tva:metadata:2004">
   <xsl:copy-of select="namespace::*[not(. = $vtoDiscard)]"/>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>

 <xsl:template  match="text()[not(ancestor::BodyMessage)]"/>
</xsl:stylesheet>

when applied on the provided XML document:

<ns0:Wrapper
xmlns:ns0="http://ref.fairyliquidplc.ads/Schema/Fairy/Wrapper/1.0" 
xmlns:mco="http://ref.fairyliquidplc.ads/Schema/Fairy/Common/1.0">
  <TaskName>SomeTaskName</TaskName>
  <TaskStatus>Start</TaskStatus>
  <Id>Y/0070/0010</Id>
  <BodyMessage>
    <tva:TVAMain rightsOwner="FAIRY"
    xmlns:tva="urn:tva:metadata:2004">
        <tva:Colour>red</tva:Colour>
        <tva:Size>12</tva:Size>
        <tva:Style>Skinny</tva:Style>
        <tva:Fabric>Denim</tva:Fabric>
      </tva:TVAMain>
  </BodyMessage>
</ns0:Wrapper> 

produces the wanted, correct result:

<tva:TVAMain xmlns:tva="urn:tva:metadata:2004" rightsOwner="FAIRY">
   <tva:Colour>red</tva:Colour>
   <tva:Size>12</tva:Size>
   <tva:Style>Skinny</tva:Style>
   <tva:Fabric>Denim</tva:Fabric>
</tva:TVAMain>

Explanation:

Both xsl:copy and xsl:copy-of copy an element together with the namespace nodes that belong to it.

The way to strip some namespace nodes off an element is to re-create it using the xsl:element, then to copy from the original element only the wanted namespace nodes.

Upvotes: 1

Related Questions