Selecting nodes with exclusions

P

PatrickRThomas

I need help selecting nodes while excluding some of them. Here's an
example of XML:

<my_xml>
<all_items>
<item>
<key>1</key>
<name>Item 1</name>
</item>
<item>
<key>2</key>
<name>Item 2</name>
</item>
<item>
<key>3</key>
<name>Item 3</name>
</item>
</all_items>
<excluded_items>
<key>1</key>
<key>3</key>
</excluded_items>
</my_xml>

I want to select the nodes from "all_items" that don't have a
coresponding value in "excluded_items". Is that possible to do? Or do
I need to do it in multiple steps by select all of the nodes and then
filtering through the ones that are excluded? Any help would be
appreciated.
 
J

Joseph Kesselman

What do you mean by "select"? Javascript, XPath/XSLT, DOM traversal, other?
 
J

Joe Kesselman

I want to select it into a variable in XSLT.

OK, then you want to find
All the <item> elements in <all_items>
Such that
The value of the <item>'s <key> child
Is not the same
As any of the <key>s in <excluded_items>

One way to write that XPath would be:

/my_xml/all_items/item[key != ../excluded_items/key]

This takes advantage of the fact that comparing two node sets reports
true if any value in the first set matches a value from the second set.
 
P

PatrickRThomas

Joe said:
One way to write that XPath would be:

/my_xml/all_items/item[key != ../excluded_items/key]

This takes advantage of the fact that comparing two node sets reports
true if any value in the first set matches a value from the second set.

Doesn't that only compare each "/my_xml/all_items[key]" to the first
"key" node of "exluded_items"?

In my example, only key=1 would be filtered out because it would only
compare to the first item in excluded_items, which is key=1.
 
J

Joe Kesselman

Doesn't that only compare each "/my_xml/all_items[key]" to the first
"key" node of "excluded_items"?

Nope. Both the ./key and ../excluded_items/key expressions return
nodesets, and as the spec says:

"If both objects to be compared are node-sets, then the comparison will
be true if and only if there is a node in the first node-set and a node
in the second node-set such that the result of performing the comparison
on the string-values of the two nodes is true."

If we were explicitly taking string-value(../excluded_items/key), then
yes, that would obtain the value only of the first such node. But that's
due to the definition of string-value on a nodeset, not of comparison of
nodesets.
 
P

PatrickRThomas

Maybe I'm doing something wrong, but it's not working for me. Here's
my stylesheet for this test case. Nothing is being returned for my
variable FilteredItems.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="FilteredItems"
select="/my_xml/all_items/item[key!=../excluded_items/key]"/>
<xsl:copy-of select="$FilteredItems"/>
</xsl:template>
</xsl:stylesheet>
 
J

Joe Kesselman

Sorry; I was describing the right idea but had two details wrong. Try:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<doc>
<xsl:variable name="FilteredItems"
select="/my_xml/all_items/item[not(key=../../excluded_items/key)]"/>
<xsl:copy-of select="$FilteredItems"/>
</doc>
</xsl:template>
</xsl:stylesheet>


(I'd left out one ../, and in this case not(=) is not the same thing as
!=. (The equality test is effectively an "or".)

Sigh. That's what I get for not tossing it though the interpreter for a
test before posting.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,809
Latest member
moe77

Latest Threads

Top