質問

私はXMLファイルを符号化 問graph (DAG) を表す 部分的な順序.などのグラフに役立つようなものを指定する依存関係を見 重要な進路.に興味のある人は、私の現在のアプリケーションを指定する部品の依存関係 システムの構築, での頂点部品-エッジ指定コンパイル時間の依存関係.ここでは、簡単な例:

<?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>

この結果が導かれるようになります:


(出典: iparelan.com)

思用 XSLT スタイルシート を製造する他のXML 含んでいるドキュメントの頂点に対応する 最小限の要素 の一部です。それは、その頂点を持たない受信しいですね。セットの最小限の頂点の例グラフ {A, B, F}.私の構築に依存関係の申請は、この設定は貴重な知り合いだったからだと私はこの設定をし、自分自身のプロジェクトを構築する。

ここには現在の私のスタイルシートソリューション(っ走ることXalan Java Apache Antの xslt タスク).キー観測は、最小限の頂点は参照される任意の directed-edge-to 要素:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xalan="http://xml.apache.org/xslt"
                exclude-result-prefixes="xalan">
    <xsl:output method="xml" indent="yes" xalan:indent-amount="4"/>

    <xsl:template match="dag">
        <minimal-vertices>
            <xsl:for-each select="//vertex">
                <xsl:if test="not(//vertex/directed-edge-to[@vertex=current()/@name])">
                    <minimal-vertex name="{@name}"/>
                </xsl:if>
            </xsl:for-each>
        </minimal-vertices>
    </xsl:template>
</xsl:stylesheet>

このスタイルシートを出力できると思うのですが、:

<?xml version="1.0" encoding="UTF-8"?>
<minimal-vertices>
    <minimal-vertex name="A"/>
    <minimal-vertex name="B"/>
    <minimal-vertex name="F"/>
</minimal-vertices>

このことが、私は完全に満足す事ができます。 私は疑問がある場合を組み合わせに selectfor-eachtestif とXPath構文です。

ものを書きたいのように:

<xsl:for-each select="//vertex[not(//vertex/directed-edge-to[@vertex=current()/@name])]">

がないので current() 機能を利用できませんを参考にノードが選択した外 //vertex 表現です。

Thusfar、中型車向けのソリューションを XPath1.0XSLT1.0 書式では、がんに開 XPath2.0XSLT2.0 構文としてます。

この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>

dot 対象の発生 Graphviz 恐竜 言語 コードのレンダリングのグラフで表示します。こちらは xml-to-dot.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xalan="http://xml.apache.org/xslt"
                exclude-result-prefixes="xalan">
    <xsl:output method="text"/>

    <xsl:template match="dag">
        digraph {
        rankdir="BT";
        node [style="filled", fillcolor="cyan", fontname="Helvetica"];
        <xsl:apply-templates select="//directed-edge-to"/>
        }
    </xsl:template>

    <xsl:template match="directed-edge-to">
        <xsl:value-of select="concat(ancestor::vertex/@name, '->', @vertex, ';')"/>
    </xsl:template>
</xsl:stylesheet>
役に立ちましたか?

解決

あなたは=オペレータ上のXPathの暗黙的存在量化を活用することができます:

<xsl:for-each select="//vertex[not(@name = //vertex/directed-edge-to/@vertex)]">
あなたはノードセットを比較するために、6つの比較演算子(!=<<=>>=、およびeq)のいずれかを使用すると、

、式はtrueを返しますノード・セット内の任意のノードは、条件を満たしている場合。互いにノードセット比較した場合、式は真を返す場合、最初のノードセットを満足内の任意のノード、第2ノード・セット内の任意のノードと比較して条件。 XPath 2.0のは、この存在量化を実行しない6つの新しい演算子を導入し(neltlegtge、およびnot())。しかし、あなたの場合、あなたはその存在量化を取得するには、「@vertex」を使用するとよいでしょう。

当然の注意、あなたはまだあなたがやっていたよう@name機能を使用したいと思うことを。ほとんどの時間、それはcurrent()演算子を避けるために良いことです。あなたがここに代わりstarts-with(@vertex, $v/@name)のそれを使用した場合、あなたの意図ではないfor値に等しくない任意のsome属性が存在する場合、それはtrueを返します。 (どちらかのノードセットが空の場合、空のノードセットとの比較は常にfalseを返すように、それは、falseを返します。)

あなたの代わりにevery使用したい場合は、

、そして、あなたがやったような何かをする必要があると思います:あなたはfor-each結合することができるように、反復から条件を分離します。しかし、XPath 2.0の中で、あなたが式の中でこれを行うことができます:

<xsl:for-each select="for $v in //vertex
                      return $v[not(//directed-edge-to[@vertex eq $v/@name])]">

これはあなたの条件は、単純な等価比較(したがって、実存「match」を使用して定量化することはできません)ではないときに便利です。例:<=>

のXPath 2.0はまた、存在量化を実行する明示的な方法を有します。代わりに、上記<=>式の、我々はこれを記述することができます:

<xsl:for-each select="//vertex[not(some $e in //directed-edge-to
                                   satisfies @name eq $e/@vertex)]">

を "<=>" 構文また、XPathの2.0はまた、ユニバーサルの定量を行うための対応する "<=>" 構文を供給する。

むしろ<=>使用するよりも、あなたはまた、よりモジュール(かつ強力)されているテンプレートルールを、使用することができます:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <minimal-vertices>
      <xsl:apply-templates/>
    </minimal-vertices>
  </xsl:template>

  <!-- Copy vertex elements that have no arrows pointing to them -->
  <xsl:template match="vertex[not(@name = //directed-edge-to/@vertex)]">
    <minimal-vertex name="{@name}"/>
  </xsl:template>

</xsl:stylesheet>

繰り返しますが、この場合には、我々は<=>の存在量化に頼っています。

XSLT 1.0、すなわち、<=>属性で、パターンの<=>機能の使用を禁止するが、XSLT 2.0はそれを可能にします。その場合、<=>現在マッチされているノードを指します。だから、XSLT 2.0で、我々はまた、(<=>表現を使用せずに)これを書くことができます:

<xsl:template match="vertex[not(//directed-edge-to[@vertex eq current()/@name])]">

このパターンは、基本的にあなたが<=>で使用しようとした式と同じであることに注意してください、それはあなたが<=>でやりたいしない一方で、それがのないの何やります(何<=>がバインドすることは異なっているので)パターンで欲しいます。

最後に、私はいくつかの方法で(<=>削除)ロジックを簡素化するもう一つのバリエーションを追加します。これはまた、XSLT 1.0を使用してに戻ります:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <minimal-vertices>
      <xsl:apply-templates/>
    </minimal-vertices>
  </xsl:template>

  <!-- By default, copy vertex elements -->
  <xsl:template match="vertex">
    <minimal-vertex name="{@name}"/>
  </xsl:template>

  <!-- But strip out vertices with incoming arrows -->
  <xsl:template match="vertex[@name = //directed-edge-to/@vertex]"/>

</xsl:stylesheet>
あなたは空白ビーイング出力が気に入らない場合は、

、テキストノードの場合は空のルールを追加しますので、彼らは(それらをコピーすることであるテキストノードのデフォルトのルールを、オーバーライド)取り除か得られます。

<xsl:template match="text()"/>

それとも、ただあなたにテンプレートを適用するもののノードにより選択することができ

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

あなたはデータを部分的に、あなたのスタイルシートのより広い文脈に依存し、予想される、味に部分的に依存している取る接近する(など、入力構造が異なる場合がありますどのくらいの。)。

私は道あなたが求めていたものを超えて行きましたけど、私はあなたが、少なくともこれは興味深い発見を願っています。 : - )

他のヒント

なXPath1.0表現:

        /*/vertex[not(@name = /*/vertex/directed-edge-to/@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>

このスタイルシートが適用され、当初提供XML文書:

<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 こちらの.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top