Subject: RE: Constructing a tree from leaf nodes (knowing the tree structure)?
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 20 Apr 2007 08:49:18 +0100
|
OK, so you have two rules, one for leaf nodes and one for non-leaf nodes.
Something like this:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:variable name="tree" select="/"/>
<xsl:variable name="data" select="doc('data.xml')/data"/>
<!-- rule for non-leaf nodes -->
<xsl:template match="*[*]">
<xsl:copy>
<xsl:attribute name="complete"
select="every $n in descendant::* satisfies
exists($data/*[name() = name($n)])"/>
<xsl:attribute name="result"
select="every $n in descendant::* satisfies
exists($data/*[name() = name($n) and @result='true']) "/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!-- rule for leaf nodes -->
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="complete"
select="exists($data/*[name() = name(current())])"/>
<xsl:attribute name="result"
select="$data/*[name() = name(current())]/@result"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This actually gives the right answer, but it's possible that the rule for
non-leaf nodes should only look at leaf descendants, not at all descendants,
which would change it to:
<xsl:template match="*[*]">
<xsl:copy>
<xsl:attribute name="complete"
select="every $n in descendant::* satisfies
(* or exists($data/*[name() = name($n)]))"/>
<xsl:attribute name="result"
select="every $n in descendant::* satisfies
(* or exists($data/*[name() = name($n) and
@result='true']))"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
Michael Kay
http://www.saxonica.com/
> Thanks, Michael.
>
> The "complete" attribute signifies whether all required
> descendent nodes are present or not. For a leaf node I
> assume that if it is present complete="true" and if it is
> absent complete="false". Hence f has complete="false". I
> agree it is redundant for the data elements c,d,h and i to
> have complete="true" but I need the attribute to be present
> to that I can style the tree in HTML.
>
> As far as the ancestors go, b is complete because all its
> descendants are complete, while e and a are incomplete
> because some of their descendants are incomplete.
>
> Simon
>
>
> -----Original Message-----
> From: Michael Kay [mailto:mike@xxxxxxxxxxxx]
> Sent: April 19, 2007 4:14 PM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: Constructing a tree from leaf nodes
> (knowing the tree structure)?
>
> XSLT is certainly suited to the problem. However, I can't
> reverse engineer your requirements from your example. The
> following stylesheet comes close, and there are various ways
> I could refine it to produce your required output, but I'd be
> using guesswork as to what the requirements are, so it would
> be better if you do that yourself! In particular I can't see
> why you consider b to be complete while f is incomplete, and
> since all the data elements say complete="true", it's hard to
> see what role that attribute plays in the calculation.
>
> I used your tree as the principal input, and wrapped the
> other nodes in a <data> element and called it data.xml. The
> stylesheet is:
>
> <xsl:stylesheet version="2.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
>
> <xsl:output indent="yes"/>
>
> <xsl:variable name="tree" select="/"/>
> <xsl:variable name="data" select="doc('data.xml')/data"/>
>
> <xsl:template match="*">
> <xsl:copy>
> <xsl:attribute name="complete"
> select="every $n in descendant::* satisfies
> exists($data/*[name() = name($n)])"/>
> <xsl:attribute name="result"
> select="every $n in descendant::* satisfies
> exists($data/*[name() = name($n) and
> @result='true']) "/>
> <xsl:apply-templates/>
> </xsl:copy>
> </xsl:template>
>
> </xsl:stylesheet>
>
> Michael Kay
> http://www.saxonica.com/
>
> > -----Original Message-----
> > From: Simon Shutter [mailto:simon@xxxxxxxxxxx]
> > Sent: 19 April 2007 21:02
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: Constructing a tree from leaf nodes (knowing
> the tree
> > structure)?
> >
> > This is probably a poorly posed question but essentially I
> am trying
> > to determine if XSLT is suited to the following problem.
> >
> > Say I have a node fragment that defines a tree structure in
> which each
> > element appears only once eg.
> >
> > <a>
> > <b>
> > <c/>
> > <d/>
> > </b>
> > <e>
> > <f/>
> > <g>
> > <h/>
> > <i/>
> > </g>
> > </e>
> > </a>
> >
> > I then have data for some of the leaf nodes ie.
> >
> > <c complete="true" result="true"/>
> > <d complete="true" result="false"/>
> > <h complete="true" result="true"/>
> > <i complete="true" result="true"/>
> >
> > In this example the leaf node </f> is missing.
> >
> > Is it possible to create a node fragment that mimics the tree
> > structure and sets ancestor attributes according to the presence or
> > absence of leaf nodes and their attributes?
> >
> > The desired output would be:
> >
> > <a complete="false" result="false">
> > <b complete="true" result="false">
> > <c complete="true" result="true"/>
> > <d complete="true" result="false"/>
> > </b>
> > <e complete="false" result="true">
> > <f complete="false" result=""/>
> > <g complete="true" result="true"/>
> > <h complete="true" result="true"/>
> > <i complete="true" result="true"/>
> > </g>
> > </e>
> > </a>
|