[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: sequential navigation problem (long)

Subject: Re: sequential navigation problem (long)
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Thu, 5 Dec 2002 12:26:52 +0000
sequential navigation example
Hi Jakob,

> In addition to the parent/next/prev sibling navigation, I want to add
> sequential (in the book, page flicker sense) navigation as well, so that it
> becomes possible to navigate the complete document only using "Next
> fragment" or "Previous fragment" buttons.  So, basically every fragment
> must know the ID of the sequentially preceding and following fragment.
>
> For this I have defined the following algorithms:
>
> for previous fragment:
> 1) test:      node's left sibling has a last child with a known GI and an
> ID
>               attr
> 2) else test: node has a left sibling with a known GI and an ID attr
> 3) else test: node has a parent with a known GI and an ID attr
>
> for next fragment:
> 1) test:      node has a first child with a known GI and an ID attr
> 2) else test: node has sibling with a known GI and an ID attr
> 3) else test: node's parent has a sibling with a known GI and an ID attr

These tests miss out situations where, for example, you want the next
fragment from a fragment whose parent doesn't have a following
sibling but whose grandparent (or other ancestor) does.

Rather than going through these separate tests, you might find it
better to use the ancestor/descendant and preceding/following axes.
For the previous fragment, you could use:

  (ancestor::* | preceding::*)
    [self::PART or self::CHAP or self::SECT or self::ART or
     self::SYMBOLS or self::APPENDIX or self::SART][@ID][last()]

and for the next fragment, you could similarly use:

  (descendant::* | following::*)
    [self::PART or self::CHAP or self::SECT or self::ART or
     self::SYMBOLS or self::APPENDIX or self::SART][@ID][1]

Using preceding and following will probably have an impact on the
speed of the transformation, but you said you don't care too much
about that -- try it and see.

> where a "known GI" is one in this list (this is to avoid fragmenting
> items such as notes and subsections which won't have their own
> fragment, but have an ID nevertheless): "PART, CHAP, SECT, ART,
> SYMBOLS, APPENDIX, SART"
>
> I have defined two named templates "tpl.next.fragment" and
> "tpl.prev.fragment" which are called from the template responsible for
> fragmenting, and are supposed to "return" the ID.  Thus, the current node
> is available in these templates.  Please note, these templates are not yet
> tested.
>
> My problem now is that I am not sure how to efficiently and
> concisely write the XPath test expression of what is defined in the
> algorithms. The following shows my approach, not tested.

Your approach won't work, unfortunately, because you're holding the
list of known GIs in a *string* and then trying to evaluate that
string as part of an XPath expression. Actually, even if that did
work, the expression that it would create wouldn't be a legal one...

The easiest way to make your list of known.gis extensible with XSLT
1.0 is to store it in an entity:

<!DOCTYPE xsl:stylesheet [
<!ENTITY known.gis
         'self::PART or self::CHAP or self::SECT or self::ART or
          self::SYMBOLS or self::APPENDIX or self::SART'>
]>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
...
<xsl:template name="tpl.next.fragment">
  <xsl:choose>
    <!-- does this node have  a FIRST CHILD
         with an ID value and one of the GIs above? -->

    <xsl:when test="child::*[&known.gis;][@ID][1]">

    </xsl:when>

    <!-- does this node have a FOLLOWING SIBLING
         with an ID value and one of the GIs above? -->
    <xsl:when test="following-sibling::*[&known.gis;][@ID][1]">

    </xsl:when>

    <!-- does this node's PARENT DOES HAVE A NEXT SIBLING
         with an ID value and one of the GIs above? -->
    <xsl:when test="../following-sibling::*[&known.gis;][@ID]">

    </xsl:when>

    <!-- not interested -->
    <xsl:otherwise/>
  </xsl:choose>
</xsl:template>
...
</xsl:stylesheet>

If you're using a processor that supports func:function from EXSLT
(e.g. Saxon or Xalan) and you're happy to use it, then I'd recommend
writing a function that tests whether a given node is one of your
known GIs or not, and then calling that function, as follows:

<func:function name="my:is-known-GI">
  <xsl:param name="n" />
  <func:result
    select="$n/self::PART or $n/self::CHAP or $n/self::SECT or
            $n/self::ART or $n/self::SYMBOLS or $n/self::APPENDIX or
            $n/self::SART" />
</func:function>

<xsl:template name="tpl.next.fragment">
  <xsl:choose>
    <!-- does this node have  a FIRST CHILD
         with an ID value and one of the GIs above? -->

    <xsl:when test="child::*[my:is-known-GI(.)][@ID][1]">

    </xsl:when>

    <!-- does this node have a FOLLOWING SIBLING
         with an ID value and one of the GIs above? -->
    <xsl:when test="following-sibling::*[my:is-known-GI(.)][@ID][1]">

    </xsl:when>

    <!-- does this node's PARENT DOES HAVE A NEXT SIBLING
         with an ID value and one of the GIs above? -->
    <xsl:when test="../following-sibling::*[my:is-known-GI(.)][@ID]">

    </xsl:when>

    <!-- not interested -->
    <xsl:otherwise/>
  </xsl:choose>
</xsl:template>

I hope that gives you some ideas.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.