class DOMXPath in Feeds XPath Parser 8
Wraps DOMXPath providing enhanced debugging and special namespace handling.
Hierarchy
Expanded class hierarchy of DOMXPath
File
- lib/
Drupal/ feeds_xpathparser/ DOMXPath.php, line 13 - Contains \Druapl\feeds_xpathparser\DOMXPath.
Namespace
Drupal\feeds_xpathparserView source
class DOMXPath extends \DOMXPath {
/**
* The DOMDocument to parse.
*
* @var \DOMDocument
*/
protected $doc;
/**
* Configuration array.
*
* @var array
*/
protected $config = array();
/**
* Modified query cache.
*
* @var arrray
*/
protected $modifiedQueries = array();
/**
* The namespaces in the document.
*
* @var arrray
*/
protected $namepsaces = array();
/**
* The most recent error from parsing.
*
* @var \stdClass
*/
protected $error;
/**
* Constructs a DOMXPath object.
*
* @param \DOMDocument $doc
* The DOMDocument that we're operating on.
*/
public function __construct(\DOMDocument $doc) {
$simple = simplexml_import_dom($doc);
// An empty DOMDocument will make $simple NULL.
if ($simple !== NULL) {
$this->namespaces = $simple
->getNamespaces(TRUE);
}
$this->doc = $doc;
parent::__construct($doc);
}
/**
* Sets the extended configuration.
*
* @param array $config
* The config array.
*/
public function setConfig(array $config) {
$this->config = $config;
}
/**
* Renders our debug messages into a list.
*
* @param mixed $data
* The result of an XPath query. Either a scalar or a DOMNodeList.
* @param string $source
* The source key that produced this query.
*
* @todo Use theme_item_list().
*/
protected function debug($data, $source) {
$output = "{$source} : <ul>";
if ($data instanceof \DOMNodeList) {
foreach ($data as $node) {
$output .= '<li>' . check_plain($this->doc
->saveXML($node)) . '</li>';
}
}
else {
$output .= '<li>' . check_plain($data) . '</li>';
}
$output .= '</ul>';
drupal_set_message($output);
}
/**
* Executes an XPath query with namespace support.
*
* @param string $query
* An XPath query.
* @param string $source
* The source key for this query.
* @param \DOMNode $context
* (optional) The current context of the XPath query. Defaults to null.
*
* @return array
* An array containing the results of the query.
*/
public function namespacedQuery($query, $source, \DOMNode $context = NULL) {
$this
->addDefaultNamespace($query);
$results = $this
->executeQuery($query, $context);
if (in_array($source, $this->config['debug'])) {
$this
->debug($results, $source);
}
if (is_object($this->error) && $this->config['errors']) {
if ($this->error->level == LIBXML_ERR_ERROR) {
drupal_set_message(t('There was an error during the XPath query: %query.<br />Libxml returned the message: %message, with the error code: %code.', array(
'%query' => $query,
'%message' => trim($this->error->message),
'%code' => $this->error->code,
)), 'error', FALSE);
}
elseif ($this->error->level == LIBXML_ERR_WARNING) {
drupal_set_message(t('There was an error during the XPath query: %query.<br />Libxml returned the message: %message, with the error code: %code.', array(
'%query' => $query,
'%message' => trim($this->error->message),
'%code' => $this->error->code,
)), 'warning', FALSE);
}
}
// DOMXPath::evaluate() and DOMXPath::query() will return FALSE on error or
// if the value is FALSE. We check error result and return NULL in case
// of error.
if (is_object($this->error) && $this->error->level == LIBXML_ERR_ERROR) {
return NULL;
}
return $results;
}
/**
* Normalizes XPath queries, adding the default namespace.
*
* @param string $query
* An XPath query string
*/
protected function addDefaultNamespace(&$query) {
foreach ($this->namespaces as $prefix => $namespace) {
if ($prefix === '') {
$this
->registerNamespace('__default__', $namespace);
// Replace all the elements without prefix by the default prefix.
if (!isset($this->modifiedQueries[$query])) {
$parser = new XPathQueryParser($query);
$mod_query = $parser
->getQuery();
$this->modifiedQueries[$query] = $mod_query;
$query = $mod_query;
}
else {
$query = $this->modifiedQueries[$query];
}
}
else {
$this
->registerNamespace($prefix, $namespace);
}
}
}
/**
* Performs a XPath query.
*
* Here we set libxml_use_internal_errors() to true because depending on the
* libxml version, $xml->xpath() might return false or an empty array() when
* a query doesn't match.
*
* @param string $query
* The XPath query string.
* @param \DOMNode $context
* (optional) A context object. Defaults to NULL.
*
* @return mixed
* The result of the XPath query.
*/
protected function executeQuery($query, \DOMNode $context = NULL) {
$use_errors = libxml_use_internal_errors(TRUE);
// Perfom XPath query.
// So, grrr. FALSE is returned when there is an error. However, FALSE is
// also a valid return value from DOMXPath::evaluate(). Ex: '1 = 2'
if ($context) {
$results = $this
->evaluate($query, $context);
}
else {
$results = $this
->query($query);
}
$this->error = libxml_get_last_error();
libxml_clear_errors();
libxml_use_internal_errors($use_errors);
return $results;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DOMXPath:: |
protected | property |
Configuration array. Overrides DOMXPath:: |
1 |
DOMXPath:: |
protected | property |
The DOMDocument to parse. Overrides DOMXPath:: |
1 |
DOMXPath:: |
protected | property |
The most recent error from parsing. Overrides DOMXPath:: |
1 |
DOMXPath:: |
protected | property |
Modified query cache. Overrides DOMXPath:: |
1 |
DOMXPath:: |
protected | property |
The namespaces in the document. Overrides DOMXPath:: |
1 |
DOMXPath:: |
protected | function |
Normalizes XPath queries, adding the default namespace. Overrides DOMXPath:: |
1 |
DOMXPath:: |
protected | function |
Renders our debug messages into a list. Overrides DOMXPath:: |
1 |
DOMXPath:: |
protected | function |
Performs a XPath query. Overrides DOMXPath:: |
1 |
DOMXPath:: |
public | function |
Executes an XPath query with namespace support. Overrides DOMXPath:: |
1 |
DOMXPath:: |
public | function |
Sets the extended configuration. Overrides DOMXPath:: |
1 |
DOMXPath:: |
public | function |
Constructs a DOMXPath object. Overrides DOMXPath:: |
1 |