XPath Helper

From GreaseSpot Wiki
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Run a particular XPath expression p against the context node context (or the document, if not provided) with this overloaded XPath helper.

Returns the results as an array, unless a value of false is passed in.

function $x() {
  var x='';
  var node=document;
  var type=0;
  var fix=true;
  var i=0;
  var cur;
    
  function toArray(xp) {
    var final=[], next;
    while (next=xp.iterateNext()) {
      final.push(next);
    }
    return final;
  }
  
  while (cur=arguments[i++]) {
    switch (typeof cur) {
      case "string": x+=(x=='') ? cur : " | " + cur; continue;
      case "number": type=cur; continue;
      case "object": node=cur; continue;
      case "boolean": fix=cur; continue;
    }
  }
  
  if (fix) {
    if (type==6) type=4;
    if (type==7) type=5;
  }
  
  // selection mistake helper
  if (!/^\//.test(x)) x="//"+x;

  // context mistake helper
  if (node!=document && !/^\./.test(x)) x="."+x;

  var result=document.evaluate(x, node, null, type, null);
  if (fix) {
    // automatically return special type
    switch (type) {
      case 1: return result.numberValue;
      case 2: return result.stringValue;
      case 3: return result.booleanValue;
      case 8:
      case 9: return result.singleNodeValue;
    }
  }

  return fix ? toArray(result) : result;
}

Example usage:

var paragraphs = $x("//p", XPathResult.ORDERED_NODE_SNAPSHOT_TYPE), i=1;
paragraphs.forEach(function(paragraph) {  // Loop over every paragraph
  paragraph.innerHTML = "This is paragraph #"+(i++);
});
var content=$x("//div[@class='center story']", XPathResult.FIRST_ORDERED_NODE_TYPE);
content.innerHTML="time to eat dinner!";

Note: When you specify a context node, you NORMALLY need to use a relative XPath expression. However, this function takes care of that technicality.