RE: [xsl] finding lowest level in ancestor:: axis

Subject: RE: [xsl] finding lowest level in ancestor:: axis
From: Florent Georges <darkman_spam@xxxxxxxx>
Date: Fri, 27 Jan 2006 00:19:48 +0100 (CET)
  Hi

  Is it what you're looking for?

    ~> cat drafts/ancestor.xml
    <!DOCTYPE div1 [
      <!ATTLIST table id ID #IMPLIED>
    ]>
    <div1>
      <p>Some text here</p>
      <div2>
        <p>More text <ref idref="t1"/></p>
        <example>
          <table id='t1'/>
        </example>
      </div2>
    </div1>

    ~> cat drafts/ancestor.xsl
    <xsl:transform
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
        version="1.0">

      <xsl:output method="text"/>

      <xsl:template match="/">
        <xsl:apply-templates select="//ref" mode="one"/>
        <xsl:text>&#10;</xsl:text>
        <xsl:apply-templates select="//ref" mode="two"/>
      </xsl:template>

      <xsl:template match="ref" mode="one">
        <xsl:variable name="parent"
                      select="id(@idref)/ancestor::div10 |
                              id(@idref)/ancestor::div9 |
                              id(@idref)/ancestor::div8 |
                              id(@idref)/ancestor::div7 |
                              id(@idref)/ancestor::div6 |
                              id(@idref)/ancestor::div5 |
                              id(@idref)/ancestor::div4 |
                              id(@idref)/ancestor::div3 |
                              id(@idref)/ancestor::div2 |
                              id(@idref)/ancestor::div1"/>
        <xsl:value-of select="count($parent)"/>
        <xsl:text> / </xsl:text>
        <xsl:value-of select="$parent/local-name()"/>
      </xsl:template>

      <xsl:template match="ref" mode="two">
        <xsl:variable name="parent"
                      select="id(@idref)/ancestor::*[
                                  self::div1 or self::div2
                                  or self::div3 or self::div4
                                  or self::div5 or self::div6
                                  or self::div7 or self::div8
                                  or self::div9 or self::div10
                                ][1]"/>
        <xsl:value-of select="count($parent)"/>
        <xsl:text> / </xsl:text>
        <xsl:value-of select="$parent/local-name()"/>
      </xsl:template>

    </xsl:transform>

    ~> saxon drafts/ancestor.xml drafts/ancestor.xsl
    Warning: Running an XSLT 1.0 stylesheet with an XSLT
    2.0 processor
    2 / div1
    1 / div2

  BTW, your solution doesn't select only div1, but it's the first node
of the node-set (because no more in the context of the ancestor axis
where it's the last node), so it's the one used to construct your
result.

  Regards,

--drkm


Dan Vint wrote:

> I'm trying to build some links between a tag (table, graphic,
> illustration) 
> and the referencing tag. So I have a <ref> tag that has an idref
> attribute 
> that can reference these objects anywhere and these objects can
> appear 
> directly under one of my division tags or they might be inside a
> table or 
> code or some other lower level structure, ultimately in the link I
> want to 
> build I need to know the containing division tag which is not always
> the 
> immediate parent.
> 
> So I have a document that looks like:
> 
> <div1>
>       <p>Some text here</p>
>       <div2>
>             <p>More text <ref idref="t1'/></p>
>               <example>
>                       <table id='t1'/>
>               </example>
>       </div2>
> </div1>
> 
> I thought the following would work:
> 
> <template match="ref">
> <xsl:variable name="parent"
>     select="id(@idref)/ancestor::div10 |
> 	    id(@idref)/ancestor::div9 |
> 	    id(@idref)/ancestor::div8 |
> 	    id(@idref)/ancestor::div7 |
> 	    id(@idref)/ancestor::div6 |
> 	    id(@idref)/ancestor::div5 |
> 	    id(@idref)/ancestor::div4 |
> 	    id(@idref)/ancestor::div3 |
> 	    id(@idref)/ancestor::div2 |
> 	    id(@idref)/ancestor::div1                    	
>     "/>
>       <a href="{concat(generate-id($parent), '.html#', @idref)}">
>            Table <xsl:number level="any" from="div1" count="table"
> format="1"/>
>            <xsl:text> </xsl:text>		
>        </a>
> </xsl:template>
> 
> Instead of finding the first <div2> tag this seems to always locate
> the 
> highest ancestor in the tree and comes back with the <div1>. I even
> changed 
> the order of the select for the variable to be high to low and low to
> high 
> and nothing changed. I though maybe there might be an evaluation
> order 
> going on.
> 
> I thought about adding a [1] to each item in the select for the
> variable 
> but I don't think that changes anything, both the div2 and div1 are
> the 
> first of that type. I think my only option is to split this select
> out into 
> a chose statement which would force the order, is there another way
> to do 
> this instead of:
> 
> <xsl:variable name="parent">
>      <xsl:choose>
>          <xsl:when test="id(@idref)/ancestor::div10">
> 	  <xsl:value-of select="id(@idref)/ancestor::div10"/>
>          </xsl:when>
> ....
> </xsl:choose>
> </xsl:variable>
> 
> thanks
> ..dan
> 
> PS still using XSLT v1
>
---------------------------------------------------------------------------
> Danny Vint
> 
> Specializing in Panoramic Images of California and the West
> http://www.dvint.com
> 
> voice: 510-522-4703
> 
> When H.H. Bennett was asked why he preferred to be out
> shooting landscapes rather than spending time in his portrait studio:
> 
> "It is easier to pose nature and less trouble to please."
> 
> http://www.portalwisconsin.org/bennett_feature.cfm
> 
> 



	

	
		
___________________________________________________________________________ 
Nouveau : tiliphonez moins cher avec Yahoo! Messenger ! Dicouvez les tarifs exceptionnels pour appeler la France et l'international.
Tilichargez sur http://fr.messenger.yahoo.com

Current Thread