XSL formatting sorting issues

John Mansfield jbmansfield at gmail.com
Mon Feb 28 08:25:12 UTC 2011


Hi Aidan,

I will try to help. First I'll discuss your issue about sorting according to
Reverse elements, then secondly I'll address your "ideal" solution of not
duplicating identical Reverse elements.

1. If you want to have all the Reverse elements in the source sorted as a
single list, rather than a series of sorted lists, one for each Headword,
then I think your problem is that you are doing your sort inside this
for-each loop:

> <xsl:for-each select="Words[Status!='Exclude']">

So you need a template structure that goes directly from the
whole-dictionary level right to the Reverse elements, rather than getting to
them via the Words wrappers. Does that make sense?
Maybe something like:

<xsl:template match="Dictionary">
  <xsl:for-each select="//Reverse">
    <xsl:sort select="."/>
    <p><b><xsl:value-of select="."/></b></p>
    <xsl:value:of select="ancestor::Words/Headword"/>
  </xsl:for-each>
</xsl:template>

PS: another way of sorting in xsl is with an attribute @order-by on the
<for-each element. I don't know what the difference is between the methods,
and it may be arcane.


2. As for de-duplicating the Reverse elements: I don't think XSL is a
particularly good tool for it; it's not a very good framework for comparing
strings... and when you want to extract wordlists from data, you often get
sets of things that are not identical character-by-character, but you would
like to have treated as one.

That said, it might work if you have a condition, simply asking at each
Reverse element, "have I already displayed a Reverse element like this one?"
And if not, then display it, but alongside display not just it's own
Headword sibling, but the Headwords of each Reverse elements with that
value.
  Code could be something like this:

<xsl:template match="Dictionary">
  <xsl:for-each select="//Reverse">
    <xsl:sort select="."/>
    <!-- I'm not sure if you need this variable, but you might need it for
the output bit below-->
    <xsl:variable name="this_word" select="."/>
    <xsl:choose>
      <xsl:when test="$this_word =
ancestor::Words/preceding-sibling::Words//Reverse">
          <!-- no output - we've seen this Reverse before -->
      </xsl:when>
      <xsl:otherwise>
         <!-- output the Reverse element -->
         <p><b><xsl:value-of select="."/></b></p>
         <!-- for each Words element that has this Reverse word in it,
output the Headword -->
         <xsl:for-each
select="ancestor::Words/preceding-sibling::Words[descendent::Reverse =
$this_word]
or ancestor::Words/following-sibling::Words[descendent::Reverse =
$this_word]">
             <xsl:value:of select="Headword"/>
         </xsl:for-each>
      </xsl:otherwise>
  </xsl:for-each>
</xsl:template>

I don't know if that will work, but it seems like it should.

j

On 28 February 2011 15:30, Aidan Wilson <a.wilson at pgrad.unimelb.edu.au>wrote:

> Hi RNLDers (I still prefer "Ronaldos")
>
> Does anyone have fairly good XSL skills and could guide me through a
> particularly nasty dictionary formatting issue?
>
> The problem is that I have a reverse word finder which is built by
> extracting an element from each headword ('Reverse' which was originally put
> in for exactly this purpose). Here's an example of a word's XML (totally
> made up
> example to demonstrate the point):
>
> <Words>
>  <Headword>elevate</Headword>
>  <Category>verb</Category>
>  <Meanings>
>    <Definition>to raise, to lift</Definition>
>    <Reverse>raise</Reverse>
>    <Reverse>lift</Reverse>
>    <Examples>
>      <Example>You need to elevate your blood pressure</Example>
>      <Translation>You need to raise your blood pressure</Translation>
>    </Examples>
>  </Meanings>
> </Words>
>
> The difficulty is that some words will have more than one Reverse element
> (as above). At the moment I can either:
> a) Extract only the first reverse element from each entry, display it next
> to the headword, and all will be in alphabetical order by the Reverse
> element, or
> b) Extract all reverse elements from all headwords, and display each one
> next to its headword, but they will be ordered *within the set of reverse
> elements of that word.
>
> What I mean by that, is that I can get it working so I can produce:
>
> Lift:
>  elevate
>
> Raise:
>  elevate
>
> But the Reverse elements from any other words will be sorted amongst
> themselves, but independently of any other word. So what I get in my English
> to Wagiman section is essentially ordered by the Wagiman word, but each
> word's
> English glosses sorted among themselves.
>
> What I would like is to pair each reverse element with its headword and
> then sort the whole list for the whole dictionary at once.
>
> Ideally, actually, I'd like to group together identical Reverse elements so
> that I could have something like:
>
> Lift:
>  boost
>  elevate
>  heighten
>  raise
>
> Instead of listing them separately.
>
> Here's the relevant section of my xsl stylesheet:
>
> <xsl:for-each select="Words[Status!='Exclude']">
>        <xsl:sort select="Meanings/Reverse"/>
>        <xsl:for-each select="Meanings/Reverse">
>                <p><strong><xsl:value-of select="."/></strong><br/>
>                <xsl:value-of select="../../Headword"/></p>
>        </xsl:for-each>
> </xsl:for-each>
>
> Hopefully this isn't an impossible task. And hopefully someone knows more
> than my week's worth of xsl and can point me in the right direction!
>
> --
> Aidan Wilson
>
> PhD Candidate
> Dept of Linguistics and Applied Linguistics
> The University of Melbourne
>
> +61428 458 969
> a.wilson at pgrad.unimelb.edu.au
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listserv.linguistlist.org/pipermail/resource-network-linguistic-diversity/attachments/20110228/792c91e6/attachment.htm>


More information about the Resource-network-linguistic-diversity mailing list