使用xsl匹配节点子集

时间:2016-04-01 16:55:09

标签: xml xslt graphml

我有以下图表:

<?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的真正专家,但有可能分步吗?即首先删除有问题的边缘,然后删除无邻居节点?

1 个答案:

答案 0 :(得分:0)

这是一个使用密钥的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>