Xml 使用XSLT将xlinks替换为SVG中的内联
我需要将所有xlink用法替换为SVG中的简单内联xml,然后删除“defs”部分并删除所有boo:属性。之所以需要这个,是因为打算使用的SVG查看器不支持xlinks 初始简化XMLXml 使用XSLT将xlinks替换为SVG中的内联,xml,xslt,optimization,svg,xlink,Xml,Xslt,Optimization,Svg,Xlink,我需要将所有xlink用法替换为SVG中的简单内联xml,然后删除“defs”部分并删除所有boo:属性。之所以需要这个,是因为打算使用的SVG查看器不支持xlinks 初始简化XML <?xml version="1.0" encoding="utf-8"?> <svg xmlns="http://www.w3.org/2000/svg"> <boo:metadata> <boo:text line-space="1.5" minimu
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
<boo:metadata>
<boo:text line-space="1.5" minimum-size="15" regular-size="20"/>
</boo:metadata>
<g transform="translate(149,60)">
<rect x="0" y="0" fill-opacity="0.6" width="579" height="150"/>
<defs><!-- huge section with predefined items-->
<g id="ne">
<path id="ne..."/>
</g>
<g id="nw">
<path id="nw.."/>
</g>
<g id="rt2">
<rect id="RT2" />
<path id="some cool path id"/>
</g>
<g id="rt3">
<rect id="rt3sss" rx="2" ry="2"/>
</g>
<g boo:type="Icon" id="AIRPORT" boo:replacementWords="FLUGHAFEN">
<rect id="ICON_AIRPORT" fill="#FCFFFF" height="15" width="15"/>
<path id="ICON_AIRPORTPATH"/>
</g>
</defs>
<g boo:side="R" id="sssss" transform="translate(184,0)">
<g transform="translate(0.000000,0.000000)">
<g boo:style="HorizontalAlignment:Center;VerticalAlignment:Bottom;" transform="translate(63.202000,126.903002)">
<g transform="translate(0.000000,0.000000)">
<!-- actual usage -->
<use xlink:actuate="onLoad" xlink:type="simple" xlink:show="embed" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#NE" boo:style="HorizontalAlignment:Left;"/>
</g>
<g transform="translate(23.045999,0.000000)" boo:style="HorizontalAlignment:Left;Margin:0 5 0 5;">
<g transform="translate(0.000000,0.000000)" boo:style="Margin:0 1 0 1;">
<g transform="scale(1.150000,1.1500000)">
<!-- actual usage -->
<use xlink:actuate="onLoad" xlink:type="simple" xlink:show="embed" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#RT2"/>
</g>
<text transform="translate(16,13)" text-anchor="middle">4</text>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
4.
预期结果
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g transform="translate(149,60)">
<rect x="0" y="0" fill-opacity="0.6" width="579" height="150"/>
<g id="sssss" transform="translate(184,0)">
<g transform="translate(0.000000,0.000000)">
<g transform="translate(63.202000,126.903002)">
<g transform="translate(0.000000,0.000000)">
<path id="ne..."/>
</g>
<g transform="translate(23.045999,0.000000)">
<g transform="translate(0.000000,0.000000)">
<g transform="scale(1.150000,1.1500000)">
<rect id="RT2" />
<path id="some cool path id"/>
</g>
<text transform="translate(16,13)" text-anchor="middle">4</text>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
4.
我自己解决了这个问题。这里的主要问题是XSL模板中名称空间的使用不正确
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:boo="..." xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg">
<!-- copy everything as is -->
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- replace xlink uses to real svg objects -->
<xsl:template match="svg:use">
<xsl:copy-of select="/*/*/*/*[@id=substring(current()/@xlink:href, 2)]"/>
</xsl:template>
<!-- remove unneeded defs section -->
<xsl:template match="svg:defs"/>
<!-- remove all unneeded cjv nodes and attributes -->
<xsl:template match="@boo:*"/>
<xsl:template match="boo:*"/>
<!-- remove comments and whitespaces -->
<xsl:strip-space elements="*"/>
<xsl:template match="comment()"/>
<!-- EXPERIMENTAL - remove id and type attributes -->
<xsl:template match="@id"/>
<xsl:template match="@type"/>
</xsl:stylesheet>
更好的路径是
<xsl:template match="svg:use">
<xsl:copy-of select="//*[@id=substring(current()/@xlink:href, 2)][1]"/>
</xsl:template>
“//*”从根匹配任何深度的任何子体。终端“[1]”表示如果恰好有两个具有指定id的节点(不应该有),请选择第一个
在我自己对这个问题的攻击中,我还想给新复制的元素提供被替换的use元素的id,但事实证明这很棘手,所以我在它周围加了一个g:
<xsl:template match="svg:use">
<g>
<!-- copy id, transform, etc through from use reference -->
<xsl:apply-templates select="@*"/>
<xsl:copy>
<xsl:apply-templates select="//*[@id=substring(current()/@xlink:href, 2)][1]"/>
</xsl:copy>
</g>
</xsl:template>
最后,当复制模板时,复制其中所有元素的所有ID,如果像我一样有多个符号副本,这是一件坏事。因此,我将所有ID转换为类:
<!-- generally, change ids to classes -->
<xsl:template match="@id">
<xsl:attribute name="class">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
显然,我使用的是xsl:copy而不是xsl:copy of,因此这些修复程序可以正常工作。我的代码有一个问题-它在生成的g元素周围包装了一个虚假的no attributesuse元素-但它呈现为OK。简化示例是一个好主意,但它应该保持名称空间格式良好,并且由于示例使用前缀boo
,但没有声明,因此示例不是命名空间格式良好。