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?
a source to share
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.
a source to share