You are here

class XPathQueryParser in Feeds XPath Parser 8

Pseudo-parser of XPath queries.

When an XML document has a default namespace this gets called so that adding the __default__ namepace where appropriate.

Aren't we nice?

@todo Cleanup.

Hierarchy

Expanded class hierarchy of XPathQueryParser

1 file declares its use of XPathQueryParser
XPathQueryParserTest.php in lib/Drupal/feeds_xpathparser/Tests/XPathQueryParserTest.php
Contains Drupal\feeds_xpathparser\Tests\XPathQueryParserTest.

File

lib/Drupal/feeds_xpathparser/XPathQueryParser.php, line 26
Contains \Drupal\feeds_xpathparser\XPathQueryParser.

Namespace

Drupal\feeds_xpathparser
View source
class XPathQueryParser {

  /**
   * Characters that represent word boundaries.
   *
   * @var array
   */
  protected $wordBoundaries = array(
    '[',
    ']',
    '=',
    '(',
    ')',
    '.',
    '<',
    '>',
    '*',
    '!',
    '|',
    '/',
    ',',
    ' ',
    ':',
  );

  /**
   * The XPath query to modify.
   *
   * @var string
   */
  protected $query;

  /**
   * The parsing index.
   *
   * @var int
   */
  protected $i;
  protected $inQuotes = FALSE;
  protected $quoteChar = '';
  protected $word = '';
  protected $output = '';
  protected $prevBoundary = '';
  protected $axis = '';
  protected $skipNextWord = FALSE;

  /**
   * Constructs a XPathQueryParser object.
   *
   * @param string $query
   *   The input XPath query string.
   */
  public function __construct($query) {

    // Normalize space.
    $this->query = preg_replace('/\\s+\\(\\s*/', '(', $query);
  }

  /**
   * Returns the modified XPath query.
   *
   * @return string
   *   A modified XPath query.
   */
  public function getQuery() {
    $this
      ->start();
    return $this->output;
  }

  /**
   * Begin parsing.
   */
  protected function start() {
    for ($i = 0; $i < drupal_strlen($this->query); $i++) {
      $this->i = $i;
      $c = drupal_substr($this->query, $i, 1);
      if ($c === '"' || $c === "'") {
        $this
          ->handleQuote($c);
        continue;
      }
      if ($this->inQuotes) {
        $this->word .= $c;
        continue;
      }
      if (in_array($c, $this->wordBoundaries)) {
        $this
          ->handleWordBoundary($c);
      }
      else {
        $this->word .= $c;
      }
    }
    $this
      ->handleWord();
  }

  /**
   * Handles quote pairs.
   */
  protected function handleQuote($c) {
    if ($this->inQuotes && $c === $this->quoteChar) {
      $this->inQuotes = FALSE;
      $this->word .= $c;
      $this->output .= $this->word;
      $this->word = '';
    }
    elseif (!$this->inQuotes) {
      $this->inQuotes = TRUE;
      $this
        ->handleWord();
      $this->word = $c;
      $this->quoteChar = $c;
    }
    else {
      $this->word .= $c;
    }
  }

  /**
   * Handles word boundaries.
   *
   * @param string $c
   *   One character.
   */
  protected function handleWordBoundary($c) {
    if (in_array($this->word, array(
      'div',
      'or',
      'and',
      'mod',
    )) && $this->prevBoundary === ' ' && $c === ' ') {
      $this->output .= $this->word;
    }
    else {
      $this
        ->handleWord($c);
    }
    $this->output .= $c;
    $this->word = '';
    $this->prevBoundary = $c;
  }

  /**
   * Handles one word.
   *
   * @param string $c
   *   (optional) A single character. Defaults to an empty string.
   */
  protected function handleWord($c = '') {
    if ($this->word === '') {
      return;
    }
    if ($c === ':' && drupal_substr($this->query, $this->i + 1, 1) === ':') {
      $this->axis = $this->word;
    }
    if ($c === ':' && drupal_substr($this->query, $this->i - 1, 1) !== ':' && drupal_substr($this->query, $this->i + 1, 1) !== ':') {
      $this->output .= $this->word;
      $this->skipNextWord = TRUE;
      return;
    }
    if ($this->skipNextWord) {
      $this->skipNextWord = FALSE;
      $this->output .= $this->word;
      return;
    }
    if (is_numeric($this->word) || $this->axis === 'attribute' || strpos($this->word, '@') === 0 || $c === '(' || $c === ':') {
      $this->output .= $this->word;
      return;
    }

    // Apply namespace.
    $this->output .= '__default__:' . $this->word;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
XPathQueryParser::$axis protected property
XPathQueryParser::$i protected property The parsing index.
XPathQueryParser::$inQuotes protected property
XPathQueryParser::$output protected property
XPathQueryParser::$prevBoundary protected property
XPathQueryParser::$query protected property The XPath query to modify.
XPathQueryParser::$quoteChar protected property
XPathQueryParser::$skipNextWord protected property
XPathQueryParser::$word protected property
XPathQueryParser::$wordBoundaries protected property Characters that represent word boundaries.
XPathQueryParser::getQuery public function Returns the modified XPath query.
XPathQueryParser::handleQuote protected function Handles quote pairs.
XPathQueryParser::handleWord protected function Handles one word.
XPathQueryParser::handleWordBoundary protected function Handles word boundaries.
XPathQueryParser::start protected function Begin parsing.
XPathQueryParser::__construct public function Constructs a XPathQueryParser object.