発見問グラフ(DAG)最小限の要素(点)のXSLT/XPath?
-
20-08-2019 - |
質問
私は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>
このことが、私は完全に満足す事ができます。 私は疑問がある場合を組み合わせに select
の for-each
の test
の if
とXPath構文です。
ものを書きたいのように:
<xsl:for-each select="//vertex[not(//vertex/directed-edge-to[@vertex=current()/@name])]">
がないので current()
機能を利用できませんを参考にノードが選択した外 //vertex
表現です。
Thusfar、中型車向けのソリューションを XPath1.0 や XSLT1.0 書式では、がんに開 XPath2.0 や XSLT2.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つの新しい演算子を導入し(ne
、lt
、le
、gt
、ge
、および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 こちらの.