Using XSLT and XPath for graph data structure processing?

Ramon M. Felciano

Usenet Archive
Joined
Apr 25, 2000
Messages
7
Reaction score
0
Helo all --

I'm trying to gain a deeper understand for what type of semi-declarative programming can be done through XML and XPath/XSLT. I'm looking at graph processing problems as a testbed for this, and came across a problem that I haven't been able to solve elegantly. The problem is to find "linker" vertexes that a pair of verteces from a pre-defined set. For example, if the graph verteces represent cities and edges represent flights between them, then given a list of cities, find all intermediate cities that you would stop in via a "connecting flight".

For example, given the following simple graph:

V1 -> V2 -> V3 -> V4
\<- V5 ->/

(V5 points to both V2 and V4), and its XML serialization:

<graph>
<vertex id="V1"/>
<vertex id="V2" type="anchor"/>
<vertex id="V3"/>
<vertex id="V4" type="anchor"/>
<vertex id="V5"/>
<edge source="V1" target="V2"/>
<edge source="V2" target="V3"/>
<edge source="V3" target="V4"/>
<edge source="V5" target="V2"/>
<edge source="V5" target="V4"/>
</graph>

I would like to transform this into a second graph where all vertexes that "link" two anchor distinct vertexes are flagged as link nodes. In this case, there are two anchor vertexes V2 and V4, and I can link them through V3 (V2 -> V3 -> V4) and V5 (V2 <- V5 -> V4). Note that linked verteces must be distinct, so traversing the V2 <- V1 -> V2 path should not yield V1 as a link node. So I'd like to see something like this:

<graph>
<vertex id="V1"/>
<vertex id="V2" type="anchor"/>
<vertex id="V3" linker="true"/>
<vertex id="V4" type="anchor"/>
<vertex id="V5" linker="true"/>
<edge source="V1" target="V2"/>
<edge source="V2" target="V3"/>
<edge source="V3" target="V4"/>
<edge source="V5" target="V2"/>
<edge source="V5" target="V4"/>
</graph>

It would be ideal to come up with a generalized solution that would let you use 1, 2, .. N intermediate linking nodes. I've been able to get this working with nested loops, but it isn't particularly declarative or speedy, and is certainly more verbose than I'd like, so I'm wondering if anyone here has insights into how to do this elegantly and in XSLT/XPath style. For example, is it possible to write a single XPath expression that will select <vertex> elements that obey the above criteria? If not, does anyone have any suggestions for how to code this effectively and efficiently with XSLT? Or is XPath/XSLT not the right paradigm for this type of information processing and transformation?

Thanks!

Ramon
 

Andy Dingley

Usenet Archive
Joined
Feb 23, 2000
Messages
3,303
Reaction score
0
I'm trying to gain a deeper understand for what type of semi-declarative programming can be done through XML and XPath/XSLT. I'm looking at graph processing problems as a testbed for this,

Don't do graphs in XML, use RDF instead.

Jave & Jena are the tools to use.
 

Andy Dingley

Usenet Archive
Joined
Feb 23, 2000
Messages
3,303
Reaction score
0
????? You are aware of course of RDF over XML?

Sure, but you don't process it _as_ XML.

XML does tree structure, not graphs. ID & IDREF just don't do anything useful for you and there's a whole issue about the difficulty of working with XML which contains a graph that isn't entirely represented by that document (ie. external resources)

If you want to work with "a graph" in something that's transported "in XML", then you need to build a layer above XML. Or you can use one, like RDF, that already exists.
 

Patrick TJ McPhee

Usenet Archive
Joined
Apr 2, 2000
Messages
269
Reaction score
0
% I'm trying to gain a deeper understand for what type of % semi-declarative programming can be done through XML and XPath/XSLT.

[...]

[given]

% <graph>
% <vertex id="V1"/>
% <vertex id="V2" type="anchor"/>
% <vertex id="V3"/>
% <vertex id="V4" type="anchor"/>
% <vertex id="V5"/>
% <edge source="V1" target="V2"/>
% <edge source="V2" target="V3"/>
% <edge source="V3" target="V4"/>
% <edge source="V5" target="V2"/>
% <edge source="V5" target="V4"/>
% </graph>

% this case, there are two anchor vertexes V2 and V4, and I can link % them through V3 (V2 -> V3 -> V4) and V5 (V2 <- V5 -> V4). Note that

I don't really understand this last one. It seems like this is a directed graph, so to have a link, you need to start at one anchor and go to the other. V5 would be a linker if there were some way to get to it from an anchor.

[we want to get]

% <graph>
% <vertex id="V1"/>
% <vertex id="V2" type="anchor"/>
% <vertex id="V3" linker="true"/>
% <vertex id="V4" type="anchor"/>
% <vertex id="V5" linker="true"/>
% <edge source="V1" target="V2"/>
% <edge source="V2" target="V3"/>
% <edge source="V3" target="V4"/>
% <edge source="V5" target="V2"/>
% <edge source="V5" target="V4"/>
% </graph>

I start by defining keys which can be used to find the anchors, the sources for each edge, and the targets for each edge:

<xsl:key name='anchors' use='@id' match='vertex[@type = "anchor"]'/> <xsl:key name='sources' use='@source' match='edge'/> <xsl:key name='targets' use='@target' match='edge'/>

If we pay attention to the directions of the edges, we want an expression which is true when the current node is the target of an edge from one or more anchors and the source of an edge towards one or more anchors. We can use the `targets' key and the current node's id attribute to find all the edges for which it's a target

key('targets', @id)

That's a node set made up of edge elements. We can turn it into a node set made up of the corresponding source attributes

key('targets', @id)/@source

then use that as an argument to key, to find the set anchor vertices which are sources of the current node:

key('anchors', key('targets', @id)/@source)

If the current node is the target of an edge from an anchor, the resulting node set will be non-empty. Similarly, here's the set of anchor nodes which are targets of edges from the current node

key('anchors', key('sources', @id)/@target)

we can use those node sets as boolean values, and so create a match expression which matches all vertex elements which are targets of an edge from an anchor and sources of an edge to an anchor

match="vertex[key('anchors', key('targets', @id)/@source) and key('anchors', key('sources', @id)/@target)]"

to ignore the direction of the edges, we can create a union of those two node sets and count the elements in the union

match="vertex[count(key('anchors', key('targets', @id)/@source)| key('anchors', key('sources', @id)/@target)) > 1]"

Note that if we were to make an edge from V2 to V1, the `directed' match expression would call V1 a link, but the undirected one would not.

The full style sheet is

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

<xsl:key name='anchors' use='@id' match='vertex[@type = "anchor"]'/> <xsl:key name='sources' use='@source' match='edge'/> <xsl:key name='targets' use='@target' match='edge'/>

<xsl:template match='node|@*'>
<xsl:copy>
<xsl:apply-templates select='node|@*'/>
</xsl:copy>
</xsl:template>

<xsl:template match='vertex[count(key("anchors", key("targets", @id)/@source) |key("anchors", key("sources", @id)/@target)) > 1]'> <xsl:copy> <xsl:apply-templates select='node|@*'/> <xsl:attribute name='linker'>true</xsl:attribute> </xsl:copy> </xsl:template>

</xsl:stylesheet>

% It would be ideal to come up with a generalized solution that would % let you use 1, 2, .. N intermediate linking nodes.

I'm not sure off the top of my head how you would generalise this.
 

Dimitre Novatchev

Usenet Archive
Joined
Nov 7, 2000
Messages
737
Reaction score
0
Helo all --

I'm trying to gain a deeper understand for what type of semi-declarative programming can be done through XML and XPath/XSLT. I'm looking at graph processing problems as a testbed for this, and came across a problem that I haven't been able to solve elegantly. The problem is to find "linker" vertexes that a pair of verteces from a pre-defined set. For example, if the graph verteces represent cities and edges represent flights between them, then given a list of cities, find all intermediate cities that you would stop in via a "connecting flight".

For example, given the following simple graph:

V1 -> V2 -> V3 -> V4
\<- V5 ->/

(V5 points to both V2 and V4), and its XML serialization:

<graph>
<vertex id="V1"/>
<vertex id="V2" type="anchor"/>
<vertex id="V3"/>
<vertex id="V4" type="anchor"/>
<vertex id="V5"/>
<edge source="V1" target="V2"/>
<edge source="V2" target="V3"/>
<edge source="V3" target="V4"/>
<edge source="V5" target="V2"/>
<edge source="V5" target="V4"/>
</graph>

I would like to transform this into a second graph where all vertexes that "link" two anchor distinct vertexes are flagged as link nodes. In this case, there are two anchor vertexes V2 and V4, and I can link them through V3 (V2 -> V3 -> V4) and V5 (V2 <- V5 -> V4). Note that linked verteces must be distinct, so traversing the V2 <- V1 -> V2 path should not yield V1 as a link node. So I'd like to see something like this:

<graph>
<vertex id="V1"/>
<vertex id="V2" type="anchor"/>
<vertex id="V3" linker="true"/>
<vertex id="V4" type="anchor"/>
<vertex id="V5" linker="true"/>
<edge source="V1" target="V2"/>
<edge source="V2" target="V3"/>
<edge source="V3" target="V4"/>
<edge source="V5" target="V2"/>
<edge source="V5" target="V4"/>
</graph>

It would be ideal to come up with a generalized solution that would let you use 1, 2, .. N intermediate linking nodes. I've been able to get this working with nested loops, but it isn't particularly declarative or speedy, and is certainly more verbose than I'd like, so I'm wondering if anyone here has insights into how to do this elegantly and in XSLT/XPath style. For example, is it possible to write a single XPath expression that will select <vertex> elements that obey the above criteria? If not, does anyone have any suggestions for how to code this effectively and efficiently with XSLT? Or is XPath/XSLT not the right paradigm for this type of information processing and transformation?

Thanks!

Ramon

Ramon,

Here's the general solution and it is quite simple and
straightforward. I use a recursive template based on the following rule:

Paths(/.., X, Z) = Union( {X -> Xi} . Paths(X, Xi, Z) )

Where the function Paths(Eset, X, Z) returns all paths from X to Z, that do not include any vertices belonging to the exclusion-set Eset.

Here {X -> Xi} are all edges from X.

As you can see the code of the transformation is 71 lines long, but it should be noted that for the purpose of readability I write some XPath expressions on several lines and also half of these 71 lines are just closing tags.

Here's the code. This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"<xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>

<xsl:key name="kNeighbors" match="vertex"
use="../edge[@target = current/@id]/@source"/>

<xsl:key name="kNeighbors" match="vertex"
use="../edge[@source = current/@id]/@target"/>

<xsl:template match="/">
<xsl:call-template name="getPaths">
<xsl:with-param name="pNode1"
select="/*/vertex[@type='anchor'][1]"/>
<xsl:with-param name="pNode2"
select="/*/vertex[@type='anchor'][2]"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="getPaths">
<xsl:param name="pNode1" select="/.."/>
<xsl:param name="pNode2" select="/.."/>
<xsl:param name="pExcluded" select="/.."/>

<xsl:for-each select=
"key('kNeighbors', $pNode1/@id)
[not(@id = $pExcluded/@id)]">
<xsl:choose>
<xsl:when test="@id = $pNode2/@id">
<path>
<xsl:copy-of
select="/*/edge[$pNode1/@id = @*
and
$pNode2/@id = @*
]"/>
</path>
</xsl:when>
<xsl:eek:therwise>
<xsl:variable name="vrtfTail">
<xsl:call-template name="getPaths">
<xsl:with-param name="pNode1"
select="."/>
<xsl:with-param name="pNode2"
select="$pNode2"/>
<xsl:with-param name="pExcluded"
select="$pExcluded | $pNode1"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="vTail"
select="exsl:node-set($vrtfTail)/*"/>

<xsl:if test="$vTail">
<path>
<xsl:copy-of
select="/*/edge[$pNode1/@id = @*
and
current/@id = @*
]"/>

<xsl:copy-of select="$vTail/*"/>
</path>
</xsl:if>
</xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

when applied on this source.xml:

<graph>
<vertex id="V1"/>
<vertex id="V2" type="anchor"/>
<vertex id="V3"/>
<vertex id="V4" type="anchor"/>
<vertex id="V5"/>
<edge source="V1" target="V2"/>
<edge source="V1" target="V3"/>
<edge source="V2" target="V3"/>
<edge source="V3" target="V4"/>
<edge source="V5" target="V2"/>
<edge source="V5" target="V4"/>
</graph>

produces thewanted result:

<path>
<edge source="V1" target="V2"/>
<edge source="V1" target="V3"/>
<edge source="V3" target="V4"/>
</path>
<path>
<edge source="V2" target="V3"/>
<edge source="V3" target="V4"/>
</path>
<path>
<edge source="V5" target="V2"/>
<edge source="V5" target="V4"/>
</path>

These are all three different paths (with all nodes in the path only once) from V2 to V4 in the graph described by the xml above.

The first solution:

V2 -> V1 -> V3 ->V4

is 3 edges long.

The other two are two edges long each.

I hope this helped in this specific problem and also to answer positively your questions about the expressiveness of XPath/XSLT and the appropriateness of XSLT as a tool for solving this type of problems.

Dimitre Novatchev.
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
 

Ed Beroset

Usenet Archive
Joined
Sep 5, 2002
Messages
46
Reaction score
0
Dimitre said:
I hope this helped in this specific problem and also to answer positively your questions about the expressiveness of XPath/XSLT and the appropriateness of XSLT as a tool for solving this type of problems.

What, no SVG output? :) I'm kidding. Seriously, I wasn't the original poster on that one, but I enjoyed looking over your solution.
Nice work!

Ed
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
548,208
Messages
3,104,799
Members
249,594
Latest member
henrywalsh

Latest Threads

Top