【问题标题】:Using XSLT to rearrange/merge nodes of SVG file使用 XSLT 重新排列/合并 SVG 文件的节点
【发布时间】:2017-01-23 16:11:18
【问题描述】:

我正在尝试使用 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。代码正确地删除了&lt;defs&gt; 部分,但我在文档开头得到的只是&lt;defs xmlns=""/&gt;,没有孩子。

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。我究竟做错了什么?

【问题讨论】:

    标签: xml xslt svg matplotlib


    【解决方案1】:

    您的样式表没有考虑源 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>
    

    【讨论】:

    • 完美,这就是我想要的! SO answer 中的一条评论我的代码基于提到的命名空间,但我不确定如何考虑它们
    • @Parfait 好点。它不在原始代码中,人们倾向于关注主要问题而忽略其余部分。现已添加。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    相关资源
    最近更新 更多