我正在尝试使用XSLT处理SVG文件。我有一些我不理解的行为,涉及doctype声明。
这是我做过的两项测试。第一个给了我预期的结果,第二个给了我一个我不明白的结果。 (用撒克逊和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>
源文件:
<?xml version="1.0"?>
<svg width="768" height="430">
</svg>
结果:
/svg
源文件:
<?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>
结果:
/
为什么doctype声明会修改处理的行为?
答案 0 :(得分:1)
SVG元素位于SVG名称空间。
DTD定义了这个,所以:
<xsl:template match="svg">
匹配名称为svg
的元素,但没有名称空间。 XML文档中的所有元素都在SVG名称空间中,并且此模板与任何节点都不匹配。
这解释了输出。
解决方案:将匹配svg
的模板替换为与SVG命名空间中的svg
匹配的模板,如以下转换中所示:
<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>
在提供的XML文档上应用此转换时:
<!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>
生成了想要的结果:
/svg
更新:
有几个人问我“DTD如何设置(默认)命名空间?”
这是一个答案:在命名空间创建之前,XML和DTD与它一起成为W3C推荐标准。在命名空间前的XML中,名称空间声明只是一个属性。
DTD可以指定“默认属性” - 属性,这些属性可以从实例中省略,但会自动添加默认值。
因此,在DTD中定义默认命名空间的一种方法是为文档的顶部元素定义xmlns
默认属性。