Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > XML > XSLT
Password Reminder
Register
| FAQ | Members List | Search | Today's Posts | Mark Forums Read
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old July 15th, 2003, 07:20 PM
Registered User
 
Join Date: Jun 2003
Location: Menlo Park, CA, USA.
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default XPath: set operation with a disjoint node set

input file:
<foo type="a"/>
<foo type="b"/>
<foo type="c"/>
<bar type="a"/>
<bar type="b"/>

Now, say I've got node sets:
<xsl:variable name="A" select="foo"/>
<xsl:variable name="B" select="bar"/>

And I'd like to select any <foo>s with types not found in the set of <bar>s. In this example, that would be just the 3rd <foo>. How would I do this?

My first thought was to select:
$A[string(@type) != string($B/@type)]

...but that will only select nodes from A whose type is not "a" (the first <foo>'s type).

Any clues?

Thanks,
Rich
Reply With Quote
  #2 (permalink)  
Old July 16th, 2003, 02:31 AM
joefawcett's Avatar
Wrox Author
Points: 9,763, Level: 42
Points: 9,763, Level: 42 Points: 9,763, Level: 42 Points: 9,763, Level: 42
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jun 2003
Location: Exeter, , United Kingdom.
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

You don't want or need string function and you need to change from != to not:
$A[not(@type = $B/@type)]

not means there are no matches, i.e. no @type in $B matches the @type of $A, != means they all don't match, if any non-match can be found then include the node.
If you're xml is:

Code:
<root>
<foo type="a"/>
<foo type="b"/>
<foo type="c"/>
<bar type="a"/>
<bar type="b"/>
</root>
and xsl is:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:variable name="A" select="root/foo"/>
    <xsl:variable name="B" select="root/bar"/>
    <xsl:for-each select="$A[@type != $B/@type]">
      <xsl:text>#x0a;</xsl:text><xsl:copy-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
Run this and then change select to:
$A[@type != $B/@type]

to see difference.

--

Joe
Reply With Quote
  #3 (permalink)  
Old July 16th, 2003, 04:47 AM
joefawcett's Avatar
Wrox Author
Points: 9,763, Level: 42
Points: 9,763, Level: 42 Points: 9,763, Level: 42 Points: 9,763, Level: 42
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jun 2003
Location: Exeter, , United Kingdom.
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Sorry, the initial xsl should have been:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:variable name="A" select="root/foo"/>
    <xsl:variable name="B" select="root/bar"/>
    <xsl:for-each select="$A[not(@type = $B/@type)]">
      <xsl:text>#x0a;</xsl:text><xsl:copy-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
I pasted the wrong version...

--

Joe
Reply With Quote
  #4 (permalink)  
Old July 16th, 2003, 05:20 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: Nor Hachin, Kotayk, Armenia.
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via Yahoo to armmarti
Default

The whole problem is in the "magical" properties of the "!=" operator and in the use of the "string" function here.
Look why your code is not working:
The function "string" returns the string value of the first node when the argument is a nodeset. So in your XPath expression you compare the context node's attribute's string-value to the first "foo" element's attribute value.
Even
Code:
$A[@type != $B/@type]
is not working again due to the rules for "!=" operator. Actually, "=" operator "returns" true for nodesets NS1 and NS2 as arguments when there is a node n1 in NS1 and node n2 in NS2 such that their string-values are the same. And "!=" is not a logical negation of "=": for 2 nodesets "!=" "returns" true if there is at least one pair of (n1, n2) [n1 is in NS1 and n2 is in NS2] such that their string-values are not the same. Therefore there are situations when "not(NS1 = NS2)" is not equivalent to "NS1 != NS2".
That's why you have to use "not" instead of "!=" here and you have to compare nodesets instead of using"string" function.

The working XPath expression is
Code:
$A[not(@type = $B/@type)]
Regards,
Armen
Reply With Quote
  #5 (permalink)  
Old July 16th, 2003, 01:30 PM
Registered User
 
Join Date: Jun 2003
Location: Menlo Park, CA, USA.
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Wow, thanks for setting me straight, guys!
Reply With Quote
  #6 (permalink)  
Old May 5th, 2008, 10:33 AM
Registered User
 
Join Date: May 2008
Location: , , .
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I have a similar issue but I'm having a hard time trying to figure out how to make it work. I'm trying to get the union of two node sets with one having priority.

Example:
<defaults>
  <color>red</color>
  <size>10</size>
  <flavor>cherry</flavor>
</defaults>

<config>
  <color>black</color>
  <flavor>blueberry</flavor>
</config>

So, it seems like I should be able to do something like this:

<xsl:variable name="class" select="defaults"></xsl:param>
<xsl:variable name="instance" select="config"></xsl:param>

<xsl:for-each select="$class[not(name() != $instance/name())]">
    <xsl:text>#x0a;</xsl:text><xsl:copy-of select="."/>
</xsl:for-each>

<xsl:for-each select="$instance">
        <xsl:copy-of select="."/>
</xsl:for-each>

The results should end up something like this then:

  <size>10</size>
  <color>black</color>
  <flavor>blueberry</flavor>

I know I've probably presented this too simply so please let me know what other info I could provide to help it make sense. The main issue seems to be the predicate not being allowed to match on name().
Reply With Quote
  #7 (permalink)  
Old May 5th, 2008, 10:58 AM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You first need to say whether you are using XSLT 1.0 or XSLT 2.0.

In 2.0 this is best treated as a grouping problem:

<xsl:for-each-group select="defaults/*, config/*" group-by="node-name()">
  <xsl:copy-of select="current-group()[last()]"/>
</xsl:for-each>

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #8 (permalink)  
Old May 6th, 2008, 09:24 AM
Registered User
 
Join Date: May 2008
Location: , , .
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I'm using XSLT 1.0
Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Illegal operation on empty result set. amisrivas JSP Basics 2 February 19th, 2008 11:49 PM
Filtering out from a node set anothervbaddict XSLT 1 May 22nd, 2007 08:42 AM
"OPERATION NOT ALLOWED AFTERRESULT SET IS CLOSED" picky JSP Basics 3 October 12th, 2006 03:26 PM
OPERATION NOT ALLOWED AFTERRESULT SET IS CLOSED" picky Java Databases 0 October 4th, 2006 05:36 AM
PWS0007 - Operation result set not found tkwhk SQL Server 2000 0 August 14th, 2006 02:32 AM



All times are GMT -4. The time now is 05:45 AM.


Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.