I have an XML record that have repeating unique ID's but would like to combine all similar ID's into 1 record, concat the reference fields and summing up the amount field.
The XML looks like this:
<root>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>0</F03>
<F04>47582736</F04>
<F05>151.12</F05>
</row>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>0</F03>
<F04>47643792</F04>
<F05>191.09</F05>
</row>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>0</F03>
<F04>47643793</F04>
<F05>95.32</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>0</F03>
<F04>36819319</F04>
<F05>138.87</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>0</F03>
<F04>36827362</F04>
<F05>9.98</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>0</F03>
<F04>36834497</F04>
<F05>79.87</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1771929</F04>
<F05>400.07</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1766940</F04>
<F05>111.52</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1810269</F04>
<F05>112.48</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1618234</F04>
<F05>60.76</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1771923</F04>
<F05>2829.19</F05>
</row>
I want to make it look like this:
<root>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>437.53</F03>
<F04>47582736, 47643792, 47643793</F04>
<F05>151.12</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>228.72</F03>
<F04>36819319, 36827362, 36834497</F04>
<F05>138.87</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>3514.02</F03>
<F04>1771929, 1766940, 1810269, 1618234, 1771923</F04>
<F05>400.07</F05>
</row>
I think I may know how to concat F04 but don't know how to sum up F05 and put that value in F03. F01 is the unique ID that should determine what to keep together.
When this XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kRowByF02" match="row" use="F02"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<root>
<xsl:apply-templates
select="row[generate-id() = generate-id(key('kRowByF02', F02)[1])]"/>
</root>
</xsl:template>
<xsl:template match="F03">
<F03>
<xsl:value-of
select="sum(key('kRowByF02', preceding-sibling::F02)/F05)" />
</F03>
</xsl:template>
<xsl:template match="F04">
<F04>
<xsl:apply-templates
select="key('kRowByF02', preceding-sibling::F02)/F04/text()"/>
</F04>
</xsl:template>
<xsl:template match="F04/text()">
<xsl:if test="not(position() = 1)">, </xsl:if>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
...is applied to the provided XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>0</F03>
<F04>47582736</F04>
<F05>151.12</F05>
</row>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>0</F03>
<F04>47643792</F04>
<F05>191.09</F05>
</row>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>0</F03>
<F04>47643793</F04>
<F05>95.32</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>0</F03>
<F04>36819319</F04>
<F05>138.87</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>0</F03>
<F04>36827362</F04>
<F05>9.98</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>0</F03>
<F04>36834497</F04>
<F05>79.87</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1771929</F04>
<F05>400.07</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1766940</F04>
<F05>111.52</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1810269</F04>
<F05>112.48</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1618234</F04>
<F05>60.76</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>0</F03>
<F04>1771923</F04>
<F05>2829.19</F05>
</row>
</root>
...the wanted result is produced:
<root>
<row>
<F01>123456</F01>
<F02>ABC Company</F02>
<F03>437.53</F03>
<F04>47582736, 47643792, 47643793</F04>
<F05>151.12</F05>
</row>
<row>
<F01>223344</F01>
<F02>DK Corp</F02>
<F03>228.72</F03>
<F04>36819319, 36827362, 36834497</F04>
<F05>138.87</F05>
</row>
<row>
<F01>113964</F01>
<F02>Direct Company</F02>
<F03>3514.02</F03>
<F04>1771929, 1766940, 1810269, 1618234, 1771923</F04>
<F05>400.07</F05>
</row>
</root>
This is a classic grouping problem that, in the case of XSLT 1.0, uses Muenchian Grouping.
Related
I have done few XSLT in the past, but I am facing challenge in this.
I am working with PLC tag, for each tag i am getting three rowset node, so after every three Rowset i need to create new "Row" group.
Updated with XSLT
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<Rowsets >
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<WC_ID>0001</WC_ID>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag1_Good>6817</Tag1_Good>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag1_Bad>0</Tag1_Bad>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<WC_ID>0002</WC_ID>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag2_Good>6800</Tag2_Good>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag2_Bad>0</Tag2_Bad>
</Row>
</Rowset>
</Rowsets>
Expected output:
<?xml version="1.0" encoding="UTF-8"?>
<Rowset>
<Row>
<WC_ID>0001</WC_ID>
<Tag1_Good>6817</Tag1_Good>
<Tag1_Bad>0</Tag1_Bad>
</Row>
<Row>
<WC_ID>0002</WC_ID>
<Tag1_Good>6800</Tag1_Good>
<Tag1_Bad>0</Tag1_Bad>
</Row>
</Rowset>
My XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Rowsets >
<xsl:variable name="batchSize" select="3"/>
<Rowset>
<xsl:for-each select="/Rowsets/Rowset[position() mod $batchSize >= 0]"
<Row>
<xsl:value-of select="Row/*[2]" />
</Row>
</xsl:for-each>
</Rowset>
</Rowsets>
</xsl:template>
</xsl:stylesheet>
I am not able to make this into a new group
Use this:
<Rowsets>
<xsl:variable name="batchSize" select="3"/>
<Rowset>
<xsl:for-each select="/Rowsets/Rowset">
<xsl:variable name="pos" select="position()"/>
<xsl:if test="$pos mod $batchSize = 0">
<Row>
<WC_ID>
<xsl:value-of select="/Rowsets/Rowset[$pos - 2]/Row/*[2]"/>
</WC_ID>
<Tag1_Good>
<xsl:value-of select="/Rowsets/Rowset[$pos - 1]/Row/*[2]"/>
</Tag1_Good>
<Tag1_Bad>
<xsl:value-of select="/Rowsets/Rowset[$pos]/Row/*[2]"/>
</Tag1_Bad>
</Row>
</xsl:if>
</xsl:for-each>
</Rowset>
</Rowsets>
I am trying to delete from an XML file, all the nodes that not satisfy certain condition.
This is my simplified input:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit xmlns="http://www.srcML.org/srcML/src">
<Rowsets>
<Rowset>
<Row>
<FirstName>Michael</FirstName>
<LastName>David</LastName>
<Phone>1234567890</Phone>
</Row>
<Row>
<FirstName>David</FirstName>
<LastName>Michael</LastName>
<Phone>01234567890</Phone>
</Row>
<Row>
<FirstName>Yang</FirstName>
<LastName>Christina</LastName>
<Phone>2345678901</Phone>
</Row>
<Row>
<FirstName>Grey</FirstName>
<LastName>Meredith</LastName>
<Phone>3456789012</Phone>
</Row>
<Row>
<FirstName>Michael</FirstName>
<LastName>Shepherd</LastName>
<Phone>5678901234</Phone>
</Row>
</Rowset>
</Rowsets>
<Tag>
<FirstName>Michael</FirstName>
<LastName>Shepherd</LastName>
<Phone>5678901234</Phone>
</Tag>
</unit>
I would like to write an XSLT transformation file that will be able to delete all the nodes that don't have a child of type FirstName with value Michael.
For the input I have just provided, I would like to obtain this output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit xmlns="http://www.srcML.org/srcML/src">
<Row>
<FirstName>Michael</FirstName>
<LastName>David</LastName>
<Phone>1234567890</Phone>
</Row>
<Row>
<FirstName>Michael</FirstName>
<LastName>Shepherd</LastName>
<Phone>5678901234</Phone>
</Row>
<Tag>
<FirstName>Michael</FirstName>
<LastName>Shepherd</LastName>
<Phone>5678901234</Phone>
</Tag>
</unit>
This is the transformation file I have written up now:
<xsl:stylesheet
xmlns="http://www.srcML.org/srcML/src"
xmlns:src="http://www.srcML.org/srcML/src"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template name="removingNotMichael" match="*[child::src:FirstName[.= 'Michael']]">
<xsl:copy><xsl:apply-templates select="#*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
</xsl:template>
</xsl:stylesheet>
It does not produce anything, just a completely empty file.
Could anybody please help me with this issue?
You can Try this:
<xsl:template match="/">
<unit>
<xsl:copy-of select="//*[src:FirstName = 'Michael']"/>
</unit>
</xsl:template>
There are examples to group items using xsl:key, but those don't work for my scenario.
Each set with column1="H" should be named <transaction>, and all the items with column1="D" following the "H" should be inside the <transaction> as <item>, until it reaches the next "H". Then it repeats with the same rule.
Problem: The values are enclosed in double quotes, but the output shouldn't have double quotes.
<root>
<row>
<column1>"H"</column1>
<column2>"2016-09-09"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Conference Services Meeting Package"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Audio Visual Meeting Package"</column2>
</row>
<row>
<column1>"H"</column1>
<column2>"2016-09-09"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Meeting Package Lunch"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Marinated Roasted Olives</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Mezza Plate Humus with Smoked Paprika Butter"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Pastry Bread Block Loaf Bread"</column2>
</row>
</root>
Output:
<xml>
<transaction>
<item>Conference Services Meeting Package</item>
<item>Audio Visual Meeting Package</item>
</transaction>
<transaction>
<item>Meeting Package Lunch</item>
<item>Marinated Roasted Olives</item>
<item>Mezza Plate Humus with Smoked Paprika Butter</item>
<item>Pastry Bread Block Loaf Bread</item>
</transaction>
</xml>
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match='row[column1='"D"']'
use='generate-id(preceding-sibling::row[column1='"H"'][1])'/>
<xsl:template match="/*">
<xml>
<xsl:apply-templates select='row[column1='"H"']'/>
</xml>
</xsl:template>
<xsl:template match="row">
<transaction>
<xsl:apply-templates select="key('kFollowing', generate-id())/column2"/>
</transaction>
</xsl:template>
<xsl:template match="column2">
<item><xsl:value-of select=
'concat(translate(substring(.,1,1),'"',""),
substring(.,2, string-length(.) -2),
translate(substring(.,string-length()),'"',""))'/></item>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<root>
<row>
<column1>"H"</column1>
<column2>"2016-09-09"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Conference Services Meeting Package"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Audio Visual Meeting Package"</column2>
</row>
<row>
<column1>"H"</column1>
<column2>"2016-09-09"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Meeting Package Lunch"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Marinated Roasted Olives</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Mezza Plate Humus with Smoked Paprika Butter"</column2>
</row>
<row>
<column1>"D"</column1>
<column2>"Pastry Bread Block Loaf Bread"</column2>
</row>
</root>
produces exactly the wanted, correct result:
<xml>
<transaction>
<item>Conference Services Meeting Package</item>
<item>Audio Visual Meeting Package</item>
</transaction>
<transaction>
<item>Meeting Package Lunch</item>
<item>Marinated Roasted Olives</item>
<item>Mezza Plate Humus with Smoked Paprika Butter</item>
<item>Pastry Bread Block Loaf Bread</item>
</transaction>
</xml>
Explanation:
A key that defines all corresponding "D" <column2> elements as a function of the generate-id() of their corresponding (nearest preceding) "H" <column1> element.
Translating the 1st and last characters from (only if they are a quote) " to the empty string. Thus "Marinated Roasted Olives is processed correctly, even though it doesn't end with a quote -- which most probably is accidental mistake.
No <xsl:for-each> (even nested!) instruction.
Try it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="tx" match="row[column1='"D"']" use="generate-id(preceding-sibling::row[column1='"H"'][1])" />
<xsl:template match="/root">
<xml>
<xsl:for-each select="row[column1='"H"']">
<transaction>
<xsl:for-each select="key('tx', generate-id())">
<item>
<xsl:value-of select="column2"/>
</item>
</xsl:for-each>
</transaction>
</xsl:for-each>
</xml>
</xsl:template>
</xsl:stylesheet>
This solves the problem of grouping adjacent items. The problem of removing the double quotes is rather trivial, and can be solved easily by using the substring() function. Post a separate question if you can't make it work.
I have the following input XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<row>
<code>EXCLUDE</code>
<value>VALUE1</value>
</row>
<row>
<code>EXCLUDEALSO</code>
<value>VALUE2</value>
</row>
<row>
<code>NUMBER</code>
<value>001</value>
</row>
<row>
<code>FROM</code>
<value>NAMELINE_FROM</value>
</row>
<row>
<code>TO</code>
<value>NAMELINE_TO</value>
</row>
<row>
<code>NUMBER</code>
<value>002</value>
</row>
<row>
<code>TO</code>
<value>NAMELINE_TO</value>
</row>
<row>
<code>NUMBER</code>
<value>003</value>
</row>
<row>
<code>FROM</code>
<value>NAMELINE_FROM</value>
</row>
<row>
<code>NUMBER</code>
<value>004</value>
</row>
<row>
<code>TO</code>
<value>NAMELINE</value>
</row>
<row>
<code>FROM</code>
<value>NAMELINE</value>
</row>
<row>
<code>EXCLUDE</code>
<value>VALUE1</value>
</row>
<row>
<code>EXCLUDEALSO</code>
<value>VALUE2</value>
</row>
</data>
And it needs to be transformed to the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<row>
<code>EXCLUDE</code>
<value>VALUE1</value>
</row>
<row>
<code>EXCLUDEALSO</code>
<value>VALUE2</value>
</row>
<group>
<row>
<code>NUMBER</code>
<value>001</value>
</row>
<row>
<code>FROM</code>
<value>NAMELINE_FROM</value>
</row>
<row>
<code>TO</code>
<value>NAMELINE_TO</value>
</row>
</group>
<group>
<row>
<code>NUMBER</code>
<value>002</value>
</row>
<row>
<code>TO</code>
<value>NAMELINE_TO</value>
</row>
</group>
<group>
<row>
<code>NUMBER</code>
<value>003</value>
</row>
<row>
<code>FROM</code>
<value>NAMELINE_FROM</value>
</row>
</group>
<group>
<row>
<code>NUMBER</code>
<value>004</value>
</row>
<row>
<code>TO</code>
<value>NAMELINE</value>
</row>
<row>
<code>FROM</code>
<value>NAMELINE</value>
</row>
</group>
<row>
<code>EXCLUDE</code>
<value>VALUE1</value>
</row>
<row>
<code>EXCLUDEALSO</code>
<value>VALUE2</value>
</row>
</data>
The rules to be applied:
Some rows needs to be excluded from the grouping. These would be the rows that do not have the code NUMBER, FROM or TO.
When code NUMBER appears a new group starts
FROM and TO could be in different order
Rows that have to be exclude will always be in front and/or at the end of the to be grouped codes. It will never appear in between.
In XSLT 2.0 this would be easy and I have the solution, but in XSLT 1.0 I do not know where to start.
Here is a stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="group" match="row[code = 'TO' or code = 'FROM']" use="generate-id(preceding-sibling::row[code = 'NUMBER'][1])"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="row[code = 'NUMBER']">
<group>
<xsl:copy-of select=". | key('group', generate-id())"/>
</group>
</xsl:template>
<xsl:template match="row[code = 'FROM' or code = 'TO']"/>
</xsl:stylesheet>
I've seen many posts on this, but none of them have helped me figure out my problem.
Test1.xml
<table>
<row>
<col1>A</col1>
</row>
<row>
<col1>B</col1>
</row>
<row>
<col1>C</col1>
</row>
</table>
Test2.xml
<table>
<row>
<col1>A</col1>
<col2>ABC</col2>
</row>
<row>
<col1>B</col1>
<col2>ABC</col2>
</row>
<row>
<col1>A</col1>
<col2>ABC</col2>
</row>
<row>
<col1>C</col1>
<col2>ABC</col2>
</row>
<row>
<col1>A</col1>
<col2>DEF</col2>
</row>
</table>
Test.xsl (XSLT 1.0)
<xsl:variable name="input" select="document('test1.xml')/>
<xsl:template match="/">
<xsl:apply-templates select="$input" mode="special"/>
</xsl:template>
<xsl:template match="node()|#" mode="special">
<xsl:copy>
<xsl:apply-templates select="node()|#" mode="special"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Row" mode="special">
<xsl:variable name="cols" select="document('test2.xml')/Table/Row[current()/Col1 = Col1]/Col2"/>
<xsl:variable name="unique_cols" select="$cols[not(. = preceding-sibling::*)]"/>
<!-- Debug -->
<xsl:for-each select="$unique_cols">
<xsl:copy-of select="."/>
</xsl:for-each>
----
</xsl:template>
Expected Output:
<col2>ABC</col2>
<col2>DEF</col2>
----
<col2>ABC</col2>
----
<col2>ABC</col2>
Current Output:
<col2>ABC</col2>
<col2>ABC</col2>
<col2>DEF</col2>
----
<col2>ABC</col2>
----
<col2>ABC</col2>
The col2 values in $unique_cols should be distinct per col1 values. If unique col2 values could be selected in $cols, even better.
Just replace:
<xsl:variable name="unique_cols" select="$cols[not(. = preceding-sibling::*)]"/>
with:
<xsl:variable name="unique_cols" select=
"$cols[not(../col1 = ../preceding-sibling::*/col1)]"/>
The full transformation (initially corrrected to fix a multitude of lexical errors) now becomes (also using my own file-Uris):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="input" select=
"document('file:///c:/temp/delete/test1.xml')"/>
<xsl:template match="/">
<xsl:apply-templates select="$input" mode="special"/>
</xsl:template>
<xsl:template match="node()|#*" mode="special">
<xsl:copy>
<xsl:apply-templates select="node()|#*" mode="special"/>
</xsl:copy>
</xsl:template>
<xsl:template match="row" mode="special">
<xsl:variable name="cols" select=
"document('file:///c:/temp/delete/test2.xml')
/table
/row[current()/col1 = col1]
/col2"/>
<xsl:variable name="unique_cols" select=
"$cols[not(../col1 = ../preceding-sibling::*/col1)]"/>
<!-- Debug -->
<xsl:for-each select="$unique_cols">
<xsl:copy-of select="."/>
</xsl:for-each>
----
</xsl:template>
</xsl:stylesheet>
and the files are:
c:/temp/delete/test1.xml:
<table>
<row>
<col1>A</col1>
</row>
<row>
<col1>B</col1>
</row>
<row>
<col1>C</col1>
</row>
</table>
and: c:/temp/delete/test2.xml:
<table>
<row>
<col1>A</col1>
<col2>ABC</col2>
</row>
<row>
<col1>B</col1>
<col2>ABC</col2>
</row>
<row>
<col1>A</col1>
<col2>ABC</col2>
</row>
<row>
<col1>C</col1>
<col2>ABC</col2>
</row>
</table>
When the transformation is performed on any XML document (not used), the wanted, correct result is produced:
<table>
<col2>ABC</col2>
----
<col2>ABC</col2>
----
<col2>ABC</col2>
----
</table>
I think I may have figured this out based on an answer provided on another post (https://groups.google.com/forum/?fromgroups#!topic/microsoft.public.xsl/i8FwJUD0r8U).
<xsl:variable name="cols" select=
"document('test2.xml')/table/row[current()/col1 = col1]/col2[not(. = ../preceding-sibling::*/col2[current()/col1 = ../col1])]"/>
This appears to select unique col2 values into $cols eliminating the need for the second variable.