docs: function XPathEngine() {
  // public
      this.doc = null;
  
      /**
       * Returns whether the current runtime environment supports the use of this
       * engine. Needs override.
       */
      this.isAvailable = function() { return false; };
  
      /**
       * Sets the document to be used for evaluation. Always returns the current
       * engine object so as to be chainable.
       */
      this.setDocument = function(newDocument) {
          this.doc = newDocument;
          return this;
      };
  
      /**
       * Returns a possibly-empty list of nodes. Needs override.
       */
      this.selectNodes = function(xpath, contextNode, namespaceResolver) {
          return [];
      };
  
      /**
       * Returns a single node, or null if no nodes were selected. This default
       * implementation simply returns the first result of selectNodes(), or
       * null.
       */
      this.selectSingleNode = function(xpath, contextNode, namespaceResolver) {
          var nodes = this.selectNodes(xpath, contextNode, namespaceResolver);
          return (nodes.length > 0 ? nodes[0] : null);
      };
  
      /**
       * Returns the number of matching nodes. This default implementation simply
       * returns the length of the result of selectNodes(), which should be
       * adequate for most sub-implementations.
       */
      this.countNodes = function(xpath, contextNode, namespaceResolver) {
          return this.selectNodes(xpath, contextNode, namespaceResolver).length;
      };
  
      /**
       * An optimization; likely to be a no-op for many implementations. Always
       * returns the current engine object so as to be chainable.
       */
      this.setIgnoreAttributesWithoutValue = function(ignore) { return this; };
  }