RE: [xsl] FW: Path Reversal

Subject: RE: [xsl] FW: Path Reversal
From: "McNally, David" <David.McNally@xxxxxxxxxx>
Date: Mon, 28 Jan 2002 12:57:12 -0500
> From: Alek Andreev [mailto:alek@xxxxxxxx]
>
> Suppose I have the following piece of XML:
> 
> <node name="funstuff">
>   <node name="jokes">
>     <node name="veryfunnyjoke"/>
>   </node>
> </node>
> 
> I have a path (as a string) which is composed of the @names of the
> nodes. It looks like /funstuff/jokes/veryfunnyjoke. How can I write a
> template (or an EXSLT function) that returns the node the 
> path points to
> (e.g. veryfunnyjoke)?


I imagine the easiest solution might be to use lots of extensions to do some
regex find and replaces on the path, to turn /funstuff/jokes/veryfunnyjoke
into /node[@name='funstuff']/node[@name='jokes']/node[@name='veryfunnyjoke']
and then to evaluate it, but I thought I'd try to do it in pure XSLT 1.0.

I'm still learning, so this solution is probably not the best - basically
I'm using a template that chops up each bit of the path, using the first bit
to select elements, and then calling itself recursively (through the
walkPath mode element template) with the rest of the path.  I was using a
test file with text at the end node - and so am just returning that.

test.xml:
<node name="funstuff">
	<node name="jokes">
		<node name="veryfunnyjoke">Number 1 1 </node>
		<node name="veryfunnyjoke2">Number 1 2 </node>
	</node>
	<node name="jokes2">
		<node name="veryfunnyjoke">Number 2 1 </node>
		<node name="veryfunnyjoke2">Number 2 2 </node>
	</node>
</node>

test.xsl:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:fo="http://www.w3.org/1999/XSL/Format";>

<xsl:template match="/">
	<xsl:text>
	/funstuff/jokes2/veryfunnyjoke  = </xsl:text>
	<xsl:call-template name="walkPath">
		<xsl:with-param name="thisPath"
select="'/funstuff/jokes2/veryfunnyjoke'"/>
	</xsl:call-template>

	<xsl:text>
	/funstuff/jokes/veryfunnyjoke2  = </xsl:text>
	<xsl:call-template name="walkPath">
		<xsl:with-param name="thisPath"
select="'/funstuff/jokes/veryfunnyjoke2'"/>
	</xsl:call-template>

</xsl:template>

<xsl:template match="*" mode="walkPath">
	<xsl:param name="thisPath" select="''"/>
	<xsl:call-template name="walkPath">
		<xsl:with-param name="thisPath" select="$thisPath"/>
	</xsl:call-template>
</xsl:template>

<xsl:template name="walkPath">
	<xsl:param name="thisPath" select="''"/>
	<xsl:variable name="bitBefore" select="substring-before($thisPath,
'/')"/>
	<xsl:variable name="bitAfter" select="substring-after($thisPath,
'/')"/>
	<xsl:choose>
		<xsl:when test="$bitAfter">
			<xsl:choose>
				<xsl:when test="$bitBefore">
					<xsl:apply-templates select="*[@name
= $bitBefore]" mode="walkPath">
						<xsl:with-param
name="thisPath" select="$bitAfter"/>
					</xsl:apply-templates>
				</xsl:when>
				<xsl:otherwise>
					<!-- This really just handles a
leading '/' - would not function well with '//' in middle of the path -->
					<xsl:call-template name="walkPath">
						<xsl:with-param
name="thisPath" select="$bitAfter"/>
					</xsl:call-template>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:when>
		<xsl:otherwise>
			<xsl:choose>
				<xsl:when test="$bitBefore">
					<xsl:apply-templates select="*[@name
= $bitBefore]" mode="walkPath"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:choose>
						<xsl:when test="$thisPath">
							<xsl:apply-templates
select="*[@name = $thisPath]" mode="walkPath"/>
						</xsl:when>
						<xsl:otherwise>
							<!-- NOW GOT THE
NODE - do whatever with it -->
							<xsl:apply-templates
select="text()"/>		
						</xsl:otherwise>
					</xsl:choose>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:otherwise>
	</xsl:choose> 	
</xsl:template>


c:\>saxon test.xml test.xsl
<?xml version="1.0" encoding="utf-8"?>
        /funstuff/jokes2/veryfunnyjoke  Number  2 1
        /funstuff/jokes/veryfunnyjoke2  Number 1 2

Hope this helps,
David.
--
David McNally            Moody's Investors Service
Software Engineer        99 Church St, NY NY 10007 
David.McNally@xxxxxxxxxx            (212) 553-7475 


> 


---------------------------------------

The information contained in this e-mail message, and any attachment thereto, is confidential and may not be disclosed without our express permission.  If you are not the intended recipient or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that you have received this message in error and that any review, dissemination, distribution or copying of this message, or any attachment thereto, in whole or in part, is strictly prohibited.  If you have received this message in error, please immediately notify us by telephone, fax or e-mail and delete the message and all of its attachments.  Thank you.

Every effort is made to keep our network free from viruses.  You should, however, review this e-mail message, as well as any attachment thereto, for viruses.  We take no responsibility and have no liability for any computer virus which may be transferred via this e-mail message.


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread