Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old August 2nd, 2005, 10:57 AM
Authorized User
 
Join Date: Jun 2005
Posts: 22
Thanks: 0
Thanked 0 Times in 0 Posts
Default Using a recursive template for various nodes

Hi!

i am trying to make a recursive template that i can call for each node of a parent. i want for this template to start at the beginning of the list, then scroll through the list of different types of nodes and tell what type of node it is. Afterwards, it should go to the next child node and do the same thing, and so on until it reaches the bottom of the list. My problem is syntactical. I have tried every possible combination that i could think of, however, i have had no luck.

I appreciate the help to anyone that can give some helpful hints.

p.s. - Note, my code must be compatible with XSLT 1.0.

Here is the code:
<xsl:template name="rel_pos">
        <xsl:param name="num" select="1"/>
            <xsl:choose>
                <xsl:when test="//w:sect/child::*[position()=$num]/@name() = 'w:p'">
                    <xsl:text>Paragraph Found </xsl:text>
                </xsl:when>
                <xsl:when test="name() = 'w:tbl'">
                    <xsl:text>Table Found </xsl:text>
                </xsl:when>
                <xsl:when test="name() = 'w:pict'">
                    <xsl:text>Picture Found </xsl:text>
                </xsl:when>
                <xsl:when test="name() = 'w:sectPr'">
                    <xsl:text>Done - end of list </xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>Unknown File! </xsl:text>
                    <error>
                        <xsl:value-of select="name()"/>
                    </error>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:call-template name="rel_pos"/>
                <xsl:param name="num" select="$num + 1"/>
            </xsl:call-template>
    </xsl:template>

 
Old August 2nd, 2005, 11:20 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The best way to test whether a node is a w:xyz node is

test="self::w:xyz"

This is especially true when using namespaces, as the form

name()='w:xyz'

tests the namespace prefix rather than the URI.

I don't know what you were thinking of with

x/y/@name() = 'w:p'

This suggests you ought to do some reading, it looks as if you've been trying to find out the rules of the language by inspired guesswork (not unusual, I'm afraid, but with XPath not very productive).

As for the recursion, I would recommend doing a "sibling recursion" here. The general logic is:

<xsl:template match="*" mode="recurse">
  do something
  <xsl:apply-templates select="following-sibling::*[1]" mode="recurse"/>
</xsl:template>

and of course you fire the thing off by applying templates to the first child.

In this case rather than having an xsl:choose within the template to switch on element type, why not have one rule per element type:

<xsl:template match="w:tbl" mode="recurse">
  <xsl:text>table found</xsl:text>
  <xsl:apply-templates select="following-sibling::*[1]" mode="recurse"/>

However, I may have misunderstood your requirement, because I can't see anything in this example that needs sibling recursion rather than a conventional depth-first apply-templates from a parent to all the children. You need sibling recursion when the processing of one child depends on information gleaned when processing its preceding siblings and passed on as a parameter.



Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old August 2nd, 2005, 12:45 PM
Authorized User
 
Join Date: Jun 2005
Posts: 22
Thanks: 0
Thanked 0 Times in 0 Posts
Default

First off, i would like to say that i do not appreciate your honesty for in highlighting amatuerity, just kidding.

I agree with you that templates with modes and matches would be the best route, however, i was wondering if you know of a good website that would have more in-depth cases for XPath than www.w3schools.com.

Also, I am still recieving possible input cases. What would be the expression for the match to catch all of the elements that have not been specified yet?

 
Old August 2nd, 2005, 02:13 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Since we're on a Wrox site, I won't recommend any web sites, I will recommend my book!

>What would be the expression for the match to catch all of the elements that have not been specified yet?

Use match="*". It will automatically have lower priority than explicit rules of the form match="foo".

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old August 2nd, 2005, 03:45 PM
Authorized User
 
Join Date: Jun 2005
Posts: 22
Thanks: 0
Thanked 0 Times in 0 Posts
Default

well, actually I just found your book on the office bookshelf. Since I have opened it up, I have almost everything that i have been looking for, so thank you.
Also, just as a side note I would like to say to the staff of Wrox that your forum and book have provided me a plethora of help and knowledge! To which I shall remain loyal.

 
Old August 2nd, 2005, 03:49 PM
Authorized User
 
Join Date: Jun 2005
Posts: 22
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I guess it would be smart of me to post the solution as well:
(in the desired template to call upon this sibling recursion template):
<xsl:apply-templates select="//a/b/child::*[1]" mode="recurse"/>

<xsl:template match="paragraph" mode="recurse">
    <xsl:param name="start_x" select="//w:pgMar/@w:left div 20"/>
    <xsl:param name="start_y" select="//w:pgMar/@w:top div 20"/>
....Do stuff here...
    <xsl:apply-templates select="following-sibling::*[1]" mode="recurse">
        <xsl:with-param name="start_x" select="$start_x + 1"/>
        <xsl:with-param name="start_y" select="$start_y + 1"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="table" mode="recurse">
    <xsl:param name="start_x" select="//w:pgMar/@w:left div 20"/>
    <xsl:param name="start_y" select="//w:pgMar/@w:top div 20"/>
....Do stuff here...
    <xsl:apply-templates select="following-sibling::*[1]" mode="recurse">
        <xsl:with-param name="start_x" select="$start_x + 1"/>
        <xsl:with-param name="start_y" select="$start_y + 1"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="picture" mode="recurse">
    <xsl:param name="start_x" select="//w:pgMar/@w:left div 20"/>
    <xsl:param name="start_y" select="//w:pgMar/@w:top div 20"/>
....Do stuff here...
    <xsl:apply-templates select="following-sibling::*[1]" mode="recurse">
        <xsl:with-param name="start_x" select="$start_x + 1"/>
        <xsl:with-param name="start_y" select="$start_y + 1"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="end" mode="recurse">
    <xsl:param name="start_x" select="//w:pgMar/@w:left div 20"/>
    <xsl:param name="start_y" select="$start_y + 1"/>
....Do stuff here...
</xsl:template>






Similar Threads
Thread Thread Starter Forum Replies Last Post
Problem in Recursive applying template ismomo XSLT 3 December 29th, 2007 11:35 PM
Recursive Template Help bucky483 XSLT 1 July 20th, 2007 12:21 PM
Recursive nodes in XML Schema XSLTer XML 1 April 13th, 2007 12:25 PM
Recursive template - Please Help! Tre XSLT 5 March 20th, 2007 11:23 AM
Handling recursive XML Nodes using XSL RichaM XSLT 5 June 21st, 2005 02:45 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.