title: Get nodes that don't have specific ancestor xml xpath
body: <p>I'm struggling few days with quite complex xpath and I'm not able to formulate it.
  I have a syntactic tree from c++ like language parser and I would like to have xpath query, that selects all names, that are not in function name.</p>
  
  <p>To be specific, I have xml document like this</p>
  
  <p>(Whole xml document is on the end of the question, it is quite large I paste here a simple overview of the document structure)
  there are four node types<br>
  a - this element contains one node<br>
  b - contains information of the node (e.g. "CALL_EXPRESSION")<br>
  c - contains actual text (e.g. "printf", variable names...)<br>
  d - contains descendats of current node (a elements)<br></p>
  
  <pre>
  CALL_EXPRESSION
    DOT_EXPRESSION
      NAME_EXPRESSION
        NAME
      NAME_EXPRESSION
        NAME
    PARAMS
      NAME_EXPRESSION
        NAME
  
  CALL_EXPRESSION
    NAME_EXPRESSION
      NAME
    PARAMS
      NAME_EXPRESSION
        NAME
  
  ASSIGNMENT_EXPRESSION
    NAME_EXPRESSION
      NAME
    NAME_EXPRESSION
      NAME
  </pre>
  
  <p>I would like to formulate Xpath query, that would select all NAMEs that are not descendats of CALL_EXPRESSION/*[1]. (This means i would like to select all variables and not the function names).</p>
  
  <p>To select all the function names I can use Xpath like this </p>
  
  <blockquote>
    <p>//a[b="CALL_EXPRESSION"]/d/a[1]</p>
  </blockquote>
  
  <p>no problem here. Now, if I would like to select all nodes that are not descendats of this nodes. I would use not(ancestor::X).</p>
  
  <p>But here goes the problem, if I formulate the Xpath expression like this:</p>
  
  <blockquote>
    <p>//*[b="NAME"][not(ancestor::a[b="CALL_EXPRESSION"]/d/a[1])]</p>
  </blockquote>
  
  <p>it selects only nodes, that don't have a that has child b="CALL_EXPRESSION" at all. In our example, it selects only NAME from the ASSIGNMENT_EXPRESSION subtree.</p>
  
  <p>I suspected, that the problem is, that ancestor:: takes only the first element (in our case a[b="CALL_EXPRESSION"]) and restricts according to its predicate and further / are discarded. So i modified the xpath query like this:</p>
  
  <blockquote>
    <p>//*[b="NAME"][not(ancestor::a[../../b="CALL_EXPRESSION"
    and position()=1])]</p>
  </blockquote>
  
  <p>This seems to work only on the simpler CALL_EXPRESSION (without the DOT_EXPRESSION). I suspected, that the path in [] might be relative only to current node, not to the potential ancestors. 
  But when I used the query</p>
  
  <blockquote>
    <p>//*[b="NAME"][not(ancestor::a[b="CALL_EXPRESSION"])]</p>
  </blockquote>
  
  <p>it worked as one would assume (all NAMEs what don't have ancestor CALL_EXPRESSION were selected).</p>
  
  <p>Is there any way to formulate the query I need? And why don't the queries work?</p>
  
  <p>Thanks in advance :)</p>
  
  <p>The XML </p>
  
  <pre><code>&lt;a&gt;
   &lt;b&gt;CALL_EXPRESSION&lt;/b&gt;
   &lt;c&gt;object.method(a)&lt;/c&gt;
   &lt;d&gt;
     &lt;a&gt;
       &lt;b&gt;DOT_EXPRESSION&lt;/b&gt;
       &lt;c&gt;object.method&lt;/c&gt;
       &lt;d&gt;
         &lt;a&gt;
           &lt;b&gt;NAME_EXPRESSION&lt;/b&gt;
           &lt;c&gt;object&lt;/c&gt;
           &lt;d&gt;
             &lt;a&gt;
               &lt;b&gt;NAME&lt;/b&gt;
               &lt;c&gt;object&lt;/c&gt;
               &lt;d&gt;
               &lt;/d&gt;
             &lt;/a&gt;
           &lt;/d&gt;
         &lt;/a&gt;
         &lt;a&gt;
           &lt;b&gt;NAME_EXPRESSION&lt;/b&gt;
           &lt;c&gt;method&lt;/c&gt;
           &lt;d&gt;
             &lt;a&gt;
               &lt;b&gt;NAME&lt;/b&gt;
               &lt;c&gt;method&lt;/c&gt;
               &lt;d&gt;
               &lt;/d&gt;
             &lt;/a&gt;
           &lt;/d&gt;
         &lt;/a&gt;
       &lt;/d&gt;
     &lt;/a&gt;
     &lt;a&gt;
       &lt;b&gt;PARAMS&lt;/b&gt;
       &lt;c&gt;(a)&lt;/c&gt;
       &lt;d&gt;
         &lt;a&gt;
           &lt;b&gt;NAME_EXPRESSION&lt;/b&gt;
           &lt;c&gt;a&lt;/c&gt;
           &lt;d&gt;
             &lt;a&gt;
               &lt;b&gt;NAME&lt;/b&gt;
               &lt;c&gt;a&lt;/c&gt;
               &lt;d&gt;
               &lt;/d&gt;
             &lt;/a&gt;
           &lt;/d&gt;
         &lt;/a&gt;
       &lt;/d&gt;
     &lt;/a&gt;
   &lt;/d&gt;
  &lt;/a&gt;
  
  &lt;a&gt;
   &lt;b&gt;CALL_EXPRESSION&lt;/b&gt;
   &lt;c&gt;puts(b)&lt;/c&gt;
   &lt;d&gt;
     &lt;a&gt;
       &lt;b&gt;NAME_EXPRESSION&lt;/b&gt;
       &lt;c&gt;puts&lt;/c&gt;
       &lt;d&gt;
         &lt;a&gt;
           &lt;b&gt;NAME&lt;/b&gt;
           &lt;c&gt;puts&lt;/c&gt;
           &lt;d&gt;
           &lt;/d&gt;
         &lt;/a&gt;
       &lt;/d&gt;
     &lt;/a&gt;
     &lt;a&gt;
       &lt;b&gt;PARAMS&lt;/b&gt;
       &lt;c&gt;(b)&lt;/c&gt;
       &lt;d&gt;
         &lt;a&gt;
           &lt;b&gt;NAME_EXPRESSION&lt;/b&gt;
           &lt;c&gt;b&lt;/c&gt;
           &lt;d&gt;
             &lt;a&gt;
               &lt;b&gt;NAME&lt;/b&gt;
               &lt;c&gt;b&lt;/c&gt;
               &lt;d&gt;
               &lt;/d&gt;
             &lt;/a&gt;
           &lt;/d&gt;
         &lt;/a&gt;
       &lt;/d&gt;
     &lt;/a&gt;
   &lt;/d&gt;
  &lt;/a&gt;
  
  &lt;a&gt;
   &lt;b&gt;ASSIGNMENT_EXPRESSION&lt;/b&gt;
   &lt;c&gt;c=d;&lt;/c&gt;
   &lt;d&gt;
     &lt;a&gt;
       &lt;b&gt;NAME_EXPRESSION&lt;/b&gt;
       &lt;c&gt;c&lt;/c&gt;
       &lt;d&gt;
         &lt;a&gt;
           &lt;b&gt;NAME&lt;/b&gt;
           &lt;c&gt;c&lt;/c&gt;
           &lt;d&gt;
           &lt;/d&gt;
         &lt;/a&gt;
       &lt;/d&gt;
     &lt;/a&gt;
     &lt;a&gt;
       &lt;b&gt;NAME_EXPRESSION&lt;/b&gt;
       &lt;c&gt;d&lt;/c&gt;
       &lt;d&gt;
         &lt;a&gt;
           &lt;b&gt;NAME&lt;/b&gt;
           &lt;c&gt;d&lt;/c&gt;
           &lt;d&gt;
           &lt;/d&gt;
         &lt;/a&gt;
       &lt;/d&gt;
     &lt;/a&gt;
   &lt;/d&gt;
  &lt;/a&gt;
  </code></pre>