XSLT插入SVG根节点问题:冗余命名空间与节点未添加求助
解决XSLT给SVG添加节点的两个问题
咱们先拆解你遇到的两个问题,再一步步给出修复方案:
问题1:<style>节点生成多余的xmlns属性
原因很直接:你直接写的<style>属于无命名空间元素,但SVG文档的所有核心元素都默认归属http://www.w3.org/2000/svg命名空间。当XSLT把无命名空间的<style>插入到SVG命名空间的上下文时,会自动添加xmlns=""来明确该元素不在父元素的命名空间里,再加上你的XSLT开头声明了xsi和svg前缀,这些属性就被连带生成了。
解决方法:用带svg前缀的<svg:style>创建元素,让它直接继承SVG命名空间,这样就不会产生多余的属性了。
问题2:<whatever>节点未被成功添加
这是因为你写了两个匹配svg:title的模板——XSLT处理时,当多个模板匹配同一节点且优先级相同时,只会执行最后一个模板(后面的模板会覆盖前面的),所以你的第一个模板逻辑被第二个覆盖,自然看不到<whatever>节点。
解决方法:把两个模板合并成一个,同时处理<style>和<whatever>的添加。
修复后的完整XSLT代码
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:svg="http://www.w3.org/2000/svg" version='1.0'> <!-- 默认复制所有节点和属性的模板 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 合并svg:title的处理逻辑,同时添加style和whatever节点 --> <xsl:template match="svg:title"> <xsl:copy-of select="."/> <!-- 使用svg前缀的style元素,避免多余命名空间属性 --> <svg:style>.val{--valence: #4599a3}</svg:style> <!-- 若需要whatever也归属SVG命名空间,可改为<svg:whatever>foo</svg:whatever> --> <whatever>foo</whatever> </xsl:template> <xsl:template match="svg:defs/svg:circle"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:attribute name="style">fill: var(--valence, #47565b)</xsl:attribute> </xsl:copy> </xsl:template> </xsl:stylesheet>
额外小提示
如果你希望<whatever>也和其他SVG元素保持同一命名空间,只需要把它改成<svg:whatever>foo</svg:whatever>即可,这样它会自动继承SVG的命名空间属性,不会出现额外的xmlns声明。
内容的提问来源于stack exchange,提问作者DevonDahon




