使用公共doctype处理XML文件

时间:2010-05-10 12:12:54

标签: xslt doctype

我正在尝试使用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>

测试1°

源文件:

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

</svg>

结果:

/svg

测试n°2

源文件:

<?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声明会修改处理的行为?

1 个答案:

答案 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默认属性。