xsl-list
[Top] [All Lists]

Re: [xsl] Sorting using more than value

2010-11-11 15:06:41
Susan,

At 03:46 PM 11/11/2010, you wrote:
I am having problems in sorting using one of two possible values.I have a template that creates an index using the indexterm element. Here is a snippet of XML: <p>Here is an <indexterm>index entry</indexterm> without an attribute, and the contents of the element will display in the index. This <indexterm term.entry="Alternate text">index entry</indexterm> does have an attribute, and the contents of the attribute will display in the index rather than the content of the indexterm element. </p> I need to be able to sort the index using one of two possible values. If the indexterm doesn't contain a term.entry attribute, it should sort using the content of the indexterm element. If the indexterm element contains a term.entry attribute, then it should sort using the value of the term.entry attribute. I have the following that sorts the index. The template outputs the value of the term.entry attribute if present, but it sorts only using the content of the indexterm element: <xsl:for-each-group select="//indexterm" group-by="."> <xsl:sort select="translate(text(),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> <div class="index"> <xsl:choose> <xsl:when test="@term.entry"><span><xsl:value-of select="@term.entry"/><xsl:text> - </xsl:text></span></xsl:when> <xsl:otherwise><span><xsl:value-of select="."/><xsl:text> - </xsl:text></span></xsl:otherwise> </xsl:choose> </div> </xsl:for-each-group> How would I be able to sort the index entries using the content of the indexterm element (when there is no term.entry element) or the term.entry attribute for the indexterm element (if present)? Thanks for any assistance with this. Susan

As I understand it, you want your sorting to use the value of the @term.entry instead of the value of the element itself, when the attribute is available.

But I think you actually want to work with the grouping key, not just the sorting key. After all, you don't want the groups to be sorted on something other than the values by which they are grouped, do you?

Something like this:

<xsl:for-each-group select="//indexterm" group-by="(@term.entry,text())[1])">
  <xsl:sort select="current-grouping-key()"/>
    <div class="index">
      <span>
       <xsl:value-of select="current-grouping-key()"/>
       <xsl:text> - </xsl:text>
      </span>
    </div>
  ...

This declares as the grouping key the value of the first node that's available for each selected node from among its @term.entry and its text node children. So, it'll be the @term.entry for those indexterms that have one, the first text node child for those that don't.

Also, I'd probably prefer "(@term.entry,.)[1])" to work around potential issues with mixed content. But maybe you know you'll never have those.

I'll let you wrap the expression in whatever munging functionality you want. But note that XSLT 2.0, which you are using, has an upper-case() function that works better than the old translate() trick.

You can also see the current-grouping-key() function here, saving more conditional logic.

Good luck,
Wendell



======================================================================
Wendell Piez                            
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>