On 4/13/07, cknell(_at_)onebox(_dot_)com <cknell(_at_)onebox(_dot_)com> wrote:
Yesterday I was tasked to produce a list of records from an Oracle database
where the result set contained rows where the value in one of the columns was
not one of a long list. (Bear with me, please, we'll get to XSLT in a moment.)
The problem was that the list of values to omit was simply too long for
SQL*Plus. So I went to plan B. I selected all the rows from the table in
question into an XML document. I prepared a second XML document that contained
an element for each of the values to be omitted.
I then wrote a stylesheet with this template:
<xsl:template match="ROWSET">
<ROWSET>
<xsl:apply-templates select="ROW[not(CODE = $active-codes/ROWSET/ROW/CODE)]"
/>
</ROWSET>
</xsl:template>
So the output contained all the ROW elements in the original document whose
CODE child string value didn't match any of the CODE string values in the
document containing the values I wanted to omit from the result.
In short, I wanted to subtract the set of values contained in the second
document from the first, resulting in a document containing only the
non-matching values.
After I finished, it occurred to me that this probably wasn't so unusual a
need, and that probably someone had written a general-purpose function for
this. What I had in mind is a function that would take four arguments:
1) A base document (base document) [$base]
2) A document containing the values to subtract from the base document
(exemplar document) [$exemplar]
3) The XPath to the elment in the base document holding the values of interest.
[$base-element]
4) The XPath to the element in the exemplar document holding the values of
interest. [$list-element]
The result would be a document with the same structure as the base document
containing only those elements which didn't have a matching value.
Here is an example of two documents:
The base document:
<?xml version="1.0"?>
<grocery-list>
<item>apple</item>
<item>milk</item>
<item>cheese</item>
<item>coffee</item>
<item>asparagus</item>
</grocery-list>
The exemplar document:
<?xml version="1.0"?>
<inventory>
<sku>apple</sku>
<sku>pear</sku>
<sku>grapes</sku>
</inventory>
What I would like is a general-purpose function that would subtract those
elements from the first document whose values matched the elements in the
second.
<grocery-list>
<item>milk</item>
<item>cheese</item>
<item>coffee</item>
<item>asparagus</item>
</grocery-list>
I've poked around on Google, but haven't found a useful was to compose the
search. Does anyone on the list know of such a function or have you written
one? I am reluctant to re-invent the wheel, particularly when mine is not
likely to be as round and smooth as an existing one.
Is this any good?
select="$base//item[not(. = $exemplar//sku)]"
cheers
andrew
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--