This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Selecting a tree...
- From: Klaus-Georg Adams <Klaus-Georg dot Adams at sap dot com>
- To: xsl-list at lists dot mulberrytech dot com
- Date: Wed, 30 Jan 2002 11:31:29 +0100 (MET)
- Subject: [xsl] Selecting a tree...
- Reply-to: xsl-list at lists dot mulberrytech dot com
Hi,
I have an XML file which represents multiple trees like so:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE document [
<!ELEMENT document (node*)>
<!ELEMENT node (subnode*)>
<!ATTLIST node name NMTOKEN #REQUIRED
isroot (true|false) "false">
<!ELEMENT subnode EMPTY>
<!ATTLIST subnode name NMTOKEN #REQUIRED>
]>
<document>
<node name="root1" isroot="true">
<subnode name="node1"/>
<subnode name="node2"/>
</node>
<node name="root2" isroot="true">
</node>
<node name="node1">
<subnode name="node3"/>
</node>
<node name="node2">
<subnode name="node3"/>
</node>
<node name="node3"/>
</document>
A node can refer to subnodes by their name. Names are unique. There
can be multiple roots in the XML file. A node can be referenced
multiple times in any given tree.
I would like to write a stylesheet which gets as parameter a nodename
of a rootnode, and which spits out an XML file containing all nodes
referenced by the tree, but, and here's the catch: only once for each
node.
Thus, the transformation should remove root2 from the XML file above
if $rootnode is set to root1.
Following the tree and spitting out all nodes in that tree is easy:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml"
indent="yes"/>
<xsl:param name="rootnode"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="document">
<document>
<xsl:apply-templates select="node[@name = $rootnode]" mode="follow"/>
</document>
</xsl:template>
<xsl:template match="node" mode="follow">
<xsl:apply-templates select="."/>
<xsl:apply-templates select="//node[@name=current()/subnode/@name]" mode="follow"/>
</xsl:template>
<!-- identity transformation -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
But this will spit out nodes as often as they apear in the tree. Does
anybody see a way around this?
The only solution I can think of (in pure XSLT) would need two
transformations: the first would write an intermediate file with a
list of nodenames which have to appear in the final document (with
duplicates) and a second one, which would remove the duplicates and
write the real output file.
Is there a way to do it in one transformation?
Regards, kga
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list