An XPath expression of /
returns the document node.
An XPath expression of /html
is equivalent to /child::html
and given an HTML document would return the html element. This is of course evaluated by going to the document node (indicated by the /
) and then finding the element child which is an html tag.
Why then does /document-node()
actually return the document node?
Given the general XPath expression rules, I would assume /document-node()
is equivalent to /child::document-node()
, and /child::document-node()
should return an empty node sequence (since a document node is never a child of a document node). In fact /child::document-node()
does return an empty node sequence, which leads me to believe that /document-node()
is not equivalent to /child::document-node()
. This seems to violate the general XPath expression rules, where an empty axis is an implied child axis1.
Is there some special rule such that when you have a step of document-node()
the axis is assumed to be self
instead of child
? I'm using the latest version of Altova XMLSpy (2018 sp1). Alternatively, is this a bug in XMLSpy? Or is some part of my understanding of general XPath expression rules incorrect?
Note: For anyone who is trying this out, only XPath 2 and XPath 3 support document-node()
.
1 Update: As an unrelated FYI, I learned something new from Mads Hansen's answer: in XPath 2 and XPath 3, an empty axis is an implied child axis unless there's an attribute test; if there's an attribute test it's actually an implied attribute axis. So while /html
is implicitly /child::html
, /attribute()
is implicitly /attribute::attribute()
.
That appears to be a bug in XML Spy.
- If the axis name is omitted from an axis step, the default axis is
child
, with two exceptions: if the NodeTest in an axis step contains an AttributeTest or SchemaAttributeTest then the default axis isattribute
; if the NodeTest in an axis step is a NamespaceNodeTest then a static error is raised [err:XQST0134] .
Verifying with Saxon 9.8.0.8 (HE, PE, EE) and MarkLogic 9.0.3, the XPath /document-node()
and /child::document-node()
do not select anything.
These XPaths with different axis names do select the document-node()
:
/self::document-node()
/ancestor-or-self::document-node()
/*/ancestor::document-node()
/*/ancestor-or-self::document-node()