Tôi có tệp XML mã hóa directed acyclic graph (DAG) đại diện cho partial order. Các đồ thị như vậy rất hữu ích cho những thứ như chỉ định phụ thuộc và tìm kiếm critical paths. Đối với tò mò, ứng dụng hiện tại của tôi là để xác định phụ thuộc thành phần cho một build system, do đó, đỉnh là các thành phần và các cạnh xác định thời gian biên dịch phụ thuộc. Dưới đây là một ví dụ đơn giản:Tìm đồ thị theo chu kỳ được chỉ định (DAG) Các thành phần tối thiểu (đỉnh) với XSLT/XPath?
<?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>
DAG Điều này có thể được rút ra như thế này:
Tôi muốn áp dụng một XSLTstylesheet sản xuất khác XML tài liệu có chứa chỉ các đỉnh tương ứng với minimal elements của đơn đặt hàng một phần. Đó là, những đỉnh không có cạnh tới. Tập hợp các đỉnh tối thiểu cho biểu đồ ví dụ là {A, B, F}
. Đối với ứng dụng phụ thuộc xây dựng của tôi, việc tìm kiếm tập hợp này có giá trị bởi vì tôi biết rằng nếu tôi xây dựng các thành viên của tập hợp này, thì mọi thứ trong dự án của tôi sẽ được xây dựng.
Đây là giải pháp biểu định kiểu hiện tại của tôi (Tôi đang chạy với Xalan trên Java bằng cách sử dụng tác vụ xslt
của Apache Ant). Một quan sát quan trọng là một đỉnh tối thiểu sẽ không được nhắc đến trong bất kỳ yếu tố 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>
Áp dụng kiểu này xuất ra như sau (mà tôi tin là đúng):
<?xml version="1.0" encoding="UTF-8"?>
<minimal-vertices>
<minimal-vertex name="A"/>
<minimal-vertex name="B"/>
<minimal-vertex name="F"/>
</minimal-vertices>
Có điều là, Tôi không hoàn toàn hài lòng với giải pháp này. Tôi tự hỏi nếu có cách nào để kết hợp số select
của số for-each
và test
của số if
với cú pháp XPath.
Tôi muốn viết một cái gì đó như:
<xsl:for-each select="//vertex[not(//vertex/directed-edge-to[@vertex=current()/@name])]">
Nhưng điều đó không làm những gì tôi muốn vì current()
chức năng không tham chiếu tới các nút bởi các //vertex
biểu hiện bên ngoài được chọn.
Do đó, giải pháp của tôi sử dụng cú pháp XPath 1.0 và XSLT 1.0, mặc dù tôi cũng mở cho cú pháp XPath 2.0 và XSLT 2.0.
Dưới đây là xây dựng kịch bản Ant nếu bạn thích:
<?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>
Mục tiêu dot
tạo GraphvizDotlanguage mã cho render đồ thị.Dưới đây là 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>
Viết tắt "//" bất cứ khi nào có thể vì nó rất tốn kém, làm cho toàn bộ cây con bắt nguồn từ nút ngữ cảnh cần tìm kiếm. "//" ở cấp cao nhất làm cho toàn bộ tài liệu XML được tìm kiếm. Nó rất quan trọng * không * để sử dụng "//" bất cứ khi nào cấu trúc của tài liệu XML được biết tại thời điểm viết biểu thức XPath –