Hi Ben,
At 07:28 AM 12/23/2004, you wrote:
I wondered if Mukul's suggestion could be generalised to function on cases
where the desired tags in the input xsl may be at any level of nesting
e.g. with 'alertBox' we might have :
<root>
<othertag>
<gui type="alertBox"></gui>
</othertag>
<gui type="tooltip"></gui>
<gui type="help"></gui>
<gui type="tooltip"></gui>
<othertag>
<deepertag>
<gui type="alertBox"></gui>
</deepertag>
</othertag>
<gui type="tooltip"></gui>
<gui type="help"></gui>
</root>
By changing the gui select in the for-each and the if test from
preceeding-sibling to preceeding it (I think) simply scans backwards in
the document to see if it has already encountered the type or not.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/root">
<root>
<xsl:for-each select="//gui">
<xsl:if test="not(@type =
preceding::gui/@type)">
<xsl:element name="{(_at_)type}" />
</xsl:if>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
I have not tested it exhaustively, but it seems to work perfectly, and
does not depend on knowing what types are available beforehand.
It certainly works, and has been used. In fact it might be called the
"canonical" solution. (As Mukul remarked, sometimes it also needs to be
extended a bit to account for ancestors.)
+In what ways might this +not+ be the general solution to the problem?+
It's very general, but commonly avoided simply because of its performance
implications. (The simple shift from preceding:: to preceding-sibling::, in
cases where the nodes are not scattered, helps with this which may be why
Mukul used the latter.) In a naive implementation, the entire tree will be
traversed backwards to the beginning for every @type attribute checked.
That's pretty serious cycling.
It is certainly logical, and elegant.
Yes, as XSLT so often is, when you give it a chance. Though admittedly its
logic is its own. :-)
You also wrote:
However, the scenario I outlined was overly simplistic.
+It should not be assumed that the gui tags are are siblings. They may be
scattered throughout the document at various nestings+
One of my additional problems is that I am using PHP5 and thus James
Clark's expat parser, which doesn't support keys?
Expat is a XML parser, not an XSLT processor. I don't know offhand which
processor PHP5 is using. But determining whether keys are supported is
easy. (Clark's XT processor didn't implement keys but that's a different
chunk of code from expat. For one, XT is in Java while Expat is in C.)
In this case I wonder which of the various proposed techniques will work!
Both my in-between solution, and Dimitre's (which I'll let him explain, but
which amounts to a more sophisticated XSLT-2 version of the approach I
used, using a sequence instead of a node-set) will both work with scattered
nodes, given a tweak or two. So will George's brute-force technique.
Cheers,
Wendell
======================================================================
Wendell Piez
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--