tags:

views:

88

answers:

1

Hi,

I'm trying to process an SVG file with XSLT. I am having behaviors I don't understand, that involves the doctype declaration.

Here are two tests I've done. The first one gives me the expected result and the second gives me a result I don't understand. (tested with saxon and xalan).

Stylesheet used for the two tests :

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="text" encoding="UTF-8"/>

    <xsl:template match="text()" >
    </xsl:template>

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


    <xsl:template match="svg">
        <xsl:text>svg</xsl:text>
        <xsl:apply-templates />
    </xsl:template>
</xsl:stylesheet>

Test n°1

source file :

<?xml version="1.0"?>
<svg width="768" height="430">

</svg>

result :

/svg

Test n°2

source file :

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20001102//EN"
"http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd"&gt;
<svg width="768" height="430">

</svg>

result :

/

Why does the doctype declaration modifies the behavior of the processing ?

+1  A: 

The SVG elements are in the SVG namespace.

The DTD defines this, so:

<xsl:template match="svg"> 

is matching an element with the name of svg, but in no namespace. All the elements in the XML document are in the SVG namespace and this template doesn't match any node.

This explains the output.

Solution: Replace the template matching svg with one that matches svg in the SVG namespace, as in the following transformation:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:s="http://www.w3.org/2000/svg"
 >
    <xsl:output method="text" encoding="UTF-8"/>

    <xsl:template match="text()" >
    </xsl:template>

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


    <xsl:template match="s:svg">
        <xsl:text >svg</xsl:text>
        <xsl:apply-templates  />
    </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20001102//EN"
"http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd"&gt;
<svg width="768" height="430" >

</svg>

the wanted result is produced:

/svg

Update:

Several people asked me "How a DTD can set a (default) namespace?"

Here is an answer: XML and DTDs with it were made a W3C Recommendation before namespaces made it. In pre-namespace XML a namespace declaration is simply an attribute.

DTD's can specify "default attributes" -- attributes, which may be ommitted from an instance but will be automatically added with a default value.

So, one way to define a default namespace in a DTD is to define an xmlns default attribute for the top element of the document.

Dimitre Novatchev
Thanks. I thought that DTD was not aware of namespaces at all. And I certainly did'nt expect that a DTD could set a namespace !
barjak
@barjak: I updated my answer with explanation how a DTD can define a namespace for the document it defines.
Dimitre Novatchev