Re: [xsl] XPath problem with getting all ancestors

Subject: Re: [xsl] XPath problem with getting all ancestors
From: Jostein Austvik Jacobsen <josteinaj@xxxxxxxxx>
Date: Fri, 23 Oct 2009 14:12:42 +0200
Ah, I guess <xsl:copy-of select="content/node()"/> is the "problem"
that makes para my new root then?

So how would I modify my note template to do what I want?


-Jostein

2009/10/23 Vyacheslav Sedov <vyacheslav.sedov@xxxxxxxxx>:
> it is ok - you copy whole node - not reference so this stats refer to
> new constructed node
>
> On Fri, Oct 23, 2009 at 4:03 PM, Jostein Austvik Jacobsen
> <josteinaj@xxxxxxxxx> wrote:
>> Ok, I've stripped it down a fair bit. When I run this:
>>
>>
>> <?xml version="1.0" encoding="utf-8"?>
>> <document>
>>       <article>
>>               <meta>
>>                       <title>Title</title>
>>               </meta>
>>               <content>
>>                       <para>
>>                               <note id="1">text</note>
>>                       </para>
>>               </content>
>>       </article>
>> </document>
>>
>>
>> through this:
>>
>>
>> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>> version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema";
>> xmlns:mf="http://example.com/2009/mf"; exclude-result-prefixes="xs mf">
>>
>>        <xsl:template match="document">
>>                <document>
>>                        <meta/>
>>                        <content>
>>                                <xsl:for-each select="article">
>>                                        <xsl:sort select="(.//@page)[1]"/>
>>                                        <xsl:apply-templates
select="article"/>
>>                                </xsl:for-each>
>>                                <xsl:apply-templates/>
>>                        </content>
>>                </document>
>>        </xsl:template>
>>
>>        <xsl:template match="article">
>>                <xsl:variable name="v1">
>>                        <xsl:copy-of select="content/node()"/>
>>                </xsl:variable>
>>                <xsl:sequence select="mf:group($v1/node())"/>
>>        </xsl:template>
>>        <xsl:function name="mf:group" as="node()*">
>>                <xsl:param name="nodes" as="node()*"/>
>>                <xsl:for-each-group select="$nodes"
group-starting-with="foo">
>>                        <xsl:apply-templates/>
>>                </xsl:for-each-group>
>>        </xsl:function>
>>
>>        <xsl:template match="note">
>>                The note at /article/content/para/note reads:
>>                ancestors="<xsl:value-of select="count(ancestor::*)"/>"
>>                preceding="<xsl:value-of select="count(preceding::*)"/>"
>>                contentNum="<xsl:value-of
select="count(preceding::content)"/>"
>>                numberTest="<xsl:number level="any" count="content"/>"
>>        </xsl:template>
>>
>> </xsl:stylesheet>
>>
>>
>> I get this:
>>
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <document>
>>        <meta/>
>>        <content>
>>                The note at /article/content/para/note reads:
>>                ancestors="1"
>>                preceding="0"
>>                contentNum="0"
>>                numberTest=""
>>        </content>
>> </document>
>>
>>
>> In this case I would expect:
>> ancestors="3" (para,content,article)
>> preceding="2" (meta,title)
>>
>> But I guess I'm applying the template in a wrong way?
>>
>> Regards
>> Jostein
>>
>> 2009/10/23 Jostein Austvik Jacobsen <josteinaj@xxxxxxxxx>:
>>> David/Syd: I tried replacing the value-of with <xsl:number level="any"
>>> count="content"/>, but it returned nothing. I'm sure I'm using it
>>> wrong though so I'll have myself a read on xsl:number.
>>> Syd: Sorry about the misplaced match. I tried it myself now and
>>> actually got the same as you.
>>> Syd/Michael: I'll try to strip down my stylesheet to localize the
>>> problem further, then I'll post it back here.
>>>
>>> Thanks
>>> Jostein
>>>
>>> 2009/10/23 Michael Kay <mike@xxxxxxxxxxxx>:
>>>>
>>>> My guess (and it's a completely wild one) is that you aren't applying
>>>> templates to the note element in the source tree as you have shown it,
but
>>>> to a copy of the note element in some smaller tree, probably a tree
rooted
>>>> at the para element.
>>>>
>>>> To confirm that we would need to see more of the stylesheet. Or, within
the
>>>> match="note" template, do
>>>>
>>>> <xsl:message><xsl:copy-of select="/"/></xsl:message>
>>>>
>>>> to see what tree you are processing at the time.
>>>>
>>>> Regards,
>>>>
>>>> Michael Kay
>>>> http://www.saxonica.com/
>>>> http://twitter.com/michaelhkay
>>>>
>>>>> -----Original Message-----
>>>>> From: Jostein Austvik Jacobsen [mailto:josteinaj@xxxxxxxxx]
>>>>> Sent: 23 October 2009 11:27
>>>>> To: xsl-list
>>>>> Subject: [xsl] XPath problem with getting all ancestors
>>>>>
>>>>> I've got a document like this:
>>>>>
>>>>> <?xml version="1.0" encoding="utf-8"?>
>>>>> <document>
>>>>>       <article>
>>>>>               <meta>
>>>>>                       <title>Title</title>
>>>>>               </meta>
>>>>>               <content>
>>>>>                       <headline>Headline</headline>
>>>>>                       <para>
>>>>>                               <note id="1">text</note>
>>>>>                       </para>
>>>>>               </content>
>>>>>       </article>
>>>>> </document>
>>>>>
>>>>> And in a template for the note tags I'm trying to use the
>>>>> ancestor axis to get the list [ para , content , article ].
>>>>> However, I only seem to get [ para ] with ancestor::* and [ para , ""
>>>>> ] with ancestor::node().
>>>>> When I test it like this:
>>>>>
>>>>> <xsl:template match="note">
>>>>>               ancestors="<xsl:value-of select="count(ancestor::*)"/>"
>>>>>               preceding="<xsl:value-of select="count(preceding::*)"/>"
>>>>>               contentNum="<xsl:value-of
>>>>> select="count(preceding::content)"/>"
>>>>> </xsl:template match>
>>>>>
>>>>> ...I get ancestors="1", preceding="2" and contentNum="0" as output.
>>>>>
>>>>> What I actually need to do is to count the number of content
>>>>> nodes preceding the current note (relevant for the input XML
>>>>> note numbering scheme). I did so earlier in the document (for
>>>>> referencing the actual
>>>>> notes) when matching document like this:
>>>>>
>>>>> <xsl:template match="document">
>>>>>       (...)
>>>>>       <xsl:for-each select="//note">
>>>>>               <note>
>>>>>                       <xsl:attribute name="id"><xsl:value-of
>>>>> select="count(ancestor::content/preceding::content)"/></xsl:attribute>
>>>>>                       <p><xsl:apply-templates/></p>
>>>>>               </note>
>>>>>       </xsl:for-each>
>>>>>       (...)
>>>>> </xsl:template>
>>>>>
>>>>> So here I get access to all of the notes ancestors. In
>>>>> retrospect I could probably have used
>>>>> select="count(preceding::content)" instead, but still...
>>>>>
>>>>> How come that I cannot access the notes ancestors from my
>>>>> note template?
>>>>>
>>>>> Regards
>>>>> Jostein

Current Thread