tags:

views:

18

answers:

1

Hi,

I am attempting to use preceding-sibling to select unique elements from a group.

Using the folliwng xml as an example..

<items>
 <item>
  <options>
   <option>
    <option-data>
     <data-ab>TEST1</date-qualifier>
     <date>20101026</date>
    </option-data>
    <option-data>
     <data-ab>TEST2</date-qualifier>
     <date>20101026</date>
    </option-data>

   </option>
   <option type="2">
    <option-data>
     <data-ab>TEST1</date-qualifier>
     <date>20101026</date>
    </option-data>
   </option>
  </options>
 </item>
 <item>
  <options>
   <option>
    <option-data>
     <data-ab>TEST1</date-qualifier>
     <date>20101026</date>
    </option-data>
   </option>
   <option type="2">
    <option-data>
     <data-ab>TEST1</date-qualifier>
     <date>20101026</date>
    </option-data>
   </option>
  </options>
 </item>
</items>

I want to be able to select unique option-date elements (distinct is by date and data-ab). I only want to select the option-data/date that is uniqueu for each item i.e not by option.I have used combinations of preceding-sibling but as it returns to the parent I can only guarentee the dates will be unique for each option where I need it by item.

Racking my brains over this for hours and cannot come up with an elegant solution.

Regards, Andy

A: 

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kODByVal" match="option-data"
  use="concat(generate-id(ancestor::item[1]), '+', data-ab, '+', date)"/>

  <xsl:template match="item">

  Unique option-data elements for item: <xsl:text/>
  <xsl:value-of select="concat(position(), '&#xA;')"/>

  <xsl:copy-of select=
  "*/*/option-data[generate-id()
                  =
                   generate-id(key('kODByVal',
                               concat(generate-id(current()), '+',
                                      data-ab,
                                      '+',
                                      date)
                               )[1])
                  ]
  "/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document (corrected to achieve well-formedness):

<items>
    <item>
        <options>
            <option>
                <option-data>
                    <data-ab>TEST1</data-ab>
                    <date>20101026</date>
                </option-data>
                <option-data>
                    <data-ab>TEST2</data-ab>
                    <date>20101026</date>
                </option-data>
            </option>
            <option type="2">
                <option-data>
                    <data-ab>TEST1</data-ab>
                    <date>20101026</date>
                </option-data>
            </option>
        </options>
    </item>
    <item>
        <options>
            <option>
                <option-data>
                    <data-ab>TEST1</data-ab>
                    <date>20101026</date>
                </option-data>
            </option>
            <option type="2">
                <option-data>
                    <data-ab>TEST1</data-ab>
                    <date>20101026</date>
                </option-data>
            </option>
        </options>
    </item>
</items>

produces the wanted, correct result:

  Unique option-data elements for item: 1
<option-data><data-ab>TEST1</data-ab><date>20101026</date></option-data>
<option-data><data-ab>TEST2</data-ab><date>20101026</date></option-data>

  Unique option-data elements for item: 2
<option-data><data-ab>TEST1</data-ab><date>20101026</date></option-data>

Do note: The most efficient XSLT 1.0 (Muenchian) grouping method is used on three concatenated keys.

Dimitre Novatchev
+1 good answer. (Distinct option-data elements, not necessarily unique ones, IIUC.)
LarsH
@LarsH: Thanks. I was probably downvoted also, as I am at 0 ... ?
Dimitre Novatchev