1

I'd like to return only the AA nodes that don't contain a BB child node. I'm using XPath 1.0 btw.

Sample xml file:

<?xml version="1.0" encoding="UTF-8"?>
<T>
 <AA>
  <ZZ>z</ZZ>        
 </AA>
 <AA>
  <BB>b1</BB>        
 </AA>
 <AA>
  <BB>b2</BB>        
  <CC>c</CC>        
 </AA>
 <AA>
  <CC>c</CC>        
  <DD>d</DD>        
 </AA>
</T>

So with the above exampe, only the first and last AA nodes should be returned. I've tried something like:

//AA/*[not(BB)]/..

...but this still returns all 4 AA nodes.

Is the 'not' function available in 1.0? If so, what am I doing wrong? thank you...

2
  • Not sure what this has to do with Perl? Commented Feb 14, 2014 at 2:09
  • Sorry, out of habit ... only if I included just one 'my' stmt, huh? Commented Feb 14, 2014 at 13:45

3 Answers 3

2

Your expression selects nodes that are children of AA nodes that do not have BB as children. If you make the assertion about the AA node then you should get what you want:

use strict;
use warnings;

use XML::XPath;

my $xp = XML::XPath->new( filename => 'test.xml');

my $nodeset = $xp->find('//AA[not(BB)]');

foreach my $node ($nodeset->get_nodelist) {
  print "FOUND:\n";
  print ' ', $node->toString, "\n";
}

Which outputs:

FOUND:
 <AA>
  <ZZ>z</ZZ>        
 </AA>
FOUND:
 <AA>
  <CC>c</CC>        
  <DD>d</DD>        
 </AA>
Sign up to request clarification or add additional context in comments.

Comments

1

Keep in mind that

//AA/*[not(BB)]/..

is just a short way or writing

descendant::AA/child::*[not(child::BB)]/parent::node()

As this makes more obvious, BB doesn't check if the name of the context node is BB, it finds the children named BB.


You're checking if the child elements of AA have child elements BB.

You want to check if the AA elements have child elements BB.

//AA[not(BB)]

1 Comment

thank you; yes, that works ... I could of sworn I tried that ... geez!
0

You can use:

//AA[not(BB)]

The expression you tried selects the elements contained in AA which don't contain BB.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.