Hermann,
I wonder if I am not mistaking your question, since prima facie it seems
pretty simple: indeed it is given by your paraphrase of "//*/*" as "all
nodes beside the root element node". (And FWIW, this should be all
_element_ nodes, not all nodes altogether.)
That is, surely the answer to the node in //* that is not in //*/* is
/*
Now perhaps you mean to inquire not about the solution to this
particular problem, but a more general problem regarding set differencing.
In XPath 2.0 we have the convenient operation "except", so we can have
//* except //*/*
Needless to say, you can expect the performance of this to degrade with
large documents, unlike /*.
If your question is restricted to XPath 1.0, and again /* won't do, then
how about the classic
//*[count(.|//*/*) != count(//*/*)]
The problem of getting out of the local context when inside the
predicate isn't a problem, since these are absolute paths.
Which again leads me to think you haven't posed the question you really
want to answer.
As for your attempt,
//*[count(.|ancestor-or-self::*//*/*)!=count(ancestor-or-self::*//*/*)]
this would actually work if instead of ancestor-or-self::* you had
ancestor-or-self::node(). (Again, this is not to say it would be at all
efficient.)
It's the fact that the document root node has to be accounted for that's
throwing this off. The expression ancestor-or-self::*//*/* will never
(from any context) return the document element (the element child of the
document root) or its element children (it goes only as high as its
children's children) -- so these will always be included in your return
set. If you had ancestor-or-self::node()//*/*, the element children of
the document element would be included in the set of elements being
counted, and so excluded from your return set -- leaving only /* (the
document element).
Cheers,
Wendell
On 3/24/2011 4:33 PM, Hermann Stamm-Wilbrandt wrote:
Hello,
I saw a question on what "//*/*" means.
The answer is simple, all nodes beside the root element node.
This can be easily seen by this XPath expression:
$ echo "<a><b><c/></b><b><c/><c/></b></a>" | xpath++ "count(//*)-count
(//*/*)" -
1
$
Now I wanted to use Kaysian set difference method to output the
node in "//*" which is not in "//*/*", see 1a on this page:
http://www.xml.org//sites/www.xml.org/files/xslt_efficient_programming_techniques.pdf#page=3
But here two nodesets ($ns1, $ns2) are determined first before determining
the set (asymmetric) difference as "$ns1[count(.|$ns2)!=count($ns2)]".
Is it possible to have that as pure XPath statement?
The problem is to jump out of the scope of "//*[. ...]".
This does not work correctly:
$ echo "<a><b><c/></b><b><c/><c/></b></a>" | xpath++ "//*[count(.|
ancestor-or-self::*//*/*)!=count(ancestor-or-self::*//*/*)]" -
-------------------------------------------------------------------------------
<a><b><c/></b><b><c/><c/></b></a>
-------------------------------------------------------------------------------
<b><c/></b>
-------------------------------------------------------------------------------
<b><c/><c/></b>
$
What is the correct XPath statement for "//* minus //*/*"?
[1]
https://www.ibm.com/developerworks/forums/thread.jspa?messageID=14511881#145
11881
--
======================================================================
Wendell Piez
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
--~------------------------------------------------------------------
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>
--~--