使用 xsl 匹配节点子集
matching a subset of nodes using xsl
我得到了下图:
<?xml version="1.0" encoding="utf-8"?><graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph edgedefault="undirected">
<node id="a">
<data key="d0">some info</data>
</node>
<node id="b"/>
<node id="c">
<data key="d0">some more info</data>
</node>
<node id="d"/>
<edge source="a" target="b"/>
<edge source="a" target="c"/>
<edge source="b" target="c"/>
<edge source="b" target="d"/>
<edge source="c" target="d"/>
</graph>
</graphml>
并且我正在尝试使用 XSLT 创建包含所有邻近节点 a
的节点的图形子集。
期望的输出:
<?xml version="1.0" encoding="utf-8"?><graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph edgedefault="undirected">
<node id="b"/>
<node id="c">
<data key="d0">some more info</data>
</node>
<edge source="b" target="c"/>
</graph>
</graphml>
我不是真正的 XSLT 专家,但是可以分步进行吗?即首先删除有问题的边,然后删除无邻居节点?
这是一个基于 XSLT 2.0(可以 运行 与 Saxon 9、Altova、XmlPrime、Exselt)的解决方案,使用键:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0"
xpath-default-namespace="http://graphml.graphdrawing.org/xmlns">
<xsl:output indent="yes"/>
<xsl:param name="start-id" as="xs:string" select="'a'"/>
<xsl:key name="node-id" match="node" use="@id"/>
<xsl:key name="source-edge" match="edge" use="@source"/>
<xsl:key name="target-edge" match="edge" use="@target"/>
<xsl:variable name="start-node" select="key('node-id', $start-id)"/>
<xsl:variable name="neighbours"
select="key('node-id', key('source-edge', $start-node/@id)/@target)
| key('node-id', key('target-edge', $start-node/@id)/@source)"/>
<xsl:variable name="neighbour-edges"
select="//edge[@source = $neighbours/@id and @target = $neighbours/@id]"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="graph">
<xsl:copy>
<xsl:copy-of select="$neighbours | $neighbour-edges"/>
</xsl:copy>
</xsl:template>
</xsl:transform>
我得到了下图:
<?xml version="1.0" encoding="utf-8"?><graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph edgedefault="undirected">
<node id="a">
<data key="d0">some info</data>
</node>
<node id="b"/>
<node id="c">
<data key="d0">some more info</data>
</node>
<node id="d"/>
<edge source="a" target="b"/>
<edge source="a" target="c"/>
<edge source="b" target="c"/>
<edge source="b" target="d"/>
<edge source="c" target="d"/>
</graph>
</graphml>
并且我正在尝试使用 XSLT 创建包含所有邻近节点 a
的节点的图形子集。
期望的输出:
<?xml version="1.0" encoding="utf-8"?><graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph edgedefault="undirected">
<node id="b"/>
<node id="c">
<data key="d0">some more info</data>
</node>
<edge source="b" target="c"/>
</graph>
</graphml>
我不是真正的 XSLT 专家,但是可以分步进行吗?即首先删除有问题的边,然后删除无邻居节点?
这是一个基于 XSLT 2.0(可以 运行 与 Saxon 9、Altova、XmlPrime、Exselt)的解决方案,使用键:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0"
xpath-default-namespace="http://graphml.graphdrawing.org/xmlns">
<xsl:output indent="yes"/>
<xsl:param name="start-id" as="xs:string" select="'a'"/>
<xsl:key name="node-id" match="node" use="@id"/>
<xsl:key name="source-edge" match="edge" use="@source"/>
<xsl:key name="target-edge" match="edge" use="@target"/>
<xsl:variable name="start-node" select="key('node-id', $start-id)"/>
<xsl:variable name="neighbours"
select="key('node-id', key('source-edge', $start-node/@id)/@target)
| key('node-id', key('target-edge', $start-node/@id)/@source)"/>
<xsl:variable name="neighbour-edges"
select="//edge[@source = $neighbours/@id and @target = $neighbours/@id]"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="graph">
<xsl:copy>
<xsl:copy-of select="$neighbours | $neighbour-edges"/>
</xsl:copy>
</xsl:template>
</xsl:transform>