[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] Muench method for two or three keys? (Sorting and Grouping)


Subject: [xsl] Muench method for two or three keys? (Sorting and Grouping)
From: Daniel O'Donnell <daniel.odonnell@xxxxxxxx>
Date: Sat, 15 Jan 2005 21:00:33 -0700

Hi
I have a question I don't think is a FAQ. In fact I've been finding it difficult to explain the problem in compact form, so please forgive any infelicities.
What I am interested in is sorting and grouping input on two or three keys. I am building an xml document containing the index for print book. The index was written in a 4-field spreadsheet. The following shows some of the allowable permutations:


head-a, subfield1-a, subfield2-a, locater1
head-a, subfield1-b, subfield2-g, locater2
head-a, subfield1-b, subfield2-h, locater3
head-b, subfield1-x, ---, locater4
head-c, ---, ---, ---

What I want to produce is a hierarchical list of the following type:


<list> <item>head-a <list> <item>subfield1-a <list> <item>subfield2-a, <seg type="locater">locater1</item> </list> </item> <item>subfield1-b <list> <item>subfield2-g, <seg type="locater">locater2</item></item> <item>subfield2-h, <seg type="locater">locater3</item></item> </list> </item> </list> </item> <item>head-b <list> <item>subfield1-x, <seg type="locater">locater4</item></item> </list> </item> <item>head-c </item> </list>

(i.e. if two subfield2's have parents with identical content I want them to be grouped under one iteration of the parent content; likewise if two subfield1's have parents with identical content)

As an intermediate form between the spreadsheet and the final list format, I've been putting the records in the following format (I don't mind changing this if there is something more convenient):

<index>
  <record>
    <head>head-a</head>
    <subfield1>subfield1-a</subfield1>
    <subfield2>subfield2-a</subfield2>
    <locater>locater1</locater>
  </record>
...
</index>

So what I need is a sheet that does the following:
a) sorts records by head
b) groups records so that if two subfield1's are children of heads with the same content they are put in the same record
c) repeats the same for subfield2's


I can find a couple of different ways of sorting and grouping for one key (i.e. making sure that subfields whose parents have identical contents are listed under one <head>). What I am finding it difficult to do is then group subfield1s so that subfield2s whose parents have identical content are also listed under one <subfield1>. In otherwords, I can get the following (where *** marks the points where what i am getting differs from the ideal):

<list>
  <item>head-a
    <list>
      <item>subfield1-a
        <list>
          <item>subfield2-a, <seg type="locater">locater1</item></item>
        </list>
      </item>
*** </list>
*** <list>
      <item>subfield1-b
        <list>
          <item>subfield2-g, <seg type="locater">locater2</item></item>
***     </list>
***   </item>
*** <list>
***   <item>subfield1-b
***     <list>
          <item>subfield2-h, <seg type="locater">locater3</item></item>
        </list>
      </item>
    </list>
  </item>
  <item>head-b
    <list>
      <item>subfield1-x, <seg type="locater">locater4</item></item>
    </list>
  </item>
  <item>head-c
  </item>
</list>



Does anybody have a solution for this?



For those of you who are interested in what I have been doing, I've been using the "Muench Method" (see Tidwell, XSLT [2001], pp. 144-147). The problem I keep coming up with is how to open a <list> element for the children of <head> that allows multiple children.

<xsl:key name="headkey" match="record" use="head"/>

<xsl:template match="index">
<index>
<xsl:for-each select="record[generate-id(.)=generate-id(key('headkey', head)[1])]">
<item>
<xsl:for-each select="key('headkey', head)">
<xsl:if test="position()=1">
<xsl:value-of select="head"/>
</xsl:if>
<xsl:if test="subfield1[string-length()!=0]">
<list>
<item>
<xsl:value-of select="subfield1"/>
<xsl:if test="subfield2[string-length()!=0]">
<list>
<item>
<xsl:value-of select="subfield2"/>
<xsl:if test="locater[string-length()!=0]">
<xsl:text>, </xsl:text>
<seg type="locater">
<xsl:value-of select="locater"/>
</seg>
</xsl:if>
</item>
</list>
</xsl:if>
<xsl:if test="subfield2[string-length()=0]">
<xsl:if test="locater[string-length()!=0]">
<xsl:text>, </xsl:text>
<seg type="locater">
<xsl:value-of select="locater"/>
</seg>
</xsl:if>
</xsl:if>
</item>
</list>
</xsl:if>
</xsl:for-each>
<xsl:if test="subfield1[string-length()=0]">
<xsl:if test="locater[string-length()!=0]">
<xsl:text>, </xsl:text>
<seg type="locater">
<xsl:value-of select="locater"/>
</seg>
</xsl:if>
</xsl:if>
</item>
</xsl:for-each>
</index>
</xsl:template>




--
Daniel Paul O'Donnell, PhD
Associate Professor of English
University of Lethbridge
Lethbridge AB T1K 3M4
Tel. (403) 329-2377
Fax. (403) 382-7191
E-mail <daniel.odonnell@xxxxxxxx>
Home Page <http://people.uleth.ca/~daniel.odonnell/>
The Digital Medievalist Project: <http://www.digitalmedievalist.org/>


Current Thread
Keywords