Subject: Re: XPath problem with getting all ancestors
From: Vyacheslav Sedov <vyacheslav.sedov@xxxxxxxxx>
Date: Fri, 23 Oct 2009 16:07:04 +0400
|
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: 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
|