这个将 graphml 转换为 svg 的 XSLT 有什么问题?
What is wrong with this XSLT that converts graphml to svg?
我找到了解决我之前问题的方法。我需要将 graphml
格式修改为 svg
。我 运行 测试了来自 the article 的例子,但它有问题,svg 没有正确渲染,但输出好像是正确的。
我的test.xml:
<graph edgedefault="directed">
<node id="n1"/>
<node id="n2"/>
<node id="n3"/>
<node id="n4"/>
<node id="n5"/>
<edge source="n1" target="n2"/>
<edge source="n1" target="n5"/>
<edge source="n1" target="n3"/>
<edge source="n2" target="n4"/>
</graph>
并使用了xslt
:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/2000/svg">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="graph">
<!-- when finding a 'graph' element, create the 'svg' root and its 'defs' section -->
<svg>
<defs>
<marker id="arrow" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="10" markerHeight="10" orient="auto">
<path fill="black" d="M0 0 10 5 0 10z"/>
</marker>
</defs>
<!-- for each 'node' create a 'g' element with its contents -->
<xsl:for-each select="node">
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">
<xsl:value-of select="@id"/>
</text>
</g>
</xsl:for-each>
<!-- for each 'edge' create a 'line' with the arrow if it is a 'directed' edge -->
<xsl:for-each select="edge">
<line>
<xsl:if test="not(@directed='false')">
<xsl:attribute name="style">marker-end:url(#arrow)</xsl:attribute>
</xsl:if>
</line>
</xsl:for-each>
</svg>
</xsl:template>
</xsl:stylesheet>
如果所有矩形都移动到 0,0 坐标,使用的结果看起来像:
结果svg代码
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrow" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="10" markerHeight="10" orient="auto">
<path fill="black" d="M0 0 10 5 0 10z"/>
</marker>
</defs>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n1</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n2</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n3</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n4</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n5</text>
</g>
<line style="marker-end:url(#arrow)"/>
<line style="marker-end:url(#arrow)"/>
<line style="marker-end:url(#arrow)"/>
<line style="marker-end:url(#arrow)"/>
</svg>
问题是,x
和 y
坐标没有设置到 <rect>
元素。因此,如果输入中有任何坐标可用,类似的事情就可以做到:
<xsl:for-each select="node">
<xsl:variable select="xpath to get x" name="x" />
<xsl:variable select="xpath to get y" name="y" />
<g>
<rect width="100" height="100" fill="silver" x="{$x}" y="{$y}" />
<text style="font-size:24;font-weight:bold">
<xsl:value-of select="@id"/>
</text>
</g>
</xsl:for-each>
我找到了解决我之前问题的方法。我需要将 graphml
格式修改为 svg
。我 运行 测试了来自 the article 的例子,但它有问题,svg 没有正确渲染,但输出好像是正确的。
我的test.xml:
<graph edgedefault="directed">
<node id="n1"/>
<node id="n2"/>
<node id="n3"/>
<node id="n4"/>
<node id="n5"/>
<edge source="n1" target="n2"/>
<edge source="n1" target="n5"/>
<edge source="n1" target="n3"/>
<edge source="n2" target="n4"/>
</graph>
并使用了xslt
:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/2000/svg">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="graph">
<!-- when finding a 'graph' element, create the 'svg' root and its 'defs' section -->
<svg>
<defs>
<marker id="arrow" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="10" markerHeight="10" orient="auto">
<path fill="black" d="M0 0 10 5 0 10z"/>
</marker>
</defs>
<!-- for each 'node' create a 'g' element with its contents -->
<xsl:for-each select="node">
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">
<xsl:value-of select="@id"/>
</text>
</g>
</xsl:for-each>
<!-- for each 'edge' create a 'line' with the arrow if it is a 'directed' edge -->
<xsl:for-each select="edge">
<line>
<xsl:if test="not(@directed='false')">
<xsl:attribute name="style">marker-end:url(#arrow)</xsl:attribute>
</xsl:if>
</line>
</xsl:for-each>
</svg>
</xsl:template>
</xsl:stylesheet>
如果所有矩形都移动到 0,0 坐标,使用的结果看起来像:
结果svg代码
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrow" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="10" markerHeight="10" orient="auto">
<path fill="black" d="M0 0 10 5 0 10z"/>
</marker>
</defs>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n1</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n2</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n3</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n4</text>
</g>
<g>
<rect width="100" height="100" fill="silver"/>
<text style="font-size:24;font-weight:bold">n5</text>
</g>
<line style="marker-end:url(#arrow)"/>
<line style="marker-end:url(#arrow)"/>
<line style="marker-end:url(#arrow)"/>
<line style="marker-end:url(#arrow)"/>
</svg>
问题是,x
和 y
坐标没有设置到 <rect>
元素。因此,如果输入中有任何坐标可用,类似的事情就可以做到:
<xsl:for-each select="node">
<xsl:variable select="xpath to get x" name="x" />
<xsl:variable select="xpath to get y" name="y" />
<g>
<rect width="100" height="100" fill="silver" x="{$x}" y="{$y}" />
<text style="font-size:24;font-weight:bold">
<xsl:value-of select="@id"/>
</text>
</g>
</xsl:for-each>