Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用XSLT/XPath查找有向无环图(DAG)最小元素(顶点)?_Xslt_Xpath_Graph Theory_Directed Acyclic Graphs_Build System - Fatal编程技术网

使用XSLT/XPath查找有向无环图(DAG)最小元素(顶点)?

使用XSLT/XPath查找有向无环图(DAG)最小元素(顶点)?,xslt,xpath,graph-theory,directed-acyclic-graphs,build-system,Xslt,Xpath,Graph Theory,Directed Acyclic Graphs,Build System,我有一个XML文件,它对 这代表了一个新的趋势。这样的图对于指定依赖项和查找等方面很有用。出于好奇,我当前的应用程序是为指定组件依赖项,因此顶点是组件,边指定编译时依赖项。下面是一个简单的例子: <?xml version="1.0"?> <dag> <vertex name="A"> <directed-edge-to vertex="C"/> </vertex> <vertex name

我有一个XML文件,它对 这代表了一个新的趋势。这样的图对于指定依赖项和查找等方面很有用。出于好奇,我当前的应用程序是为指定组件依赖项,因此顶点是组件,边指定编译时依赖项。下面是一个简单的例子:

<?xml version="1.0"?>
<dag>
    <vertex name="A">
        <directed-edge-to vertex="C"/>
    </vertex>
    <vertex name="B">
        <directed-edge-to vertex="C"/>
        <directed-edge-to vertex="D"/>
    </vertex>
    <vertex name="C">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="D">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="E">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="F">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="G"/>
</dag>
应用此样式表将产生以下输出(我认为是正确的):

但这并不是我想要的,因为
current()
函数不引用外部
//vertex
表达式选择的节点

Thusfar,我的解决方案使用和语法,尽管我也对和语法持开放态度

如果您愿意,下面是Ant构建脚本:

<?xml version="1.0"?>
<project name="minimal-dag" default="default">
    <target name="default">
        <xslt in="dag.xml" out="minimal-vertices.xml" style="find-minimal-vertices.xsl"/>
    </target>
    <target name="dot">
        <xslt in="dag.xml" out="dag.dot" style="xml-to-dot.xsl"/>
    </target>
</project>

您可以在
=
运算符上利用XPath的隐式存在量化:

<xsl:for-each select="//vertex[not(@name = //vertex/directed-edge-to/@vertex)]">
当您的条件不是简单的相等比较时(因此无法使用“
=
”)进行存在性量化),这非常有用。例如:
以(@vertex,$v/@name)
开头

XPath 2.0还提供了一种执行存在量化的显式方法。我们可以编写以下内容,而不是上面的表达式的:

<xsl:for-each select="//vertex[not(some $e in //directed-edge-to
                                   satisfies @name eq $e/@vertex)]">
同样,在本例中,我们依赖于
=
的存在量化

XSLT1.0禁止在模式中使用
current()
函数,即在
match
属性中使用,但XSLT2.0允许这样做。在这种情况下,
current()
引用当前匹配的节点。因此,在XSLT2.0中,我们还可以编写以下代码(无需对表达式使用
):

如果您不喜欢输出空白,请为文本节点添加一个空规则,这样它们将被剥离(覆盖文本节点的默认规则,即复制它们):


或者,您可以选择将模板应用于哪些节点:

<xsl:apply-templates select="/dag/vertex"/>

您采取哪种方法部分取决于品味,部分取决于样式表的更广泛背景和预期数据(输入结构可能会有多大变化,等等)

我知道我远远超出了你的要求,但我希望你至少觉得这很有趣。:-)

其中一个XPath 1.0表达式是:

/*/vertex[非(@name=/*/vertex/定向边到/@vertex)]

然后将其放入XSLT样式表中,如下所示:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="/">
      <minimal-vertices>
          <xsl:for-each select=
          "/*/vertex[not(@name = /*/vertex/directed-edge-to/@vertex)]"
          >
           <minimal-vertex name="{@name}"/>
          </xsl:for-each>
      </minimal-vertices>
    </xsl:template>
</xsl:stylesheet>
<dag>
    <vertex name="A">
        <directed-edge-to vertex="C"/>
    </vertex>
    <vertex name="B">
        <directed-edge-to vertex="C"/>
        <directed-edge-to vertex="D"/>
    </vertex>
    <vertex name="C">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="D">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="E">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="F">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="G"/>
</dag>
<minimal-vertices>
  <minimal-vertex name="A" />
  <minimal-vertex name="B" />
  <minimal-vertex name="F" />
</minimal-vertices>

将此样式表应用于最初提供的XML文档时

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="/">
      <minimal-vertices>
          <xsl:for-each select=
          "/*/vertex[not(@name = /*/vertex/directed-edge-to/@vertex)]"
          >
           <minimal-vertex name="{@name}"/>
          </xsl:for-each>
      </minimal-vertices>
    </xsl:template>
</xsl:stylesheet>
<dag>
    <vertex name="A">
        <directed-edge-to vertex="C"/>
    </vertex>
    <vertex name="B">
        <directed-edge-to vertex="C"/>
        <directed-edge-to vertex="D"/>
    </vertex>
    <vertex name="C">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="D">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="E">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="F">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="G"/>
</dag>
<minimal-vertices>
  <minimal-vertex name="A" />
  <minimal-vertex name="B" />
  <minimal-vertex name="F" />
</minimal-vertices>

产生所需结果

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="/">
      <minimal-vertices>
          <xsl:for-each select=
          "/*/vertex[not(@name = /*/vertex/directed-edge-to/@vertex)]"
          >
           <minimal-vertex name="{@name}"/>
          </xsl:for-each>
      </minimal-vertices>
    </xsl:template>
</xsl:stylesheet>
<dag>
    <vertex name="A">
        <directed-edge-to vertex="C"/>
    </vertex>
    <vertex name="B">
        <directed-edge-to vertex="C"/>
        <directed-edge-to vertex="D"/>
    </vertex>
    <vertex name="C">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="D">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="E">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="F">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="G"/>
</dag>
<minimal-vertices>
  <minimal-vertex name="A" />
  <minimal-vertex name="B" />
  <minimal-vertex name="F" />
</minimal-vertices>


请注意:XSLT中提供了一种遍历完整(可能是循环)图的解决方案。

谢谢!这也是一个很好的答案,它非常关注我提出的问题。这是一个艰难的决定,但我接受了埃文的答案,因为他的答案很广泛。我很好奇为什么您更喜欢/*/语法而不是//,额外的字符有什么好处吗?@greg mattes应尽可能避免使用“/”缩写,因为它非常昂贵,导致搜索以上下文节点为根的整个子树。顶层的“//”会导致搜索整个XML文档。在编写XPath表达式时,只要知道XML文档的结构,就不要使用“/”,这一点非常重要。因此,一般来说,/*/更好,因为它将搜索限制在单个级别,因为*意味着“选择上下文节点的所有元素子节点”(而不是所有子元素),这可能是一个大型搜索?在这个特殊的例子中,这不应该有什么区别,但要记住这一点。再次感谢。我同意Dimitre关于“/”的使用。您是对的,对于这个特定的数据,性能并不是一个重要的考虑因素。但是,使用/*/vertex,或者更好的是使用/dag/vertex的另一个原因是,它使您的意图更加明确。“*”表示文档元素的名称可能不同,“/”表示元素可能显示为更深的子体。通过使您的意图更加明确,您可以避免阅读您的代码的人对这些事情产生疑问。“//”仍然有用,当然,当它是必要的,即当它实际上是你的意图。伟大的答案!感谢所有的变化和清晰的解释。希望这个答案将来能帮助很多人!(这个问题可以分为几个答案)我很高兴你发现它很有用。谢谢你的投票。我还在学习如何使用这个网站。我应该提供单独的答案吗?提供单独的答案还是一个答案带几个变体是一个品味问题。独立回答允许独立投票。例如,也许我会接受一个使用apply模板作为最佳响应的答案,但社区可能会更喜欢每个模板都使用的答案。其他替代方案本可以被否决。按选票排序时,首先显示我接受的答案,然后显示社区答案。评论可以针对特定的解决方案。非常有意义。谢谢你的提示!尽可能避免使用“/”缩写,因为它非常昂贵,会导致搜索以上下文节点为根的整个子树。顶层的“//”会导致搜索整个XML文档。在编写XPath表达式时,只要知道XML文档的结构,就不要使用“/”非常重要
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="/">
      <minimal-vertices>
          <xsl:for-each select=
          "/*/vertex[not(@name = /*/vertex/directed-edge-to/@vertex)]"
          >
           <minimal-vertex name="{@name}"/>
          </xsl:for-each>
      </minimal-vertices>
    </xsl:template>
</xsl:stylesheet>
<dag>
    <vertex name="A">
        <directed-edge-to vertex="C"/>
    </vertex>
    <vertex name="B">
        <directed-edge-to vertex="C"/>
        <directed-edge-to vertex="D"/>
    </vertex>
    <vertex name="C">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="D">
        <directed-edge-to vertex="E"/>
    </vertex>
    <vertex name="E">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="F">
        <directed-edge-to vertex="G"/>
    </vertex>
    <vertex name="G"/>
</dag>
<minimal-vertices>
  <minimal-vertex name="A" />
  <minimal-vertex name="B" />
  <minimal-vertex name="F" />
</minimal-vertices>