Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: [xsl] complex positioning problem

From: Geert Josten <Geert.Josten@----------->
To:
Date: 11/3/2004 7:59:00 AM
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


transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent