xsl-list
[Top] [All Lists]

Re: Sorting problem

2005-08-31 04:51:49
On 8/31/05, Joe Fawcett <joefawcett(_at_)hotmail(_dot_)com> wrote:
David and Dimitre

Thanks for your advice, I still am missing something about keys though. The
document I showed was obtained midway through a transform by building an RTF
and applying xx:node-set. How then can I define a key based on @type?

Exactly as shown in my solution -- an  xsl:key defines the
relationship node --> key-value regardless of the document in which
the node is present.

The key() function obtains all the nodes with the specified key-value
in the *current document*.

In my code this line:

            <xsl:for-each select="$vDoc">

serves the sole purpose of setting the right current document, so that
the key() function will return its matching nodes.


Cheers,
Dimitre Novatchev
  


Joe


From: Dimitre Novatchev <dnovatchev(_at_)gmail(_dot_)com>
Reply-To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] Sorting problem
Date: Wed, 31 Aug 2005 21:36:44 +1000

On 8/31/05, Joe Fawcett <joefawcett(_at_)hotmail(_dot_)com> wrote:
Dear All

Supposing I have a document such as below =>
<root>
 <item type="A" subType="1"/>
 <item type="A" subType="2"/>
 <item type="A" subType="4"/>
 <item type="B" subType="2"/>
 <item type="B" subType="3"/>
 <item type="D" subType="1"/>
 <item type="D" subType="2"/>
 <item type="D" subType="3"/>
 <item type="D" subType="4"/>
 <item type="E" subType="2"/>
 <item type="E" subType="4"/>
</root>

This is sorted by @type and then @subType, the subType can be any
positive
number, not just an integer.

I need to select the first occurrence of each item, based on its
@subType,
then the second, then the third etc, keeping them in alphabetical order
based on @type =>

<root>
 <item type="A" subType="1"/>
 <item type="B" subType="2"/>
 <item type="D" subType="1"/>
 <item type="E" subType="2"/>
 <item type="A" subType="2"/>
 <item type="B" subType="3"/>
 <item type="D" subType="2"/>
 <item type="E" subType="4"/>
 <item type="A" subType="4"/>
 <item type="D" subType="3"/>
 <item type="D" subType="4"/>
</root>

This is the result of converting a RTF via xx:node-set, I am stuck with
version 1.0, so as far as I understand I cannot use keys in the
solution.


I have produced a working solution but it seems inelegant. I first
select a
distinct list of @type using pre-Muenchian methods where the type
doesn't
have a preceding-sibling of the same value. I then call a template by
name
recursively whereby the first pass iterates through the distinct list
using
for-each and selects the the first <item> that matches the type. This
template is then called again and does the same for the second matching
item
and continues in the same fashion. The recursion stops after being
called
sufficient times to ensure each item is matched once.

Can anyone suggest anything more appealing?


This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl"
 >
      <xsl:output omit-xml-declaration="yes" indent="yes"/>

      <xsl:key name="kTypes" match="@type" use="."/>
      <xsl:key name="kItemByType" match="item" use="@type"/>

      <xsl:variable name="vDoc" select="/"/>

      <xsl:variable name="vrtfdistTypes">
        <xsl:for-each select=
          "/*/item/@type
              [generate-id()
              =
               generate-id(key('kTypes', .)[1])
               ]">
           <type code="{.}" count="{count(key('kTypes', .))}"/>
    </xsl:for-each>
      </xsl:variable>

      <xsl:variable name="vdistTypes"
select="msxsl:node-set($vrtfdistTypes)/*"/>

      <xsl:variable name="vmaxCount"
       select="number($vdistTypes[not(@count <
$vdistTypes/@count)]/@count)"/>

      <xsl:variable name="vmaxCountTypecode"
       select="$vdistTypes[not(@count < $vdistTypes/@count)]/@code[1]"/>

      <xsl:template match="/">
       <items>
        <xsl:for-each select="key('kItemByType', $vmaxCountTypecode)">
          <xsl:variable name="vcurTuple" select="position()"/>
          <xsl:for-each select="$vdistTypes">
            <xsl:variable name="vthisType" select="."/>
            <xsl:for-each select="$vDoc">
              <xsl:copy-of select=
                 "key('kItemByType', $vthisType/@code)[$vcurTuple]"/>
            </xsl:for-each>
          </xsl:for-each>
        </xsl:for-each>
       </items>
      </xsl:template>

</xsl:stylesheet>

when applied on this source xml:

<root>
      <item type="A" subType="1"/>
      <item type="A" subType="2"/>
      <item type="A" subType="4"/>
      <item type="B" subType="2"/>
      <item type="B" subType="3"/>
      <item type="D" subType="1"/>
      <item type="D" subType="2"/>
      <item type="D" subType="3"/>
      <item type="D" subType="4"/>
      <item type="E" subType="2"/>
      <item type="E" subType="4"/>
</root>

produces the wanted result:

<items>
  <item type="A" subType="1" />
  <item type="B" subType="2" />
  <item type="D" subType="1" />
  <item type="E" subType="2" />
  <item type="A" subType="2" />
  <item type="B" subType="3" />
  <item type="D" subType="2" />
  <item type="E" subType="4" />
  <item type="A" subType="4" />
  <item type="D" subType="3" />
  <item type="D" subType="4" />
</items>


Cheers,
Dimitre Novatchev.

--~------------------------------------------------------------------
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>
--~--




--~------------------------------------------------------------------
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>
--~--




-- 
Cheers,
Dimitre Novatchev
---------------------------------------
Harry did not ask how Dumbledore knew; ...but Harry had long since
learned that bangs and smoke were more often the marks of ineptitude
than expertise.

--~------------------------------------------------------------------
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>