[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: Jakob.Fix@xxxxxxxxxxxxxxxxx
Date: Thu, 5 Dec 2002 17:30:54 +0100
jakob fix

Jeni, David,

Thanks for your responses.  Thanks for pointing out the error in my logic.

I am currently using the catch-all expressions, which works ok,

  (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
  (descendant::* | following::*)
    [self::PART or self::CHAP or self::SECT or self::ART or
     self::SYMBOLS or self::APPENDIX or self::SART][@ID][1]

However, as you indicated, this slows down the processing enormously:
normally, to fragment my 15 MB file into about 1800 fragments, it takes
about 8 minutes.  Currently, I am at 1040 fragments processed in 90 minutes
... another 800 to go ...
An occasion to optimize ...

I will also look into the function extension to modularize the stylesheet.

Again, thanks for your quick replies!

Jakob.







Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>@lists.mulberrytech.com on 12/05/2002
01:26:52 PM

Veuillez répondre à xsl-list@xxxxxxxxxxxxxxxxxxxxxx

Envoyé par :   owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx


Pour :    Jakob Fix/HO/VERITAS@VERITAS
cc :  xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Objet :   Re:  sequential navigation problem (long)

Ref. Message:

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







 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.