473,406 Members | 2,843 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Recursively including all dependencies of an element

I found myself needing to find my way recursively through a document
in XSLT, finding the dependencies one element had on others, and
including only those in an initial set, their dependencies, the
dependencies of those dependencies and so on. I managed to do it, but
I'm not really happy with the method, and I'm wondering if anyone can
suggest something better.

My technique involves manipulating a string containing the names,
calling a template that adds the names of the direct dependencies to a
temporary string and then, if there are no additional names, returning
that list, or, if there are additional ones, returning a recursive
call to the template using the new list. It's pretty simple Recursion
101 code, but there's a level of indirection I don't like here. I
shouldn't be using a string of names; I would rather be using node-
sets. But whenever I tried that, I ran into issues of variables that
held things that looked like but weren't really node-sets.

Any suggestions for how I could do this without resorting to using the
names, would be appreciated.

Here's a simplified sample input document:

<root>
<x name="a">
<y dep="b"/>
<y dep="c"/>
</x>
<x name="b">
<y dep="g"/>
</x>
<x name="c">
<y dep="a"/>
</x>
<x name="e">
<y dep="b"/>
</x>
<x name="f">
<y dep="c"/>
<y dep="e"/>
</x>
<x name="g">
<y dep="h"/>
</x>
<x name="h">
<y dep="i"/>
</x>
<x name="i"/>
<x name="j">
<y dep="i"/>
</x>
</root>

Passed the parameter, "a, b", the stylesheet should note that 'a'
depends on 'b' and' c', 'b' depends on 'g', which depends on 'h',
which depends on 'i', which has no further dependencies. And 'c'
depends on 'a'. That last is important because it demonstrates that
this is not necessarily a tree structure. There are cycles.

The output should be something like:

<root>
<x name="a">
<y dep="b"/>
<y dep="c"/>
</x>
<x name="b">
<y dep="g"/>
</x>
<x name="c">
<y dep="a"/>
</x>
<x name="g">
<y dep="h"/>
</x>
<x name="h">
<y dep="i"/>
</x>
<x name="i"/>
</root>

The XSLT I use for this is pretty straightforward:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />

<xsl:param name="base" select="'a b'"/>

<xsl:variable name="start">
<xsl:call-template name="normalize">
<xsl:with-param name="data" select="$base"/>
</xsl:call-template>
</xsl:variable>

<xsl:template match="/">
<root>
<xsl:variable name="names">
<xsl:call-template name="choose-names">
<xsl:with-param name="names" select="$start"/>
</xsl:call-template>
</xsl:variable>
<xsl:for-each select="//x">
<xsl:if test="contains($names, @name)">
<xsl:text>
</xsl:text><xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</root>
</xsl:template>

<xsl:template name="normalize">
<xsl:param name="data" />
<xsl:value-of select="concat(normalize-space($data), ' ')" />
</xsl:template>

<xsl:template name="choose-names">
<xsl:param name="names"/>
<xsl:variable name="temp">
<xsl:for-each select="//x">
<xsl:variable name="name" select="@name"/>
<xsl:if test="contains($names, $name) or
//x[contains($names, @name)]/y[@dep = $name]">
<xsl:value-of select="@name"/><xsl:text</
xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="$names = $temp">
<xsl:value-of select="$temp"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="choose-names">
<xsl:with-param name="names" select="$temp" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

I know there are holes in the string processing here. I'm sure I
could tighten it up by using a separator other than space and then
doing some escaping if the name contained the separator, but since I'd
rather not be using the names anyway...

So, does anyone have suggestions for how to do this without resorting
to using strings (except to get the original set from the input
parameter?)

Thank you very much,

-- Scott Sauyet

Jun 4 '07 #1
8 2353
Scott Sauyet wrote:
I would rather be using node-
sets. But whenever I tried that, I ran into issues of variables that
held things that looked like but weren't really node-sets.
result tree fragments. If using XSLT2 is an option then that particular
problem goes away as rtf is no more (node sets are also gone) both
replaced by sequences.

I'm not quite sure what output format you want but probably something
like this in xslt1 will chase your dependencies
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />

<xsl:param name="base" select="'a b'"/>

<xsl:key name="x" match="x" use="@name"/>

<xsl:template match="root">
<xsl:param name="set" select="x[contains($base,@name)]"/>
<xsl:param name="s" select="1"/>
Stage <xsl:value-of select="$s"/set is <xsl:for-each
select="$set">
<xsl:value-of select="@name"/>
<xsl:text</xsl:text></xsl:for-each>
<xsl:variable name="nset" select="$set|key('x',$set/y/@dep)"/>
<xsl:if test="count($nset)&gt;count($set)">
<xsl:apply-templates select=".">
<xsl:with-param name="set" select="$nset"/>
<xsl:with-param name="s" select="$s+1"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

$ saxon dep.xml dep.xsl
<?xml version="1.0" encoding="utf-8"?>
Stage 1 set is a b
Stage 2 set is a b c g
Stage 3 set is a b c g h
Stage 4 set is a b c g h i

--
http://dpcarlisle.blogspot.com
Jun 4 '07 #2
Thank you very much for your help. This is a real improvement from my
ugly hack!

David Carlisle wrote:
Scott Sauyet wrote:
> I would rather be using node-
sets. But whenever I tried that, I ran into issues of variables that
held things that looked like but weren't really node-sets.

result tree fragments. If using XSLT2 is an option then that particular
problem goes away as rtf is no more (node sets are also gone) both
replaced by sequences.
I honestly don't even know what XSLT processor I'm using, at the
moment; it's whatever default Ant 1.7 has when running on Java 1.6
(Xalan?). I can switch to whatever I want, as this will just end up
part of the build process. The actual problem is to reduce a WSDL
document to a smaller one based upon a parameter that lists the high-
level services to include. I worked my way through the services,
bindings, port-types, and messages based upon that input parameter.
And, with some help from the kind people on this list, I got the
initial list of the custom xs:simpleTypes and xs:complexTypes needed
to support the selected messages, but I then need to recursively work
through their dependencies.

As I said in my original message, I had this working, but wasn't happy
with the technique. I'm glad to know that there is something better;
and I'll be updating my stylesheet soon with your suggestions.

I'm not quite sure what output format you want but probably something
like this in xslt1 will chase your dependencies
I actually need to output format to be identical to the input format,
just with a smaller set of elements chosen. It was pretty simple to
modify your suggestion, though, to get that. Thank you again for your
help.

-- Scott

Jun 5 '07 #3
Scott Sauyet wrote:
David Carlisle wrote:
>I'm not quite sure what output format you want but probably something
like this in xslt1 will chase your dependencies
I actually need to output format to be identical to the input format,
just with a smaller set of elements chosen. It was pretty simple to
modify your suggestion, though, to get that. Thank you again for your
help.
I suppose I should double-check that I'm looking at the output of my
new process rather than the old one before I claim that it's
working! :-(

Things aren't working correctly in Ant1.7/Java1.6. When I run them
through Saxon, though, it's all fine. Any idea what might be causing
this?

I was going to move this into my main code and noticed an odd bit in
my output. I had been looking at the output of an earlier version
before; the one I called the ugly hack. So I ran again with David'
Carlisle's code and noticed a subtle difference in output:

David Carlisle's
> Stage 1 set is a b
Stage 2 set is a b c g
Stage 3 set is a b c g h
Stage 4 set is a b c g h i
Mine:
Stage 1 set is a b
Stage 2 set is a b c g
Stage 3 set is a b c g h
Stage 4 set is a b c g h i

Note the extra space after "Stage 3 set is"? And stage 4 too? This
is the output of

<xsl:value-of select="@name"/>
<xsl:text</xsl:text>

for the context node of the third and fourth iteration, which seems to
be the document node itself. !!?? I checked this by inserting a line
that counts the child elements of the context node:

<xsl:value-of select="count(.//*)"/><xsl:text>:</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text</xsl:text>

And I get this output:

Stage 1 set is 2:a 1:b
Stage 2 set is 2:a 1:b 1:c 1:g
Stage 3 set is 20: 2:a 1:b 1:c 1:g 1:h
Stage 4 set is 20: 2:a 1:b 1:c 1:g 1:h 0:i

Note that the input document has twenty elements, and the counts in
this list for the number of elements inside the named elements are all
correct (x[@name='a'] has two children, 'b' has one, ... 'i' has
zero.)

I can't understand how this line:

<xsl:variable name="nset" select="$set|key('x',$set/y/@dep)"/>

with the key

<xsl:key name="x" match="x" use="@name"/>

and a $set value that contains only elements of type "x" could ever
generate a value for $nset that includes the root node. But that is
certainly what seems to be happening.

I thought I was just going crazy, but I've realized it's not me, it's
my XSLT processor that's awry. When I run it through SAXON,
everything works fine.

Anyone have an idea what this is about?

-- Scott

Jun 5 '07 #4
Scott Sauyet wrote:
Scott Sauyet wrote:

I thought I was just going crazy, but I've realized it's not me, it's
my XSLT processor that's awry. When I run it through SAXON,
everything works fine.

Anyone have an idea what this is about?

-- Scott
when something works in saxon and not in another processor you always
have the possibility that you've hit a bug somewhere. If your
description is accurate it sounds like something strange is happening
with the key.

David

--
http://dpcarlisle.blogspot.com
Jun 5 '07 #5
David Carlisle wrote:
when something works in saxon and not in another processor you always
have the possibility that you've hit a bug somewhere. If your
description is accurate it sounds like something strange is happening
with the key.
As you may be able to tell, I haven't been doing all that much XSLT
recently. I'm much more likely to doubt myself than the tools when
I'm inexperienced or rusty with a technology. But there is a clear-
cut difference between when I run this stylesheet through Saxon and
when I run it through my default processor. Maybe it's not me after
all! :-)

Is Saxon generally considered the gold standard? I don't know what
version of Xalan is being used in my default setup (Ant 1.7 on Java 6)
but it looks as though it is Xalan, since this:

javax.xml.transform.TransformerFactory.newInstance ().getClass()

returns this:
com.sun.org.apache.xalan.internal.xsltc.trax.Trans formerFactoryImpl
In any case, thank you very much for your help,

-- Scott

Jun 5 '07 #6
Scott Sauyet wrote:
I don't know what
version of Xalan is being used in my default setup (Ant 1.7 on Java 6)
but it looks as though it is Xalan,
<xsl:value-of select="system-property('xsl:vendor')" />

<xsl:value-of select="system-property('xsl:vendor-url')" />

should reveal all
--
http://dpcarlisle.blogspot.com
Jun 5 '07 #7
On Jun 5, 7:05 pm, David Carlisle <david-n...@dcarlisle.demon.co.uk>
wrote:
<xsl:value-of select="system-property('xsl:vendor')" />
<xsl:value-of select="system-property('xsl:vendor-url')" />

should reveal all
And it does.:

Vendor: Apache Software Foundation (Xalan XSLTC)
URL: http://xml.apache.org/xalan-j

Thank you very much. I'm pretty swamped today, but later this week,
I'll try to post a simple test case and see about reporting a bug to
Xalan.

Thanks,

-- Scott

Jun 6 '07 #8
Reminder: The version of Xalan that ships with the JVM is pretty far
outdated. If you've found a bug, the first thing to try is downloading a
current version from Apache, overriding the JVM's copy (you'll need to
play with the bootclasspath/endorsed-libraries configuration to do this;
instructions are also on the Xalan website), and see if the problem
persists.

If that cures it, you're good to go... except that anyone else using
your code will also have to install the updated version of the processor.

If not, then by all means submit a bug report!

--
Joe Kesselman / Beware the fury of a patient man. -- John Dryden
Jun 6 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Neil | last post by:
Hi, I'm new to all this so any help would be appreciated. I'm trying to build a DOM Tree by retrieving info from the database and storing these objects as elements. I have a structure a bit...
2
by: Stanimir Stamenkov | last post by:
I'm trying to find out if it is permissible to include a schema document with absent target namespace to a schema with specified target namespace, and if it is, what are the rules to resolve the...
0
by: TGF | last post by:
Hello, I am creating a console app. I try to link a static library by including it in the Linker-Input-Additional Dependencies field under the Project properties. Then I specify the path to...
0
by: TGF | last post by:
Hello, I am creating a console app. I try to link a static library by including it in the Linker-Input-Additional Dependencies field under the Project properties. Then I specify the path to...
3
by: Kamen TOMOV | last post by:
Hi, Is uploading recursively directories to a web server possible with JavaScript? I mean is it possible read a directory recursively and dynamically construct <input type="file"> with value...
8
by: david.lindsay.green | last post by:
Hello all, I am quite new a web scripting and making web pages in general and I have stumbled across a problem I have as yet been unable to solve. I am trying to take the contents of a textarea box...
7
by: DFS | last post by:
Before I build my own custom system, I wondered if anyone here has created or knows of some commercial systems (say for construction cost/time estimating) that help manage projects where some Task...
0
by: Mathieu Prevot | last post by:
2008/9/24 Jaime Huerta Cepas <jhuerta@cipf.es>: IMHO this is too complex to commit. Macport is a way to do what you want, but packages may not be up to date enough. Maybe the easiest and...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.