Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > [XSL] Obtaining an attribute from self or ancestor

Reply
Thread Tools

[XSL] Obtaining an attribute from self or ancestor

 
 
Ebenezer
Guest
Posts: n/a
 
      10-21-2008
Hello!

Let's suppose we have an XML with some nested NODE nodes:

<root attr="first">
<node id="1" attr="mike">
<node id="2" />
<node id="3" attr="dave" />
</node>
<node id="4">
<node id="5" attr="peter" />
</node>
</root>

What I want to achieve is to have an XSL that:
- takes a $id variable externally from a PHP script
- finds the node with @id=$id
- outputs the value "@attr" attribute IF PRESENT, otherwise the parent's
"@attr" attribute IF PRESENT, otherwise the grandparent's... recursively
traversing from parent to parent, until an @attr value is found

This won't work for some nodes:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0">
<xslutput method="html" />
<xsl:template match="root">
<xsl:apply-templates select="//node[@id=$id]" />
</xsl:template>
<xsl:template match="node">
<xsl:choose>
<xsl:when test="not(@attr)"><xsl:apply-templates ".." /></xsl:when>
<xsltherwise><xsl:value-of select="@attr" /></xsltherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
 
Reply With Quote
 
 
 
 
Martin Honnen
Guest
Posts: n/a
 
      10-21-2008
Ebenezer wrote:

> What I want to achieve is to have an XSL that:
> - takes a $id variable externally from a PHP script
> - finds the node with @id=$id
> - outputs the value "@attr" attribute IF PRESENT, otherwise the parent's
> "@attr" attribute IF PRESENT, otherwise the grandparent's... recursively
> traversing from parent to parent, until an @attr value is found
>
> This won't work for some nodes:
>
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0">
> <xslutput method="html" />


You need to define the id parameter
<xslaram name="id"/>

> <xsl:template match="root">
> <xsl:apply-templates select="//node[@id=$id]" />
> </xsl:template>
> <xsl:template match="node">
> <xsl:choose>
> <xsl:when test="not(@attr)"><xsl:apply-templates ".."
> /></xsl:when>


That is not the correct syntax, you need
<xsl:apply-templates select=".."/>
Also it is not clear what you want to do if you do not find a 'node'
ancestor element with an 'attr' attribute.
If you walk up to the 'root element then the template matching that will
lead to infinite recursion. So perhaps you should better use
<xsl:apply-templates select="parent::node"/>
Or if you want to walk up to the 'root' element as well you need a mode e.g.
<xsl:apply-templates select=".." mode="attribute-check"/>

and then you need to add that mode parameter to the template e.g.


<xsl:template match="root">
<xsl:apply-templates select="//node[@id=$id]"
mode="attribute-check" />
</xsl:template>
<xsl:template match="node | root" mode="attribute-check">
<xsl:choose>
<xsl:when test="not(@attr)"><xsl:apply-templates
select="parent::*" /></xsl:when>
<xsltherwise><xsl:value-of select="@attr" /></xsltherwise>
</xsl:choose>
</xsl:template>




--

Martin Honnen
http://JavaScript.FAQTs.com/
 
Reply With Quote
 
 
 
 
Ebenezer
Guest
Posts: n/a
 
      10-21-2008
Martin Honnen ha scritto:
> Ebenezer wrote:
>
>> What I want to achieve is to have an XSL that:
>> - takes a $id variable externally from a PHP script
>> - finds the node with @id=$id
>> - outputs the value "@attr" attribute IF PRESENT, otherwise the
>> parent's "@attr" attribute IF PRESENT, otherwise the grandparent's...
>> recursively traversing from parent to parent, until an @attr value is
>> found
>>
>> This won't work for some nodes:
>>
>> <?xml version="1.0"?>
>> <xsl:stylesheet version="1.0">
>> <xslutput method="html" />

>
> You need to define the id parameter
> <xslaram name="id"/>


Are you sure? I don't know if it's a standard behaviour, but other
stylesheet's I've made take the parameters with no effort or definition...

> That is not the correct syntax, you need
> <xsl:apply-templates select=".."/>


Sorry, that was my mistake in pasting the code, it's with "select" indeed...

> Also it is not clear what you want to do if you do not find a 'node'
> ancestor element with an 'attr' attribute.
> If you walk up to the 'root element then the template matching that will
> lead to infinite recursion. So perhaps you should better use
> <xsl:apply-templates select="parent::node"/>


Yes! There was an infinite recursion indeed but I didn't find a clue on
it...

> Or if you want to walk up to the 'root' element as well you need a mode
> e.g.
> <xsl:apply-templates select=".." mode="attribute-check"/>
>
> and then you need to add that mode parameter to the template e.g.


This info was really valuable. Thanks a lot and excuse me for the multipost.
 
Reply With Quote
 
Pavel Lepin
Guest
Posts: n/a
 
      10-21-2008

Ebenezer <(E-Mail Removed)> wrote in
<bRgLk.86409$(E-Mail Removed)>:
> <root attr="first">
> <node id="1" attr="mike">
> <node id="2" />
> <node id="3" attr="dave" />
> </node>
> <node id="4">
> <node id="5" attr="peter" />
> </node>
> </root>
>
> What I want to achieve is to have an XSL that:
> - takes a $id variable externally from a PHP script
> - finds the node with @id=$id
> - outputs the value "@attr" attribute IF PRESENT,
> otherwise the parent's "@attr" attribute IF PRESENT,
> otherwise the grandparent's... recursively traversing from
> parent to parent, until an @attr value is found


<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslaram name="id"/>
<xsl:template match="/">
<xsl:value-of select=
"(//node[@id=$id]/ancestor-or-self::*/@attr)[last()]"
/>
</xsl:template>
</xsl:stylesheet>

HTH, HAND.

--
If we want the average quality of computer programs to rise
by 1000%, all we have to do is carefully to select 90% of
the world's programmers, and shoot them. --Richard
Heathfield in <(E-Mail Removed)>
 
Reply With Quote
 
Dimitre Novatchev
Guest
Posts: n/a
 
      10-24-2008
Actually, this can be achieved with a single XPath one-liner (even without
XSLT being involved).

Use:

//node[@id = $id]/ancestor-or-self::*[@attr][1]/@attr


Cheers,
Dimitre Novatchev


"Ebenezer" <(E-Mail Removed)> wrote in message
news:bRgLk.86409$(E-Mail Removed)...
> Hello!
>
> Let's suppose we have an XML with some nested NODE nodes:
>
> <root attr="first">
> <node id="1" attr="mike">
> <node id="2" />
> <node id="3" attr="dave" />
> </node>
> <node id="4">
> <node id="5" attr="peter" />
> </node>
> </root>
>
> What I want to achieve is to have an XSL that:
> - takes a $id variable externally from a PHP script
> - finds the node with @id=$id
> - outputs the value "@attr" attribute IF PRESENT, otherwise the parent's
> "@attr" attribute IF PRESENT, otherwise the grandparent's... recursively
> traversing from parent to parent, until an @attr value is found
>
> This won't work for some nodes:
>
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0">
> <xslutput method="html" />
> <xsl:template match="root">
> <xsl:apply-templates select="//node[@id=$id]" />
> </xsl:template>
> <xsl:template match="node">
> <xsl:choose>
> <xsl:when test="not(@attr)"><xsl:apply-templates ".." /></xsl:when>
> <xsltherwise><xsl:value-of select="@attr" /></xsltherwise>
> </xsl:choose>
> </xsl:template>
> </xsl:stylesheet>



 
Reply With Quote
 
Richard Tobin
Guest
Posts: n/a
 
      10-24-2008
In article <490139f9$0$17067$(E-Mail Removed)>,
Dimitre Novatchev <(E-Mail Removed)> wrote:

>Actually, this can be achieved with a single XPath one-liner (even without
>XSLT being involved).
>
>Use:
>
> //node[@id = $id]/ancestor-or-self::*[@attr][1]/@attr


Or, if you find it clearer not to repeat @attr:

(//node[@id = $id]/ancestor-or-self::*/@attr)[last()]

-- Richard
--
Please remember to mention me / in tapes you leave behind.
 
Reply With Quote
 
Dimitre Novatchev
Guest
Posts: n/a
 
      10-25-2008

"Richard Tobin" <(E-Mail Removed)> wrote in message
news:gdsk17$2hbq$(E-Mail Removed)...
> In article <490139f9$0$17067$(E-Mail Removed)>,
> Dimitre Novatchev <(E-Mail Removed)> wrote:
>
>>Actually, this can be achieved with a single XPath one-liner (even without
>>XSLT being involved).
>>
>>Use:
>>
>> //node[@id = $id]/ancestor-or-self::*[@attr][1]/@attr

>
> Or, if you find it clearer not to repeat @attr:
>
> (//node[@id = $id]/ancestor-or-self::*/@attr)[last()]
>


This may be "clearer" but risks to be less efficient.

Using [1] in a reverse axis is a strong optimization hint and a clever XPath
engine will not traverse the whole way up -- it wil just stop on the first
self-or-ancestor element found that has an "attr" attribute.

Cheers,
Dimitre Novatchev


 
Reply With Quote
 
Richard Tobin
Guest
Posts: n/a
 
      10-25-2008
In article <490386ab$0$17066$(E-Mail Removed)>,
Dimitre Novatchev <(E-Mail Removed)> wrote:

>> (//node[@id = $id]/ancestor-or-self::*/@attr)[last()]


>This may be "clearer" but risks to be less efficient.
>
>Using [1] in a reverse axis is a strong optimization hint and a clever XPath
>engine will not traverse the whole way up -- it wil just stop on the first
>self-or-ancestor element found that has an "attr" attribute.


True, but unlikely to be significant when the axis is ancestor-or-self,
because XML documents tend to be much shallower than they are wide.
For preceding-sibling it would be much more likely to make a difference.

-- Richard
--
Please remember to mention me / in tapes you leave behind.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
obtain element name, or attribute and value of the document name itself, and some elemnts and attributes from an ancestor or the node itself using xquery Jeff Kish XML 4 10-30-2008 05:47 PM
Proposal: reducing self.x=x; self.y=y; self.z=z boilerplate code Ralf W. Grosse-Kunstleve Python 16 07-11-2005 09:28 PM
__autoinit__ (Was: Proposal: reducing self.x=x; self.y=y;self.z=z boilerplate code) Ralf W. Grosse-Kunstleve Python 18 07-11-2005 04:01 PM
How to output the all the ancestor and their attribute of an element ai2003lian@yahoo.com XML 2 02-03-2005 06:03 PM
XML Schema keys, uniqueness based on ancestor's attribute Ognen Ivanovski XML 0 07-15-2003 02:36 PM



Advertisments