xsl-list
[Top] [All Lists]

Re: [xsl] XPath problem with getting all ancestors

2009-10-23 09:16:21
Hi,

Although you can keep the mf: group function if you need it elsewhere, as Martin pointed out, you do not need $v1 which creates a subtree so this should work

<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:apply-templates select="article">
                   <xsl:sort select="(.//@page)[1]"/>
               </xsl:apply-templates>
               <xsl:apply-templates select="*[not(self::article)]"/>
           </content>
       </document>
   </xsl:template>

   <xsl:template match="article">
<xsl:for-each-group select="content/node()" group-starting-with="foo">
           <xsl:apply-templates/>
       </xsl:for-each-group>
   </xsl:template>

   <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>


and return:
The note at /article/content/para/note reads: ancestors="4" preceding="2" contentNum="0" numberTest="1"


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(_at_)gmail(_dot_)com>:
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(_at_)saxonica(_dot_)com>:
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(_at_)gmail(_dot_)com]
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

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--