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

Re: complex positioning problem

Subject: Re: complex positioning problem
From: Geert Josten <Geert.Josten@xxxxxxxxxxx>
Date: Wed, 03 Nov 2004 08:58:48 +0100
xslt positioning
Hi Bruce,

Wendell noted correctly that your input document doesn't cover all situations. Even more, I think it is just not complex enough for the general problem of numbering citations.

I'm afraid it's going to have to be.

Because more difficult examples are too complex to handle?


BTW, I'm using XSLT 2.0 (I should have stated that again), and my strategy has been to create a temporary tree with enhanced data that I use for subsequent processing.

Current code is here:

http://www.users.muohio.edu/darcusb/files/xbiblio.tar.gz

Ah, great, I will take a look at this, when I have some spare time... :-P


There are two ways to order numbered citations. One is based on occurrence within the document (e.g. the biblioref elements), and the other is to sort the bibliography as you would in an author-year style, number those, and then use them in the citation. This is an absolutely silly style that results in markers like [34, 2] and [1, 23], but it should be that hard I guess because I already the author-year style working fine.

It looks silly indeed, that is why I suggested to present [2,1] as [1,2] in the first place.. :)


It is probably not the most efficient code, but it works.

This is what I wondered about; particularly whether there are some new functions in XSLT 2.0 that would get me the functionality I need, as well as decent performance.

Because of general lack of support for XSLT 2, I really tend to stick to XSLT 1. If this can be solved in XSLT 1, then it shouldn't be a problem in XSLT 2. And getting it work in XSLT 1 is a bigger issue than performance I guess.. ;-)


Note also that I didn't solve the ordering of the bibliorefs within one citation. That can be done, by gathering the positions in a variable again and doing the sorting magic as you like.

XSLT 2.0 grouping can handle that.

Yup, I guess. XSLT 1 sorting might get you far enough as well.


Anyway, let me see if I understand what you've done conceptually....

  <xsl:key name="bibrefs" match="d:biblioref" use="'all'" />
  <xsl:key name="bibrefs" match="d:biblioref" use="@linkend" />
  <xsl:key name="biblio" match="d:mods" use="@ID" />

OK, use keys to index the biblioref elements. I don't really have experience with using keys, so wasn't sure if I needed them, or how to use them here. One thing to note is that the biblioref elements can be all over the document: at various levels of section depth, or in footnotes, for example.

the key match works as template match. Because no parent path is specified (e.g. something like /d:biblioref or table/d:biblioref), this matches bibrefs anywhere. Note that keys are evaluated in a pass _before_ the first template is fired.


I use it simply because of performance. An xsl:variable containing //d:biblioref would do as well, but is not as efficient, especially when looking for a bibref with a specific linkend.

<xsl:variable name="unique-bibrefs">
<xsl:for-each select="key('bibrefs', 'all')">
<xsl:if test="generate-id(.) = generate-id(key('bibrefs', @linkend)[1])">

What is the above doing?

Oh sorry, I nicked this from Jeni T. The loop goes over all bibrefs and seeks those that are first of all with the same linkend. key('bibrefs', @linkend) results the list of all bibrefs with linkend value equal to @linkend of the specific bibref from the outer loop. The predicate [1] makes sure that the first in document order is selected. This one is copied. The others are skipped.


If you run the script on the data.xml you sent, you will see that two xml elements are added to the root level (not well-formed xml, but it is just for debugging). The first shows the contents of the bibrefs index. The second shows the contents of the unique-bibrefs variable.

  <xsl:template match="/">
    <bibrefs>
      <xsl:for-each select="key('bibrefs', 'all')">
        <xsl:copy-of select="." />
      </xsl:for-each>

The above three lines could have been: <xsl:copy-of select="key('bibrefs', 'all')" />

:-P

    </bibrefs>
    <unique-bibrefs>
      <xsl:copy-of select="$unique-bibrefs" />
    </unique-bibrefs>
    <xsl:apply-templates select="node()"/>
  </xsl:template>

And the above?

This is the code that produces the debugging info I meant.


  <xsl:template match="d:biblioref" mode="get-bibref-position">
    <xsl:variable name="linkend" select="@linkend" />
    <xsl:for-each select="msxsl:node-set($unique-bibrefs)/*">
      <xsl:if test="@linkend = $linkend">
        <xsl:value-of select="position()" />
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

I'm not quite following this either.

And this is the most tricky part.


The template is entered with one of the bibrefs in the document and you want to find the bibref with the same linkend that is the first in document order. Once found, you want to determine the 'count' or 'position' of that first bibref.

The for-each loops over the unique (or distinct if you like) bibrefs, this contains the first bibrefs in document order. (XSLT 1 requires the use of the node-set function, but ignore that.) By simply comparing the linkend, the match between the current bibref en the first in document order is found. Because we are in a loop over the distinct bibrefs, simply requesting the position when the match is found, gives the count of the first bibref with that linkend in the document.

Hope this is somewhat clearer. If not, just run the script (with XSLT 1 preferably?) and make it print out some extra values here and there. I wrote the stylesheet in such a way, that it simply outputs the original, but with those two debugging elements in front and with citations replaced by a representation.

Greets,
Geert

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.