views:

156

answers:

1

Hi,

I've got a problem with xsl:include and default namespaces which is causing the final xml document contain nodes with the xmlns=""

In this synario I have 1 source document which is Plain Old XML and doesn't have a namespace:

<?xml version="1.0" encoding="UTF-8"?>
<SourceDoc>
    <Description>Hello I'm the source description</Description>
    <Description>Hello I'm the source description 2</Description>
    <Description/>
    <Title>Hello I'm the title</Title>
</SourceDoc>

This document is transformed into 2 different xml documents each with their own default namespace.

First Document:

<?xml version="1.0" encoding="utf-8"?>
<OutputDocType1 xmlns="http://MadeupNS1"&gt;
   <Description >Hello I'm the source description</Description>
   <Description>Hello I'm the source description 2</Description>
   <Title>Hello I'm the title</Title>
</OutputDocType1>

Second Document:

<?xml version="1.0" encoding="utf-8"?>
<OutputDocType2 xmlns="http://MadeupNS2"&gt;
   <Description>Hello I'm the source description</Description>
   <Description>Hello I'm the source description 2</Description>
   <DocTitle>Hello I'm the title</DocTitle>
</OutputDocType2>

I want to be able to re-use the template for descriptions in both of the transforms. As it's the same logic for both types of document. To do this I created a template file which was *xsl:include*d in the other 2 transformations:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

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

    <xsl:template match="Description[. != '']">
        <Description>
            <xsl:value-of select="."/>
        </Description>
    </xsl:template>
</xsl:stylesheet>

Now the problem here is that this shared transformation can't have a default Namespace as it will be different depending on which of the calling transformations calls it.

E.g. for First Document Transformation:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

    <xsl:output indent="yes" method="xml"/>
    <xsl:template match="SourceDoc">
        <OutputDocType1 xmlns="http://MadeupNS1"&gt;

            <xsl:apply-templates select="Description"/>
            <xsl:if test="Title">
                <Title>
                    <xsl:value-of select="Title"/>
                </Title>
            </xsl:if>
        </OutputDocType1>
    </xsl:template>

    <xsl:include href="Template.xsl"/>
</xsl:stylesheet>

This actually outputs it as follows:

<?xml version="1.0" encoding="utf-8"?>
<OutputDocType1 xmlns="http://MadeupNS1"&gt;
   <Description xmlns="">Hello I'm the source description</Description>
   <Description xmlns="">Hello I'm the source description 2</Description>
   <Title>Hello I'm the title</Title>
</OutputDocType1>

Here is the problem. On the description Lines I get an xmlns=""

Does anyone know how to solve this issue?

Thanks

Dave

+3  A: 

Your first xslt, which contains the literal result element Description has no default namespace. This element is therefore in no namespace, and is being explicitly rendered as such via xmlns="".

Section 6.2 of Namespaces in XML 1.0 says that:

The attribute value in a default namespace declaration MAY be empty. This has the same effect, within the scope of the declaration, of there being no default namespace.

In order to control the namespace generated in the included stylesheet you will need to pass the namespace-uri through to its templates, using a variable or param.

<!-- in the included stylesheet -->
<xsl:template match="Description[. != '']">
    <xsl:element name="Description" namespace="{$output-namespace}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

<!--
    and add this to your First Document Transformation stylesheet
    as a top level element under xsl:stylesheet
-->
<xsl:variable name="output-namespace" select="'http://MadeupNS1'"/&gt;
Lachlan Roche
Can you explain how that could be done with a variable? I did try that myself, however the calling templates couldn't update the variable name.
CraftyFella
Hi, I couldn't get it working, so i went with param's in the end..
CraftyFella