Reputation: 11270
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).
<?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>
source file :
<?xml version="1.0"?>
<svg width="768" height="430">
</svg>
result :
/svg
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">
<svg width="768" height="430">
</svg>
result :
/
Why does the doctype declaration modifies the behavior of the processing ?
Upvotes: 2
Views: 474
Reputation: 243529
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">
<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.
Upvotes: 1