Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Suppressing value within a XSL filter (<xsl:for-each>)

Status
Not open for further replies.

SilverStray

Programmer
Oct 25, 2001
47
AU
Hi,
Here's my problem with my XSL:

Based on a certain filter condition using xsl:for-each, I want to display an element value only on the first occurrence of that particular element, and all the succeeding similar values will be suppressed.

Here's how my XML data looks like:


<step>
<name>StepA1</name>
<oper>Oper100</oper>
<show>N</show>
<seq>10</seq>
</step>
<step>
<name>StepB1</name>
<oper>Oper200</oper>
<show>N</show>
<seq>10</seq>
</step>
<step>
<name>StepB3</name>
<oper>Oper200</oper>
<show>Y</show>
<seq>30</seq>
</step>
<step>
<name>StepB2</name>
<oper>Oper200</oper>
<show>Y</show>
<seq>20</seq>
</step>
<step>
<name>StepC1</name>
<oper>Oper300</oper>
<show>Y</show>
<seq>10</seq>
</step>
<step>
<name>StepC2</name>
<oper>Oper300</oper>
<show>Y</show>
<seq>20</seq>
</step>
<step>
<name>StepC3</name>
<oper>Oper300</oper>
<show>Y</show>
<seq>30</seq>
</step>

What I wanted to do is to display only those with show='Y' and display the oper once only for every type, such as:

Oper200
StepB2
StepB3

Oper300
StepC1
StepC2
StepC3

My XSL code looks like this:

<xsl:key name="operkey" match="step" use="oper"/>

<xsl:for-each select="step[show='Y']">
<xsl:sort data-type="number" select="seq" order="ascending" />
<xsl:if test="count(.|key('operkey',oper)[1])=1">
<xsl:value-of select="oper" />
</xsl:if>
</xsl:sort>
</xsl:for-each>

I was hoping that this will filter the data first into those with show='Y',and then count the oper, such that if it's 1 it will display the oper value.But what happens is that in Oper200, it counts including the one with show value of 'N', which resulted in the erroneous data display such as the ff:


StepB2
StepB3

Oper300
StepC1
StepC2
StepC3

It did not display the Oper200 because because it still considered the first element for Oper200 with show='N', when I thought it would no longer be considered since I have filtered it first.

Please help me how to get on with this.


Thanks in advance!
 
You could also filter the node-set that builds your key:
Code:
<xsl:key name="operkey" match="step[show='Y']" use="oper" />
...
<xsl:for-each select="//step[show='Y']">
  <xsl:sort data-type="number" select="seq" order="ascending" />
  <xsl:if test="count(.|key('operkey',oper)[1])=1">
    <xsl:value-of select="oper" />
  </xsl:if>
</xsl:for-each>
I don't know if the sorting will be as you expected: this way you find the first <step> in the original nodeset for every <oper> based on the position the step has before sorting. The steps you found are sorted after that.
 
Thanks jel. It did sort, but something went wrong with the if-test value, cause it printed the oper value for each record now, when it's supposed to be printed just once.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top