Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to eliminate xmlns="" entries produced by XSLT transform of one XML doc to another XML doc

Ok, I've seen numerous variations on this question, but none exactly answer what I'm trying to solve and perhaps I'm just too dense to see how to apply one of the other answers to what I'm trying to do.

I have some XML that looks something like the following:

<?xml version="1.0" encoding="utf-8"?>
<message>
  <cmd id="api_info">
    <api-version>1.0</api-version>
    <api-build>1.0.0.0</api-build>
  </cmd>
</message>

Now I have an XSLT transform that I'm applying to this XML. The XSLT is similar to the following:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                version="2.0">

    <xsl:output method="xml" version="1.0" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates select="message"/>
    </xsl:template>

    <xsl:template match="message">
        <xsl:element name="message" xmlns="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/message/cmd/@id">
        <xsl:variable name="_commandType" select="/message/cmd/@id"/>
        <xsl:element name="messageHeader">
            <xsl:element name="cmdType">
                <xsl:value-of select="$_commandType"/>
            </xsl:element>
        </xsl:element>

        <xsl:element name="messageBody">
            <xsl:choose>
                <xsl:when test="$_commandType = 'api_info'">
                    <xsl:element name="apiInfoBody">
                        <xsl:element name="apiVersion">
                            <xsl:value-of select="/message/cmd/api-version"/>
                        </xsl:element>
                        <xsl:element name="apiBuild">
                            <xsl:value-of select="/message/cmd/api-build"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
                <xsl:when test="$_commandType = 'communicationError'">
                    <xsl:element name="communicationErrorBody">
                        <xsl:element name="errorCode">
                            <xsl:value-of select="error-code"/>
                        </xsl:element>
                        <xsl:element name="badCmd">
                            <xsl:value-of select="bad-cmd"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

The output I get is basically what I want and looks like the following:

<?xml version="1.0" encoding="UTF-8"?>
<message xmlns="http://www.companyname.com/schemas/product/Version001">
    <messageHeader xmlns="">
        <cmdType>api_info</cmdType>
    </messageHeader>
    <messageBody xmlns="">
        <apiInfoBody>
            <apiVersion>1.0</apiVersion>
            <apiBuild>1.0.0.0</apiBuild>
        </apiInfoBody>
    </messageBody>
</message>

But what I don't want are the xmlns="" attributes in the <messageHeader> and <messageBody> elements.

Now I've found that if I explicitly specify the namespace in the XSLT for those elements, then the unwanted attribute gets pushed down one level to the children of those attributes.

I could just go through my entire XSLT and explicitly add the xmlns=""http://www.companyname.com/schemas/product/Version001" attribute to each of my xsl:element definitions, but I know that there must be a more elegant way. We programmers are far too lazy to not have a shortcut for this kind of nonsense. If my XSLT didn't consist of something as simple as the shortened example, I be tempted to do it that way. But I know there must be a better way.

Does anyone know what I'm missing here?

Thanks,

AlarmTripper

like image 603
AlarmTripper Avatar asked Dec 04 '09 02:12

AlarmTripper


People also ask

How do you transform one XML to another XML document using XSLT transform?

The standard way to transform XML data into other formats is by Extensible Stylesheet Language Transformations (XSLT). You can use the built-in XSLTRANSFORM function to convert XML documents into HTML, plain text, or different XML schemas. XSLT uses stylesheets to convert XML into other data formats.

How do I disable escaping output in XSLT?

If you code disable-output-escaping="yes" , the character > is written instead. The XSLT processor uses this attribute only if you use the html or xml output methods. If you use <xsl:output method="test"> , the attribute is ignored becasue output escaping is not done for the text output method.

What is xmlns in XSLT?

In XML a namespace is a collection of names used for elements and attributes. A URI (usually, a URL) is used to identify a particular collection of names.

What is exclude result prefixes in XSLT?

The exclude-result-prefixes attribute in both XSLT 1.0 and XSLT 2.0 allows for the exclusion of certain namespace declarations in the output document.


1 Answers

Use exclude-result-prefixes on the xsl:stylesheet tag with the prefix "#default"

The reference in w3c for this is HERE

EDIT: OK, I should have studied your XSL more carefully. Move the xmlns on the message tag up to the stylesheet tag. This will put ALL the result elements in the same namespace and result in one namespace attribute on the message tag. I ran this in Oxygen/XML and got the output you want.

like image 146
Jim Garrison Avatar answered Oct 01 '22 03:10

Jim Garrison