1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file
|
5
|
* Pseudo-parser of XPath queries. When an XML document has a default
|
6
|
* namespace this gets called so that adding the __default__ namepace where
|
7
|
* appropriate. Aren't we nice?
|
8
|
*
|
9
|
* @todo
|
10
|
* Cleanup.
|
11
|
* @param $query
|
12
|
* An XPath query string.
|
13
|
* @return string
|
14
|
* An XPath query string with the __default__ namespace added.
|
15
|
*/
|
16
|
class FeedsXPathParserQueryParser {
|
17
|
function __construct($query) {
|
18
|
$this->query = preg_replace('/\s+\(\s*/', '(', $query);
|
19
|
|
20
|
$this->word_boundaries = array(
|
21
|
'[', ']', '=', '(', ')', '.', '<', '>', '*', '!', '|', '/', ',', ' ', ':',
|
22
|
);
|
23
|
$this->in_quotes = FALSE;
|
24
|
$this->quote_char = '';
|
25
|
$this->word = '';
|
26
|
$this->output = '';
|
27
|
$this->prev_boundary = '';
|
28
|
$this->axis = '';
|
29
|
$this->skip_next_word = FALSE;
|
30
|
$this->start();
|
31
|
}
|
32
|
|
33
|
function start() {
|
34
|
for ($i=0; $i < drupal_strlen($this->query); $i++) {
|
35
|
$this->i = $i;
|
36
|
$c = drupal_substr($this->query, $i, 1);
|
37
|
|
38
|
if ($c == '"' || $c == "'") {
|
39
|
$this->handle_quote($c);
|
40
|
continue;
|
41
|
}
|
42
|
if ($this->in_quotes) {
|
43
|
$this->word .= $c;
|
44
|
continue;
|
45
|
}
|
46
|
|
47
|
if (in_array($c, $this->word_boundaries)) {
|
48
|
$this->handle_word_boundary($c);
|
49
|
}
|
50
|
else {
|
51
|
$this->word .= $c;
|
52
|
}
|
53
|
}
|
54
|
$this->handle_word();
|
55
|
}
|
56
|
|
57
|
function handle_quote($c) {
|
58
|
if ($this->in_quotes && $c == $this->quote_char) {
|
59
|
$this->in_quotes = FALSE;
|
60
|
$this->word .= $c;
|
61
|
$this->output .= $this->word;
|
62
|
$this->word = '';
|
63
|
}
|
64
|
elseif (!$this->in_quotes) {
|
65
|
$this->in_quotes = TRUE;
|
66
|
$this->handle_word();
|
67
|
$this->word = $c;
|
68
|
$this->quote_char = $c;
|
69
|
}
|
70
|
else {
|
71
|
$this->word .= $c;
|
72
|
}
|
73
|
}
|
74
|
|
75
|
function handle_word_boundary($c) {
|
76
|
if (in_array($this->word, array('div', 'or', 'and', 'mod')) &&
|
77
|
$this->prev_boundary == ' ' && $c == ' ') {
|
78
|
$this->output .= $this->word;
|
79
|
}
|
80
|
else {
|
81
|
$this->handle_word($c);
|
82
|
}
|
83
|
$this->output .= $c;
|
84
|
$this->word = '';
|
85
|
$this->prev_boundary = $c;
|
86
|
}
|
87
|
|
88
|
function handle_word($c='') {
|
89
|
if ($this->word == '') {
|
90
|
return;
|
91
|
}
|
92
|
|
93
|
if ($c == ':' && drupal_substr($this->query, $this->i + 1, 1) == ':') {
|
94
|
$this->axis = $this->word;
|
95
|
}
|
96
|
|
97
|
if ($c == ':' && drupal_substr($this->query, $this->i - 1, 1) != ':' &&
|
98
|
drupal_substr($this->query, $this->i + 1, 1) != ':') {
|
99
|
$this->output .= $this->word;
|
100
|
$this->skip_next_word = TRUE;
|
101
|
return;
|
102
|
}
|
103
|
if ($this->skip_next_word) {
|
104
|
$this->skip_next_word = FALSE;
|
105
|
$this->output .= $this->word;
|
106
|
return;
|
107
|
}
|
108
|
if (is_numeric($this->word) ||
|
109
|
$this->axis == 'attribute' ||
|
110
|
strpos($this->word, '@') === 0 ||
|
111
|
$c == '(' ||
|
112
|
$c == ':') {
|
113
|
$this->output .= $this->word;
|
114
|
return;
|
115
|
}
|
116
|
$this->output .= '__default__:' . $this->word;
|
117
|
}
|
118
|
|
119
|
function getQuery() {
|
120
|
return $this->output;
|
121
|
}
|
122
|
}
|