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

[xsl] Muenchian method on filtered data set


Subject: [xsl] Muenchian method on filtered data set
From: Joelle Tegwen <tegwe002@xxxxxxx>
Date: Wed, 20 May 2009 09:51:34 -0500

I've just recently figured out how to make the Muenchian method work and I've run into a problem that I figured out a way to hack around. It seems rather inelegant so I'm wondering if there's a better way.

I've got an external reference data source that has all of the people in my department and their associate (truncated for simplicity)
<people>
<staff staff_id="unique_id_here" alpha_key="A">
<name>Fred Anderson</name>
<associate associate_id="1">
</staff>
<staff staff_id="unique_id_here" alpha_key="A">
<name>Jane Anderson</name>
<associate associate_id="2">
</staff>
<staff staff_id="unique_id_here" alpha_key="B">
<name>Sue Bates</name>
<associate associate_id="0">
</staff>
<staff staff_id="unique_id_here" alpha_key="B">
<name>John Boxer</name>
<associate associate_id="0">
</staff>
....
</people>


It's imported into my document and indexed thusly
   <xsl:variable name="staff" select="document($ref_staff)/people"/>
   <xsl:key name="alpha" match="@alpha_key" use="."/>


When I display them in the form I want to separate them out with preference to a certain associate. In this case, lets say associate_id=1.


In the using the "native" xml I've got a template that looks like this:
<xsl:template match="people">
<xsl:variable name="center_staff"
select="$staff/staff[associate/@associate_id = $associate_id]"/>
<xsl:variable name="other_staff"
select="$staff/staff[associate/@associate_id != $associate_id]"/>
<xsl:if test="count($center_staff) > 0">
<fieldset class="span-18 last col-wrap">
<legend class="quiet">
<xsl:value-of select="ancestor::project/associates/associate/title"/>
People</legend>
<xsl:call-template name="layout_3column">
<xsl:with-param name="objects" select="$center_staff"/>
</xsl:call-template>
</fieldset>
</xsl:if>


<xsl:if test="count($other_staff) > 0">
<fieldset class="span-18 last col-wrap">
<legend class="quiet">All other U of M People</legend>
<div id="tabs">
<ul>
<xsl:for-each
select="$other_staff/@alpha_key[generate-id()=generate-id(key('alpha', .))]">
<xsl:call-template name="tab_link">
<xsl:with-param name="alpha_string" select="."/>
</xsl:call-template>
</xsl:for-each>
</ul>
<xsl:for-each
select="$other_staff/@alpha_key[generate-id()=generate-id(key('alpha', .))]">
<xsl:call-template name="tab_data">
<xsl:with-param name="alpha_string" select="."/>
<xsl:with-param name="objects"
select="$other_staff[@alpha_key = current()]"/>
</xsl:call-template>
</xsl:for-each>
</div>
</fieldset>
</xsl:if>
</xsl:template>



The problem that I have is that because Fred Anderson is not in the $other_staff node set, the As don't show up at all because the keys don't match.


I debugged this by running the following two snippets:
<xsl:for-each select="$staff/staff/@alpha_key">
<xsl:value-of select="."/> -
<xsl:value-of select="generate-id(.)"/> -
<xsl:value-of select="generate-id(key('alpha', .))"/>
<br/> </xsl:for-each>
<xsl:for-each select="$other_staff/@alpha_key">
<xsl:value-of select="."/> -
<xsl:value-of select="generate-id(.)"/> -
<xsl:value-of select="generate-id(key('alpha', .))"/>
<br/> </xsl:for-each>



Which generate: $staff/staff/@alpha_key: A - id51618272 - id51618272 A - id51618367 - id51618272 A - id51620641 - id51618272 A - id51620731 - id51618272 A - id51620821 - id51618272

$other_staff/@alpha_key
A - id51618367 - id51618272
A - id51620641 - id51618272
A - id51620731 - id51618272
A - id51620821 - id51618272

None of the keys match for the letter A in the second set because the one that has been keyed is not a member of the set anymore so it's not displayed.

If I change the stylesheet to this it works:
<xsl:template match="people">
<xsl:variable name="center_staff"
select="$staff/staff[associate/@associate_id = $associate_id and associate/@associate_id != 0]"/>
<xsl:variable name="other_staff"
select="$staff/staff[associate/@associate_id != $associate_id or associate/@associate_id = 0]"/>
<xsl:if test="count($center_staff) > 0">
<fieldset class="span-18 last col-wrap">
<legend class="quiet">
<xsl:value-of select="ancestor::project/associates/associate/title"/>
People</legend>
<xsl:call-template name="layout_3column">
<xsl:with-param name="objects" select="$center_staff"/>
</xsl:call-template>
</fieldset>
</xsl:if>
<xsl:if test="count($other_staff) > 0">
<fieldset class="span-18 last col-wrap">
<legend class="quiet">All other U of M People</legend>
<div id="tabs">
<ul>
<xsl:for-each
changed --> select="$staff/staff/@alpha_key[generate-id()=generate-id(key('alpha', .))]">
added --> <xsl:if test="count($other_staff[@alpha_key = current()]) > 0">
<xsl:call-template name="tab_link">
<xsl:with-param name="alpha_string" select="."/>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</ul>
<xsl:for-each
changed --> select="$staff/staff/@alpha_key[generate-id()=generate-id(key('alpha', .))]">
added --> <xsl:if test="count($other_staff[@alpha_key = current()]) > 0">
<xsl:call-template name="tab_data">
<xsl:with-param name="alpha_string" select="."/>
<xsl:with-param name="objects"
select="$other_staff[@alpha_key = current()]"/>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</div>
</fieldset>
</xsl:if>
</xsl:template>




Is there a better way to do this?

Thanks
Joelle


Current Thread
Keywords
xml