XPath Helper

From GreaseSpot Wiki
Jump to navigationJump to search

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.