Krishna
Krishna

Reputation: 51

XSLT: remove unused namespaces from XML

I want to apply XSLT to convert my existing XML to remove unused namespaces.

Sample XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Session xmlns="http://www.cloud.com/prod/v1.5" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" 
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" 
xmlns:common="http://schemas.dmtf.org/wbem/wscim/1/common" 
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" 
xmlns:vmw="http://www.cloud.com/schema/ovf" 
xmlns:ovfenv="http://schemas.dmtf.org/ovf/environment/1" 
xmlns:vmext="http://www.cloud.com/prod/extension/v1.5" 
xmlns:ns9="http://www.cloud.com/prod/networkservice/1.0" 
xmlns:ns10="http://www.cloud.com/prod/networkservice/common/1.0" 
xmlns:ns11="http://www.cloud.com/prod/networkservice/ipam/1.0" 
xmlns:ns12="http://www.cloud.com/prod/versions" 
org="Development" roles="vApp Author" user="kchaitanya" 
userId="urn:prod:user:0dc14413-74ce-4a20-8908-0e2fd1da6160" href="https://x.x.x.x/api/session" 
type="application/vnd.cloud.prod.session+xml">
    <Link rel="remove" href="https://x.x.x.x/api/session"/>
    <Link rel="down" href="https://x.x.x.x/api/admin/" type="application/vnd.cloud.admin.prod+xml"/>
    <Link rel="entityResolver" href="https://x.x.x.x/api/entity/" type="application/vnd.cloud.prod.entity+xml"/>
    <Link rel="down:extensibility" href="https://x.x.x.x/api/extensibility" type="application/vnd.cloud.prod.apiextensibility+xml"/>
    <ovf:Info>My Ovf Info</ovf:Info>
    <vmext:Extension>
        <vssd:Info> 2000 </vssd:Info>
    </vmext:Extension>
</Session>

XSLT Used:

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


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

<xsl:template match="*" >
  <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
   <xsl:variable name="vtheElem" select="."/>

   <xsl:for-each select="namespace::*">
     <xsl:variable name="vPrefix" select="name()"/>

     <xsl:if test=
      "$vtheElem/descendant::*
              [namespace-uri()=current()
             and
              substring-before(name(),':') = $vPrefix
             or
              @*[substring-before(name(),':') = $vPrefix]
              ]
      ">
      <xsl:copy-of select="." />
     </xsl:if>
   </xsl:for-each>
   <xsl:apply-templates select="node()|@*" />
  </xsl:element>
</xsl:template>
</xsl:stylesheet>

Expected Output:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Session xmlns="http://www.cloud.com/prod/v1.5" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" 
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" 
xmlns:vmext="http://www.cloud.com/prod/extension/v1.5" 
org="Development" roles="vApp Author" user="kchaitanya" 
userId="urn:prod:user:0dc14413-74ce-4a20-8908-0e2fd1da6160" href="https://x.x.x.x/api/session" 
type="application/vnd.cloud.prod.session+xml">
    <Link rel="remove" href="https://x.x.x.x/api/session"/>
    <Link rel="down" href="https://x.x.x.x/api/admin/" type="application/vnd.cloud.admin.prod+xml"/>
    <Link rel="entityResolver" href="https://x.x.x.x/api/entity/" type="application/vnd.cloud.prod.entity+xml"/>
    <Link rel="down:extensibility" href="https://x.x.x.x/api/extensibility" type="application/vnd.cloud.prod.apiextensibility+xml"/>
    <ovf:Info>My Ovf Info</ovf:Info>
    <vmext:Extension>
        <vssd:Info> 2000 </vssd:Info>
    </vmext:Extension>
</Session>

But Actual Output:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns0:Session xmlns:ns0="http://www.vmware.com/vcloud/v1.5" xmlns="http://www.cloud.com/prod/v1.5"
org="Development" roles="vApp Author" user="kchaitanya" 
userId="urn:prod:user:0dc14413-74ce-4a20-8908-0e2fd1da6160" href="https://x.x.x.x/api/session" 
type="application/vnd.cloud.prod.session+xml">
    <ns1:Link xmlns:ns1="http://www.vmware.com/vcloud/v1.5" rel="remove" href="https://x.x.x.x/api/session"/>
    <ns2:Link xmlns:ns2="http://www.vmware.com/vcloud/v1.5" rel="down" href="https://x.x.x.x/api/admin/" type="application/vnd.cloud.admin.prod+xml"/>
    <ns3:Link xmlns:ns3="http://www.vmware.com/vcloud/v1.5" rel="entityResolver" href="https://x.x.x.x/api/entity/" type="application/vnd.cloud.prod.entity+xml"/>
    <ns4:Link xmlns:ns4="http://www.vmware.com/vcloud/v1.5" rel="down:extensibility" href="https://x.x.x.x/api/extensibility" type="application/vnd.cloud.prod.apiextensibility+xml"/>
    <ns5:Info xmlns:ns5="http://schemas.dmtf.org/ovf/envelope/1" >My Ovf Info</ns5:Info>
    <ns6:Extension xmlns:ns6="http://www.cloud.com/prod/extension/v1.5" >
        <ns7:Info xmlns:ns7="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" > 2000 </ns7:Info>
    </ns6:Extension>
</ns0:Session>

I'm using java 1.8.121 and CXF 3.1.11(org.apache.cxf.interceptor.XSLTOutInterceptor) to convert the XML. The XSLT package used is, by default, "com.sun.org.apache.xalan.internal.xsltc". I've used apache-xalan 2.7.1, with the same result.

I could not test this online, as the output from the java code and that from the online xslt tests(ex: http://xsltransform.net/) are different.

Can anyone suggest, the correct way or XSLT to achieve what I'm trying to do?

Upvotes: 0

Views: 1067

Answers (1)

Michael Kay
Michael Kay

Reputation: 163322

Download Saxon to give yourself the benefit of XSLT 2.0, and then just do

<xsl:copy-of select="/" copy-namespaces="no"/>

It can be done in XSLT 1.0 but it's much more complicated.

Upvotes: 3

Related Questions