XPath doesn't seem to descend into iframes.

J

John Nagle

The usual approach for finding all links:

var allhrefs = document.evaluate(
"//a[@href]",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);

doesn't seem to descend into <iframe> sections of the DOM
in FireFox 2. Is that correct? Can XPath be told to descend
into an iframe subdocument? Or is it necessary to find all the
<iframe> tags and recurse?

John Nagle
 
H

Henry

The usual approach for finding all links:

var allhrefs = document.evaluate(
"//a[@href]",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);

That is a long way from a "usual" approach. The usual approach is
probably to use the pre-existing - document.links - collection (as
specified in the W3C HTML DOM as a formalisation of pre-existing
browser object model's "convenience" links collection, and thus the
reliable and cross-browser approach). In the presence of a pre-
existing collection any approach that requires a runtime traversal of
the entire DOM is actually pushing perverse.
doesn't seem to descend into <iframe> sections of the DOM
in FireFox 2. Is that correct?

That would be the expected situation, given that you are calling an -
evaluate - method of the document object and the documents in the
IFRAMEs are separate document objects.
Can XPath be told to descend into an iframe subdocument?

What do the XPath specs say? The last time I looked at an XPath
specification there were no suggestions of facilities for working
outside of the current document. Things may have changed in more
recent versions.
Or is it necessary to find all the
<iframe> tags and recurse?

It would be more normal to loop through the window object's - frames -
collection and examine the document object of each window/frame found
in that collection (and possibly recursing through the - frames -
collections of those frame/window objects). XPath is a bit like using
a hammer to crack a nut in this context.
 
M

Martin Honnen

John said:
The usual approach for finding all links:

var allhrefs = document.evaluate(
"//a[@href]",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);

doesn't seem to descend into <iframe> sections of the DOM
in FireFox 2. Is that correct? Can XPath be told to descend
into an iframe subdocument? Or is it necessary to find all the
<iframe> tags and recurse?

If you want to evaluate XPath expressions on the document of an iframe
then you need to use the iframe's document object and call evaluate on
it e.g.
<iframe name="iframe1"
src="foo.html"></iframe>

var iframeDoc = window.frames.iframe1.document;
if (typeof iframeDoc.evaluate != 'undefined') {
var xpathResult = iframeDoc.evaluate('expression', iframeDoc, null,
resultType, null);
}
 
T

Thomas 'PointedEars' Lahn

John said:
The usual approach for finding all links:

var allhrefs = document.evaluate(
"//a[@href]",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);

As Richard said, it is not the usual approach at all as XPath support
was introduced late in client-side DOM scripting and is therefore not
universally supported.

It should also be noted that the //a[@href] snapshot and the
`document.links' collection are not equivalent. Firstly,
document.links includes also `area' elements ('//area[@href]', and
eventually '//*[local-name() = "A" or (local-name() = "AREA" and
@href)]' -- use lowercase for XHTML, XPath 2.0 is apparently not
supported yet --, or simply '//*[@href]', in XPath). Secondly, the
collection is /live/.

http://www.w3.org/TR/xpath#predicates
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-7068919
doesn't seem to descend into <iframe> sections of the DOM
in FireFox 2. Is that correct?

Yes. The iframe document is not part of the parse tree of the
embedding document.
Can XPath be told to descend into an iframe subdocument?

No. XPath operates within the parse tree of a specific document:

,-<http://www.w3.org/TR/xpath#section-Introduction>
|
| [...]
| XPath models an XML document as a tree of nodes.
| There are different types of nodes, including
| element nodes, attribute nodes and text nodes.
| [...]
Or is it necessary to find all the <iframe> tags and recurse?

It is necessary to find all _`iframe' elements_ and use the respective
iframe document object or a descendant node object as XPath context
node:

// "DOM Level 0" [DOM0]
var iframes = window.frames;

for (var i = iframes && iframes.length; i--;)
{
// W3C DOM Level 2 Views [DOM2Views]
var d = iframes.document;
if (d)
{
// W3C DOM Level 3 XPath [DOM2XPath]
var allhrefs = d.evaluate('//a[@href]', d, ...);

// ...
}
}

or

// W3C DOM Level 2 && 3 Core [DOMCore]
var iframes = document.getElementsByTagName("iframe");

for (var i = iframes && iframes.length; i--;)
{
// W3C DOM Level 2 HTML [DOM2HTML]
var d = iframes.contentDocument;

// ...
}

References:

[DOM0] http://www.w3.org/TR/DOM-Level-2-HTML/glossary.html
http://developer.mozilla.org/en/docs/DOM:window.frames
http://msdn2.microsoft.com/en-us/library/ms537459(VS.85).aspx
[DOMCore] http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1938918D
[DOM2HTML] http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-50708718
[DOM2Views] http://www.w3.org/TR/DOM-Level-2-Views/views.html#Views-AbstractView
[DOM3XPath] http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-evaluate


HTH

PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
It should also be noted that the //a[@href] snapshot and the
`document.links' collection are not equivalent. Firstly,
document.links includes also `area' elements ('//area[@href]', and
eventually '//*[local-name() = "A" or (local-name() = "AREA" and
@href)]' -- use lowercase for XHTML, XPath 2.0 is apparently not
supported yet -- [...]

'//*[local-name() = "A" and @href) or local-name() = "AREA"]'


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top