123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- <?php
- /**
- * @file
- * Provides a custom version of DOMXPath for use with feeds_xpathparser.
- */
- class FeedsXPathParserDOMXPath extends DOMXPath {
- protected $config = array();
- protected $modifiedQueries = array();
- public function __construct(DOMDocument $doc) {
- $this->namespaces = array();
- $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);
- }
- public function setConfig(array $config) {
- $this->config = $config;
- }
- 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 $xpath
- * The DOMXPath object.
- *
- * @param $query
- * An XPath query.
- *
- * @return array
- * An array containing the results of the query.
- */
- public function namespacedQuery($query, $context, $source) {
- $this->addDefaultNamespace($query);
- $results = $this->_query($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 $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 FeedsXPathParserQueryParser($query);
- $modQuery = $parser->getQuery();
- $this->modifiedQueries[$query] = $modQuery;
- $query = $modQuery;
- }
- else {
- $query = $this->modifiedQueries[$query];
- }
- }
- else {
- $this->registerNamespace($prefix, $namespace);
- }
- }
- }
- /**
- * 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.
- */
- protected function _query($query, $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;
- }
- }
|