xsl-list
[Top] [All Lists]

RE: Re: [xsl] XSLT Subtract function?

2007-04-13 08:49:00
Thanks, Andrew. David Carlisle put me right. I can't evaluate a string as an 
XPath expression, which was (now that David has pointed out my error), not a 
legitimate approach.
-- 
Charles Knell
cknell(_at_)onebox(_dot_)com - email



-----Original Message-----
From:     Andrew Welch <andrew(_dot_)j(_dot_)welch(_at_)gmail(_dot_)com>
Sent:     Fri, 13 Apr 2007 16:27:09 +0100
To:       xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject:  Re: [xsl] XSLT Subtract function?

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>
--~--




--~------------------------------------------------------------------
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>
--~--