Re: [xsl] use of xsl:key in cross-referencing

Subject: Re: [xsl] use of xsl:key in cross-referencing
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Sat, 22 Mar 2003 15:30:26 -0500
Xiaocun,

Sorry I've been off the list-- out here in the hills of WV, my phone line is down, and I have to hoof it to my neighbor's to get a net connection.

Anyhow, you are pretty close to your solution:

<xsl:key name="QuestionnaireKey"
 match="row[count(cell)=3]/cell[2]"
 use="."/>

<xsl:key name="QuestionnaireKey"
 match="row[count(cell)=2]/cell[1]"
 use="."/>

Instead of recognizing the different groups by their row number, I decided to use the count of their cells. If I have three cells, I know this is a row like

<row row="17">
  <cell column="1">Questionnaire B</cell>
  <cell column="2">QB</cell>
  <cell column="3">Questionnaire B, empty with no questions</cell>
</row>

and the Questionnaire identifier is the second cell (whose value is 'QB').

If I have only two cells, however, my data is like this

<row row="28">
  <cell column="1">QA</cell>
  <cell column="2">Questionnaire A, Question 2</cell>
</row>

and the identifier is the first cell (value is 'QA').

If this assumption does not hold for your data, you need to adjust the match patterns in the key declarations to whatever does work.

On the data as you provided it, the Questionnaire key retrieves either one of these kinds of identifiers by the correct value ('QA', 'QB' or 'QC').

Then if I have

<xsl:template match="/">
  <xsl:apply-templates
    select="//cell[key('QuestionnaireKey',.) and
                   count(.|key('QuestionnaireKey',.)[1])=1 ]"/>
</xsl:template>

I select

//cell ... all the cells in the document...

[key('QuestionnaireKey',.)
... testing whether this cell's value is among my Questionnaire identifiers (note this introduces a very subtle assumption about these identifiers, namely that they are unique strings) ...


and count(.|key('QuestionnaireKey',.)[1])=1 ]
... making sure if it is an identifier, it's the first one (Muenchian grouping).


I think you can see this is a cleaned-up version of what you almost had....

Cheers,
Wendell

At 06:36 PM 3/20/2003, you wrote:
Hi, Wendell:

Thanks for the idea of define two keys for the two
groups with the same name but different "use" value,
but I was unable to find anything in regard to it at
Jenni's website, xsl-list archive (using keywords "two
key;same name;") or google web/group.  I did some
thinking myself and still don't see how that works.
Following is an example, having rows 10-19 being the
first group (Questionnaire) and 20-29 being the second
group (Question):
<range>
<row row="16">
        <cell column="1">Questionnaire A</cell>
        <cell column="2">QA</cell>
        <cell column="3">Questionnaire A, two
questions</cell>
</row>
<row row="17">
        <cell column="1">Questionnaire B</cell>
        <cell column="2">QB</cell>
        <cell column="3">Questionnaire B, empty with no
questions</cell>
</row>

<row row="27">
        <cell column="1">QA</cell>
        <cell column="2">Questionnaire A, Question 1<cell>
</row>
<row row="28">
        <cell column="1">QA</cell>
        <cell column="2">Questionnaire A, Question 2</cell>
</row>
<row row="29">
        <cell column="1">QC</cell>
        <cell column="2">Questionnaire C, Question 1</cell>
</row>
</range>

In this case, questionnaire QA has two questions, QB
is only referred in the 1st group and QC is only
referred in the 2nd group.  What I need is to be able
to process each of QA/QB/QC.

To define two keys for the two groups with the same
name but different "use":
<xsl:key name="QuestionnaireKey" match=//row[@row &lt;
20]" use="string(cell[@column=2])"/>
<xsl:key name="QuestionnaireKey" match=//row[@row &gt;
20]" use="string(cell[@column=1])"/>

Use Muenchian method to process each just once, for
the 2nd group:
<xsl:apply-templates select="//row[@row &gt; 20 and
@row &lt; 30][count(.|key('QuestionnaireKey',
string(cell[@column=1]))[1]) = 1]"/>
but this will miss questionnaire QC.

I guess to take advantage of the combined key, I need
to do select on all rows, like:
<xsl:apply-templates
select="//row[count(.|key('QuestionnaireKey',
string(cell[@column=1]))[1]) = 1]"/>
Would the above work?  If so, how can I tell if the
row being processed is from group 1 (Questionnaire) or
2 (Question)?

___&&__&_&___&_&__&&&__&_&__&__&&____&&_&___&__&_&&_____&__&__&&_____&_&&_ "Thus I make my own use of the telegraph, without consulting the directors, like the sparrows, which I perceive use it extensively for a perch." -- Thoreau


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread