使用 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>