Print

Print


+1 for Dirk's suggestion to use XSLT 2.0 and for-each-group.

I poked around with XQuery to do this also...my hack isn't going to be as efficient as it should because it pulls the doc into memory twice.  I need to look in to the union functionality for XQuery to improve it, but given this:

<ead xmlns="http://loc.gov/ead">
    <c0x>
        <unittitle>Horse, still life</unittitle>
        <origination>Picasso</origination>
    </c0x>
    <c0x>
        <unittitle>Apple, still life</unittitle>
        <origination>Picasso</origination>
    </c0x>
    <c0x>
        <unittitle>Giraffe, still life</unittitle>
        <origination>Holbein</origination>
    </c0x>
    <c0x>
        <unittitle>Baby, still life</unittitle>
        <origination>Fra Angelico</origination>
    </c0x>
    <c0x>
        <unittitle>Frog, still life</unittitle>
        <origination>Michelangelo</origination>
    </c0x>
    <c0x>
        <unittitle>Elephant, still life</unittitle>
        <origination>Holbein</origination>
    </c0x>
    <c0x>
        <unittitle>Chair, still life</unittitle>
        <origination>Picasso</origination>
    </c0x>
    <c0x>
        <unittitle>Duck, still life</unittitle>
        <origination>Michelangelo</origination>
    </c0x>
</ead>

you can use the following to get somewhat close to what you needed.

xquery version "1.0";

declare namespace m = "http://monarchos.com";
declare namespace ead = "http://loc.gov/ead";

declare function m:orig($name) {
    let $originator := $name
    let $query := 
        for $lmnop in doc('/db/ead/ead.xml')/ead:ead/ead:c0x/ead:origination[text() eq $originator] 
        order by $lmnop/preceding-sibling::ead:unittitle ascending 
        return string($lmnop/preceding-sibling::ead:unittitle)
    return $query
};

<dl xmlns="http://www.w3.org/1999/xhtml"> {

    let $orig := for $lmnop in doc('/db/ead/ead.xml')/ead:ead return distinct-values($lmnop/ead:c0x/ead:origination)
    let $titles := 
        for $name in $orig 
        order by $name ascending 
        return (<dt>{$name}</dt>, <dd>{m:orig($name)}</dd>)
    return $titles

}
</dl>

>>> Dirk van Laanen <[log in to unmask]> 02/08/08 4:03 AM >>>

supposing
<c01><did>
  <unittitle>Duck, still life</unittitle>
  <origination>Michelangelo</origination>
</did></c01>


In XSLT 2.0 you might use


  <xsl:for-each-group select="/ead/archdesc/dsc/c01/did" group-by="origination">
    <xsl:sort select="current-grouping-key()"/> 
    <xsl:text>

</xsl:text>
    <xsl:value-of select="origination" />
    <xsl:for-each-group select="current-group()" group-by=".">
      <xsl:sort select="unittitle"/> 
      <xsl:text>
	</xsl:text>
      <xsl:value-of select="unittitle" />
    </xsl:for-each-group>
  </xsl:for-each-group>
  <xsl:text>

</xsl:text>



Not very hip on me keys, but in XSLT 1.0 you might try Muenchian grouping. 

<xsl:key name="painter" match="did" use="origination" />

<xsl:template match="/">
  <xsl:text>

</xsl:text>
  <xsl:for-each select="/ead/archdesc/dsc/c01/did[generate-id(.) = 
                generate-id(key('painter', origination)[1])]">
    <xsl:sort select="origination"/> 
    <xsl:value-of select="origination" />
    <xsl:for-each select="key('painter', origination)">
      <xsl:sort select="unittitle"/>
      <xsl:text>
	</xsl:text>
      <xsl:value-of select="unittitle" />
    </xsl:for-each>
    <xsl:text>
</xsl:text>
  </xsl:for-each>
  <xsl:text>

</xsl:text>
</xsl:template>



Regards, Dirk