DOM/XPath Generator: Difference between revisions

m
GPHemsley moved page DOM:XPath Generator to DOM/XPath Generator without leaving a redirect
m (GPHemsley moved page DOM:XPath Generator to DOM/XPath Generator without leaving a redirect)
 
(20 intermediate revisions by 6 users not shown)
Line 14: Line 14:


== Potential Use Cases ==
== Potential Use Cases ==
Currently, mozilla.org code uses similar functionality in at least two places:
Currently, mozilla.org code uses similar functionality in at least one:


http://lxr.mozilla.org/seamonkey/source/content/base/src/nsContentUtils.cpp#1567
http://lxr.mozilla.org/seamonkey/source/content/base/src/nsContentUtils.cpp#1567
GenerateStateKey
GenerateStateKey
http://lxr.mozilla.org/seamonkey/source/xpfe/browser/resources/content/viewPartialSource.js#215
View Selection Source


Other sources:
Other sources:
Line 29: Line 26:
(From WeirdAl's weblog)
(From WeirdAl's weblog)
http://xpath.alephzarro.com/index
http://xpath.alephzarro.com/index
XPather, a current implementation as an extension
XPather, adds XPath support to Firefox and DOM Inspector


(From WeirdAl's weblog)
(From WeirdAl's weblog)
Line 42: Line 39:
namespace resolver (assuming that we need to handle XML to be future proof)." -- Alex Hecht
namespace resolver (assuming that we need to handle XML to be future proof)." -- Alex Hecht


[http://verbosio.mozdev.org Verbosio] would be able to translate a XPath for a document it's editing into a XPath for a XUL tree (a la DOM Inspector) representing the document's structure.  This would be through simple text replaces.  Thus, a node found in the master document would easily translate to a XUL tree item.
[http://verbosio.mozdev.org Verbosio] would be able to translate a XPath for a document it's editing into a XPath for a XUL tree (a la DOM Inspector) representing the document's structure.  This would be through simple text replacements.  Thus, a node found in the master document would easily translate to a XUL tree item.
 
Shane Caraveo at ActiveState is working to develop a XUL unit test extension that would work in a similar fashion to Selenium and Selenium Recorder.  This consists of recording DOM events, and saving an xpath to the event target so the target can found and used to replay an event.  Exploratory code is in [https://bugzilla.mozilla.org/show_bug.cgi?id=323938 bug 323938].


Developers would no longer have to guess a working XPath to a node for future reference.  This would reduce development time.
Developers would no longer have to guess a working XPath to a node for future reference.  This would reduce development time.
Line 49: Line 48:


<pre>
<pre>
#include "domstubs.idl"
#include "domstubs.idl"
#include "nsIDOMXPathNSResolver.idl"


[scriptable, uuid(ab50beb3-4049-4299-92ea-4dea4609a1e1)]
[scriptable, uuid(341d8cbe-bcb3-4d9a-a5a6-dd4ef72a402d)]
interface nsIXPathGenerator : nsISupports {
interface nsIXPathGenerator : nsISupports {
   /* A collection of bitwise flags which modify behavior.
   /* A collection of bitwise flags which modify behavior.
Line 58: Line 57:
   */
   */


   /**
   // Ignore ID-type attribute nodes on elements and continue to the document or context node.
  * Ignore ID-type attribute nodes on elements and continue to the document node.
  */
   const unsigned long GO_TO_DOCUMENT_ROOT          = 0x00000001;
   const unsigned long GO_TO_DOCUMENT_ROOT          = 0x00000001;
  // Return expression containing a single step that uses the descendant axis.
  const unsigned long USE_DESCENDANT_AXIS          = 0x00000002;


   /**
   /**
   * Flags which modify the parameters used to generate the xpath string.
   * Flags which modify the parameters used to generate the xpath string.
   */
   */
   unsigned long attribute searchFlags;
   attribute unsigned long searchFlags;


   /**
   /**
Line 96: Line 96:
   * Namespace resolver corresponding to all generated xpaths.
   * Namespace resolver corresponding to all generated xpaths.
   */
   */
   readonly nsIDOMXPathNSResolver resolver;
   readonly attribute nsIDOMXPathNSResolver resolver;


   /**
   /**
   * Generate the xpath as a string.
  * Add a namespace URI and prefix to the namespace resolver.
  *
  * @param namespaceURI    The namespace URI of the namespace.
  * @param prefix          The prefix of the namespace.
  */
  void addNamespace(in DOMString namespaceURI,
                    in DOMString prefix);
 
  /**
   * Generate a xpath as a string.
   *
   *
   * @param targetNode  The node our xpath ends at.
   * @param targetNode  The node our xpath ends at.
Line 106: Line 115:
   * @return DOMString XPath from the context node to the target node.
   * @return DOMString XPath from the context node to the target node.
   */
   */
   DOMString generateXPath(in nsIDOMNode targetNode
   DOMString generateXPath(in nsIDOMNode targetNode,
                           in nsIDOMNode contextNode);
                           in nsIDOMNode contextNode);
}
 
  /**
  * Generate a xpointer as a string.
  *
  * @param targetNode  The node our xpath ends at.
  * @param contextNode The node our xpath starts from.  If null, use targetNode's owner document.
  *
  * @return DOMString XPointer from the context node to the target node.
  */
  DOMString generateXPointer(in nsIDOMNode targetNode,
                            in nsIDOMNode contextNode);
};
</pre>
</pre>


== API Notes ==
The resolver of each XPathGenerator object would not be a standard document.createNSResolver(node) object.  Instead, the XPathGenerator object will create and maintain the resolver independently.  This will allow the generator to add additional namespaces transparently and harmlessly as needed.
The resolver of each XPathGenerator object would not be a standard document.createNSResolver(node) object.  Instead, the XPathGenerator object will create and maintain the resolver independently.  This will allow the generator to add additional namespaces transparently and harmlessly as needed.


Line 118: Line 139:


Implementation: [https://bugzilla.mozilla.org/show_bug.cgi?id=319768 Bug 319768]
Implementation: [https://bugzilla.mozilla.org/show_bug.cgi?id=319768 Bug 319768]
I think we should add a generateXPointer function too, since it's trivial to implement once we have implemented generateXPath and the resolver. You just need to serialize the namespace mappings from the resolver following the [http://www.w3.org/TR/xptr-xmlns/ XPointer xmlns() scheme] and use the [http://www.w3.org/TR/xptr-xpointer/ XPointer xpointer() scheme] for the result of generateXPath. -- Peter Van der Beken
It would probably be a good idea to include a addNamespace(namespaceURI, prefix) method to the IDL, to point into the resolver's namespace map. -- Alex Vincent
I'd like the ability for a caller to tell the generator that it should identify the starting node by the content it contains when calling generateXPath.  We could do that by adding a searchFlag called something like IDENTIFY_START_BY_CONTENT which triggers the behavior.
When I say "identify the starting node by the content it contains", I mean use the contains() method or the like to filter nodes with the same tag name.  For example, for an XPath expression starting at a DIV node whose content is "foo", the beginning of the XPath expression should be DIV[contains(.,"foo")] or some other XPath construct which identifies the node by the content it contains. -- Myk Melez
== XPath: Content Boundaries ==
(non-normative)
Mozilla's XPath implementation doesn't currently support crossing boundaries between framed content and the container frame element, or between real content and its anonymous children.  Our XPath and XPathGenerator can be reasonably expected to support this in the future, so now's the best time to come up with a function syntax for doing this.
Suggested new XPath functions:
* From element in framed document to the container iframe:
** XPath 1: "frameElement(.)" (Alex Vincent)
** XPath 2: "./frameElement()" (Alex Vincent)
* From container iframe to element in the framed document:
** XPath 1: "contentDocument(.)" (Alex Vincent)
** XPath 2: "./contentDocument()" (Alex Vincent)
* From anonymous content to the XBL-bound parent:
** XPath 1: "bindingParent(.)" (Alex Vincent)
** XPath 2: "./bindingParent()" (Alex Vincent)
* From XBL-bound parent to first anonymous child:
** XPath 1: "anonymousChild(.)[1]" (Alex Vincent)
** XPath 2: "./anonymousChild()[1]" (Alex Vincent)
<pre><sicking> we do not want a different syntax in xpath2
<sicking> at least i think not. at the very least we do not want to commit to it</pre>
Whatever you think is a better syntax, please suggest it here.  All suggestions are welcome.
Implementation: [https://bugzilla.mozilla.org/show_bug.cgi?id=326745 bug 326745]
canmove, Confirmed users, Bureaucrats and Sysops emeriti
960

edits