|
[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Hierearchy navigation in XSL
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
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|

Cart








