Subject: [xsl] Re: Network diagram - node set intersection From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx> Date: Mon, 23 Feb 2004 19:52:13 +0100 |
<cknell@xxxxxxxxxx> wrote in message news:B0018919762@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx > ==========> Direction of graph > ______ > | | > / |__B__| > ______/ \_____ > | | | | > |__A__| |__D__| > \ / > \ ______/ > | | > |__C__| > > I'm working on producing a network diagram in SVG by processing an XML document with XSLT. Above is a symbolic representation of the output. The relationship between nodes in the graph can't be represented directly in XML because it isn't a tree (Node D has two parents which isn't allowed in XML). > > Here is a simplified sample of the XML document: > <network> > <node> > <node-id>A</node-id> > <predecessor-id></predecessor-id> > <successor-id>B</successor-id> > </node> > <node> > <node-id>B</node-id> > <predecessor-id>A</predecessor-id> > <successor-id>D</successor-id> > </node> > <node> > <node-id>C</node-id> > <predecessor-id>A</predecessor-id> > <successor-id>D</successor-id> > </node> > <node> > <node-id>D</node-id> > <predecessor-id>B</predecessor-id> > <predecessor-id>C</predecessor-id> > <successor-id></successor-id> > </node> > </network> > > In my stylesheet I have a template that matches <node>. For the purpose of positioning the SVG elements I want to determine how many other nodes have a <predecessor-id> that matches one of the <predecessor-id> children of the context <node>. In addition to determining how many "siblings" a <node> has, I also want to know where the context node is in document order relation to these "siblings". > > The <node> elements with common <predecessor-id> values would be, in the context of the network diagram, "siblings". Of course in the XML document all the <node> elements are siblings in the XPath sense. > > To determine the number of siblings a <node> element has, I thought I would count the elements in the intersection of the set of <predecessor-id> children of the context node with the set of <predecessor-id> children of all the other <node> elements. I modelled the expression on the example shown on page 425 of the XSLT Programmer's Reference 2nd Edition. > > Here is a simplfied stylesheet: > > <?xml version="1.0" encoding="UTF-8" ?> > <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> > <xsl:output method="xml" indent="yes" encoding="UTF-8" /> > > <xsl:template match="/"> > <xsl:apply-templates /> > </xsl:template> > > <xsl:template match="network"> > <xsl:apply-templates /> > </xsl:template> > > <xsl:template match="node"> > <xsl:variable name="this-node-id" select="node-id" /> > <xsl:variable name="this-predecessor-nodes" select="predecessor-id" /> > <xsl:variable name="other-predecessor-nodes" select="/network/node[node-id != $this-node-id]" /> > <xsl:variable name="sibling-cnt" select="count($this-predecessor-nodes[count(. | $other-predecessor-nodes) != count($other-predecessor-nodes)])" /> > > This node id = <xsl:value-of select="$this-node-id" /> > Sibling count = <xsl:value-of select="$sibling-cnt" /> > </xsl:template> > > </xsl:stylesheet> > > This yielded the following output: > > <?xml version="1.0" encoding="UTF-8"?> > > > This node id = A > Sibling count = 1 > > > This node id = B > Sibling count = 1 > > > This node id = C > Sibling count = 1 > > > This node id = D > Sibling count = 2 > > It the intersection operation didn't do what I expected. I expected that nodes A and D would have a Sibling count of 0 and that nodes B and C would each have a sibling count of 1. > > Could anyone tell me where I'm going wrong and point me in the right direction? > Thanks. The reason is you're mixing node-identity with value-identity. The XPath expression for intersection of two node-sets selects the *identical* nodes from the two node-sets. In your case you want to find all nodes with the same *value*. Here's a transformation, which produces what you want: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8" /> <xsl:template match="/"> <xsl:apply-templates /> </xsl:template> <xsl:template match="network"> <xsl:apply-templates /> </xsl:template> <xsl:template match="node"> <xsl:variable name="this-node-id" select="node-id" /> <xsl:variable name="this-predecessor-nodes" select="/*/node[node-id = current()/node-id]/predecessor-id" /> <xsl:variable name="other-predecessor-nodes" select="/*/node[node-id != $this-node-id]/predecessor-id" /> <xsl:variable name="sibling-cnt" select="count($other-predecessor-nodes [. =$this-predecessor-nodes] )" /> This node id = <xsl:value-of select="$this-node-id" /> Sibling count = <xsl:value-of select="$sibling-cnt" /> </xsl:template> </xsl:stylesheet> When this transformation is applied on your source.xml: <network> <node> <node-id>A</node-id> <predecessor-id></predecessor-id> <successor-id>B</successor-id> </node> <node> <node-id>B</node-id> <predecessor-id>A</predecessor-id> <successor-id>D</successor-id> </node> <node> <node-id>C</node-id> <predecessor-id>A</predecessor-id> <successor-id>D</successor-id> </node> <node> <node-id>D</node-id> <predecessor-id>B</predecessor-id> <predecessor-id>C</predecessor-id> <successor-id></successor-id> </node> </network> the wanted result is produced: This node id = A Sibling count = 0 This node id = B Sibling count = 1 This node id = C Sibling count = 1 This node id = D Sibling count = 0 One final remark: the chosen representation of the graph is not good at all. I'd recommend a better one, e.g. the standard for graph representation -- graphML. Hope this helped. Cheers, Dimitre Novatchev , FXSL developer, http://fxsl.sourceforge.net/ -- the home of FXSL Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Network diagram - node se, Michael Kay | Thread | [xsl] defining namespace / function, Kaleb Pederson |
RE: [xsl] Network diagram - node se, Michael Kay | Date | RE: [xsl] Re: Network diagram - nod, cknell |
Month |