Subject: Re: [xsl] Hierearchy navigation in XSL From: Dimitre Novatchev <dnovatchev@xxxxxxxxx> Date: Wed, 16 Oct 2002 00:07:39 -0700 (PDT) |
I tried to send this twice two days ago, but due to some reason, I cannot see it in the archives and the digests. Sorry, if someone has received more than one instance of this message. --- Scott Bronson wrote: > Hello. I've solved most of this problem, but the last tiny bit has > me > stumped. I'm hoping someone can tell me how to fix this. > > Here's some input: > > > <masterdoc> > <class name="Object" namespace="System"/> > <class name="Array" namespace="System"/> > <class name="ArrayList" namespace="System.Collections"/> > <class name="Comparer" namespace="System.Collections"/> > <class name="Grimey" > namespace="System.Collections.Overkill"/> > <class name="Formatter" > namespace="System.Runtime.Serialization"/> > <class name="ObjectHandle" namespace="System.Runtime.Remoting"/> > <class name="Garbage" namespace="Other.SubAPI"/> > </masterdoc> > > > My script accepts a parameter that tells where it is in the > hierarchy. > It then outputs all immediate child nodes at that level in the > hierarchy. > > Some examples: if we're at "System", the script should output > "Collections" and "Runtime". If we're at "System.Collections", it > should output "Overkill". If we're at "", it should output "System" > and > "Other". If at "Other", output "SubAPI". Seems a fairly easy > problem, > right? > > > > Here's my script right now: > > > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > version="1.0"> > <xsl:output method="text"/> > <xsl:param name="ns"/> > <xsl:key name='uniq' match='class' use='@namespace'/> > > <xsl:template match="/masterdoc"> > <xsl:for-each > select="class[generate-id()=generate-id(key('uniq',@namespace)[1])]"> > <xsl:sort select="@namespace"/> > <xsl:choose> > <xsl:when test="string-length($ns)=0"> > <xsl:value-of select="@namespace"/> > </xsl:when> > <xsl:when test="starts-with(@namespace,concat($ns,'.'))"> > <xsl:value-of > select="substring(@namespace,string-length($ns)+2)"/> > </xsl:when> > </xsl:choose> > <xsl:text> > </xsl:text> > </xsl:for-each> > </xsl:template> > > </xsl:stylesheet> > > > > Here are some example runs of this script: > > xalan -Q -XSL samp1.xsl -IN sample.xml -PARAM ns > "'System.Collections'" > Overkill > > xalan -Q -XSL samp1.xsl -IN sample.xml -PARAM ns "'System'" > Collections > Collections.Overkill > Runtime.Remoting > Runtime.Serialization > > > The last one illustrates the problem. It should have output only > "Collections" and "Runtime". > > I picture the algorithm being something like: > if(not(already copied string-before("Runtime.Remoting", ".")) > then copy string-before("Runtime.Remoting", ".") to output > > I've tried various combinations of preceding, preceding sibling, and > position to try to figure out what I've already output. I even tried > key() and using IDs to navigate the parent. All has resulted in > frustration. > > Does anyone have any idea of what I can do? I'm out of ideas. > > Thank you! > > - Scott Hi Scott, Here is a solution: The Muenchian method for grouping cannot be directly applied, as xsl:key cannot contain a reference to an xsl:variable. Therefore, I'm doing this in two passes and do not depend on the "class" elements being initially sorted on the values of their "namespace" attribute: First get an RTF containing "childName" elements whose value is every token in any "namespace" attribute, which immediately follows the string contained in your parameter. Then convert this RTF to a regular xml document and process it with the Muenchian method. Here's the transformation: ========================= <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:vendor="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="vendor"> <xsl:output method="text"/> <xsl:key name="kChildren" match="childName" use="."/> <xsl:template match="/"> <xsl:param name="pPrefix" select="'System'"/> <xsl:variable name="vprefTest"> <xsl:choose> <xsl:when test="$pPrefix"> <xsl:value-of select="concat('.', $pPrefix, '.')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="'.'"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="vrtfImmChildren"> <xsl:for-each select="/*/*/@namespace [starts-with(concat('.', .), $vprefTest )]"> <childName> <xsl:variable name="vSuffix" select="substring-after(concat('.', .), $vprefTest )"/> <xsl:choose> <xsl:when test="contains($vSuffix, '.')"> <xsl:value-of select="substring-before($vSuffix, '.')" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$vSuffix"/> </xsl:otherwise> </xsl:choose> </childName> </xsl:for-each> </xsl:variable> <xsl:variable name="vImmChildren" select="vendor:node-set($vrtfImmChildren)"/> <xsl:for-each select="$vImmChildren"> <xsl:for-each select="*[generate-id() = generate-id(key('kChildren', . )[1] ) ]"> <xsl:value-of select="concat(., '
')"/> </xsl:for-each> </xsl:for-each> </xsl:template> </xsl:stylesheet> When applied on your source xml document: ======================================== <masterdoc> <class name="Object" namespace="System"/> <class name="Array" namespace="System"/> <class name="ArrayList" namespace="System.Collections"/> <class name="Comparer" namespace="System.Collections"/> <class name="Grimey" namespace="System.Collections.Overkill"/> <class name="Formatter" namespace="System.Runtime.Serialization"/> <class name="ObjectHandle" namespace="System.Runtime.Remoting"/> <class name="Garbage" namespace="Other.SubAPI"/> </masterdoc> the result is: ============= Collections Runtime If I change the "pPrefix" parameter to "", now the result is: ================= System Other Hope this helped. ===== Cheers, Dimitre Novatchev. http://fxsl.sourceforge.net/ -- the home of FXSL __________________________________________________ Do you Yahoo!? Faith Hill - Exclusive Performances, Videos & More http://faith.yahoo.com XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Hierearchy navigation in , David Carlisle | Thread | Re: [xsl] Hierearchy navigation in , Scott Bronson |
[xsl] Re: Insert a node into an att, Dimitre Novatchev | Date | Re: [xsl] Selecting all ancestors, Jeni Tennison |
Month |