vale
vale

Reputation: 65

Remove all the XML namespaces using XSL but one

I used some XSL code, i found in another post, to remove all the namespaces from my XML document.

I used this code i used:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <!-- Stylesheet to remove all namespaces from a document -->
    <!-- NOTE: this will lead to attribute name clash, if an element contains
        two attributes with same local name but different namespace prefix -->
    <!-- Nodes that cannot have a namespace are copied as such -->

    <!-- template to copy elements -->
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <!-- template to copy the rest of the nodes -->
    <xsl:template match="comment() | text() | processing-instruction()">
        <xsl:copy/>
    </xsl:template>
	
</xsl:stylesheet>

1- Can somebody give me a simple explanation of how this code works? 2- How can i remove all the namespaces of the document but the ones in the Schema section (xs:schema)?

XML sample:

    <?xml version="1.0" encoding="utf-16"?>
<DataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Table">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="timestamp" type="xs:base64Binary" minOccurs="0" />
                <xs:element name="Name" type="xs:string" minOccurs="0" />
                <xs:element name="No_" type="xs:string" minOccurs="0" />
                <xs:element name="Account_x0020_Type" type="xs:string" minOccurs="0" />
                <xs:element name="Indentation" type="xs:int" minOccurs="0" />
                <xs:element name="Company" type="xs:int" minOccurs="0" />
                <xs:element name="ParentAccount" type="xs:string" minOccurs="0" />
                <xs:element name="nodesc" type="xs:string" minOccurs="0" />
                <xs:element name="AccountID" type="xs:int" minOccurs="0" />
                <xs:element name="Code" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <NewDataSet>
      <Table diffgr:id="Table1" msdata:rowOrder="0">
        <No_>11</No_>
        <Company>1</Company>
        <AccountID>2224</AccountID>
      </Table>
      </NewDataSet>
  </diffgr:diffgram>
</DataSet>

Desired output:

    <?xml version="1.0" encoding="utf-16"?>
<DataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Table">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="timestamp" type="xs:base64Binary" minOccurs="0" />
                <xs:element name="Name" type="xs:string" minOccurs="0" />
                <xs:element name="No_" type="xs:string" minOccurs="0" />
                <xs:element name="Account_x0020_Type" type="xs:string" minOccurs="0" />
                <xs:element name="Indentation" type="xs:int" minOccurs="0" />
                <xs:element name="Company" type="xs:int" minOccurs="0" />
                <xs:element name="ParentAccount" type="xs:string" minOccurs="0" />
                <xs:element name="nodesc" type="xs:string" minOccurs="0" />
                <xs:element name="AccountID" type="xs:int" minOccurs="0" />
                <xs:element name="Code" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr>
    <NewDataSet>
      <Table id="Table1">
        <No_>11</No_>
        <Company>1</Company>
        <AccountID>2224</AccountID>
      </Table>
      </NewDataSet>
  </diffgr>
</DataSet>

Upvotes: 0

Views: 440

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116992

You are almost there - try:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- "copy" an element while removing any namespace -->
<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
</xsl:template>

<!-- "copy" an attribute while removing any namespace -->
<xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

<!-- copy the entire schema part as is -->
<xsl:template match="xs:schema">
    <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

Added:

Is there a simple way to change the root node name from <DataSet> to <NewDataSet>?

Sure. Just add another template like this:

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

Upvotes: 2

Related Questions