使用XSLT重新排列/合并SVG文件的节点

时间:2016-09-15 15:02:56

标签: xml xslt svg matplotlib

我尝试使用matplotlib生成一些svg图像,并将它们嵌入到html和pdf报告中。我在我的应用程序使用的WebKit中遇到了this bug,在Adobe Acrobat中遇到了另一个渲染错误。这两个问题都是由matplotlib<clipPath>个元素放在svg文件的末尾引起的。

要解决这两个错误,我想使用XSLT将所有<defs>个节点合并到文件开头的单个节点中

示例svg

<svg height="288pt" version="1.1" viewBox="0 0 576 288" width="576pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <style type="text/css">
            *{stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:100000;}
        </style>
    </defs>
    <g id="figure_1">
        ...

    </g>
    <defs>
        <clipPath id="p8596dc1504">
            <rect height="230.5245" width="211.84" x="339.7475" y="28.90175"/>
        </clipPath>
        <clipPath id="p9534ff1f4d">
            <rect height="230.5245" width="211.84" x="66.534375" y="28.90175"/>
        </clipPath>
    </defs>
</svg>

所需的输出

<svg height="288pt" version="1.1" viewBox="0 0 576 288" width="576pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <style type="text/css">
            *{stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:100000;}
        </style>
        <clipPath id="p8596dc1504">
            <rect height="230.5245" width="211.84" x="339.7475" y="28.90175"/>
        </clipPath>
        <clipPath id="p9534ff1f4d">
            <rect height="230.5245" width="211.84" x="66.534375" y="28.90175"/>
        </clipPath>
    </defs>
    <g id="figure_1">
        ...

    </g>
</svg>

这是我现有的XSLT。该代码正确删除了<defs>部分,但我在文档开头得到的只有<defs xmlns=""/>没有子代。

xsl文件

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes" doctype-system="about:legacy-compat"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy>
            <defs>
                <xsl:copy-of select="/svg/defs/*"/>
            </defs>
            <xsl:apply-templates select="*[name()!='defs']"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

输出继电器

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs xmlns=""/>
    <g id="figure_1">
        ...

    </g>
</svg>

我仍然试图绕过XSLT。我究竟做错了什么?

1 个答案:

答案 0 :(得分:3)

您的样式表没有考虑源XML使用的名称空间

尝试:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg">
<xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes" doctype-system="about:legacy-compat"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <defs>
                <xsl:copy-of select="/svg:svg/svg:defs/*"/>
            </defs>
            <xsl:apply-templates select="*[not(self::svg:defs)]"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>