Processing an XML file using a public document

I am trying to render an SVG file using XSLT. I have behavior that I don't understand, this includes the doctype declaration.

Here are two tests I did. The first one gives me the expected result and the second one gives me the result which I don't understand. (tested with Saxon and Halan).

The 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 No. 1

original file:

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

</svg>

      

result:

/svg

      

Test number 2

original 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">
<svg width="768" height="430">

</svg>

      

result:

/

      

Why does doctype change the processing behavior?

+2


a source to share


1 answer


SVG elements are in the SVG namespace .

The DTD defines this, so:

<xsl:template match="svg"> 

      

matches an element with a name svg

, but not in a namespace. All elements in the XML document are in the SVG namespace and this template does not match any node.

This explains the conclusion.

Solution . Replace the template that matches the svg

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 to 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">
<svg width="768" height="430" >

</svg>

      

the desired result is obtained :

/svg

      

Update :

Several people have asked me, "How can a DTD establish a (default) namespace?"

Here's the answer: The XML and DTDs with it were made by the W3C Recommendation before namespaces did. In the pre-namespace XML, the namespace declaration is just an attribute.

The DTD can specify default attributes that can be excluded from the instance but will be automatically added with a default value.

So, one way to define a default namespace in a DTD is to define a xmlns

default attribute for the top element of the document.

+1


a source







All Articles