Hoa central
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
Hoa\Xml\CssToXPath Class Reference
Inheritance diagram for Hoa\Xml\CssToXPath:

Public Member Functions

 __construct ()
 
 getResult ()
 
 getXPath ()
 
 setDefaultNamespacePrefix ($prefix)
 
 getDefaultNamespacePrefix ()
 
- Public Member Functions inherited from Hoa\Compiler\Ll1
 __construct (Array $skip, Array $tokens, Array $states, Array $terminal, Array $transitions, Array $actions, Array $names=[])
 
 compile ($in)
 
 getResult ()
 
 setInitialLine ($line)
 
 setSkip (Array $skip)
 
 setTokens (Array $tokens)
 
 setStates (Array $states)
 
 setTerminal (Array $terminal)
 
 setTransitions (Array $transitions)
 
 setActions (Array $actions)
 
 setNames (Array $names)
 
 getInitialLine ()
 
 getSkip ()
 
 getTokens ()
 
 getStates ()
 
 getTerminal ()
 
 getTransitions ()
 
 getActions ()
 
 getNames ()
 
 __toString ()
 

Protected Member Functions

 flush ($element, $selector, $pseudo)
 
 consume ($action)
 
 pre (&$in)
 
 end ()
 
 callPseudoClass ($element, $pseudoClass)
 
 callPseudoElement ($element, $pseudoElement)
 
 callPseudoClassFunction ($element, $function)
 
 callPseudoElementFunction ($element, $function)
 
- Protected Member Functions inherited from Hoa\Compiler\Ll1
 consume ($action)
 
 pre (&$in)
 
 end ()
 

Protected Attributes

 $_root = null
 
 $_current = null
 
 $_prefix = null
 
- Protected Attributes inherited from Hoa\Compiler\Ll1
 $_initialLine = 0
 
 $_skip = []
 
 $_tokens = []
 
 $_states = []
 
 $_terminal = []
 
 $_transitions = []
 
 $_actions = []
 
 $_names = []
 
 $buffers = []
 
 $line = 0
 
 $column = 0
 

Additional Inherited Members

- Static Public Member Functions inherited from Hoa\Compiler\Ll1
static enableCache ()
 
static disableCache ()
 
- Static Protected Attributes inherited from Hoa\Compiler\Ll1
static $_cache = []
 
static $_cacheEnabled = true
 

Detailed Description

Class .

Compiler CSS3 to XPath2.0.

Definition at line 49 of file CssToXPath.php.

Constructor & Destructor Documentation

Hoa\Xml\CssToXPath::__construct ( )

Set up the compiler.

Returns
void

Definition at line 79 of file CssToXPath.php.

80  {
81 
82  // http://w3.org/TR/css3-selectors/#w3cselgrammar
83  parent::__construct(
84  // Skip.
85  [
86  '#\/\*[^*]*\*+([^/*][^*]*\*+)*\/' // /* … */
87  ],
88 
89  // Tokens.
90  [
91  // 1. Selectors group.
92  [
93  '#,\s*' // ,
94  ],
95 
96  // 2. Selector.
97  [
98  '#\s*\+\s*', // +
99  '#\s*>\s*', // >
100  '#\s*~\s*', // ~
101  '#\s* \s*' // s
102  ],
103 
104  // 3. Simple selector sequence.
105  [
106  '#(\*|\w+)\|', // tu (type selector or universal)
107  '#\w+', // w
108  '|', // |
109  '#\*' // *
110  ],
111 
112  // 4. Hacpn.
113  [
114  '[', // [
115  ']', // ]
116  '#(\*|\w+)\|(?!=)', // tu (type selector or universal)
117  '#[\w\-]+\(((\+|\-|\d+\w+|\d+|\'\w+\'|\w+)\s*)+\)', // f
118  '#[\w\-]+', // w
119  '#\^=', // ^
120  '#\$=', // $
121  '#~=', // ~
122  '#\*=', // *
123  '#\|=', // |=
124  '=', // =
125  '#\|', // |
126  '#(\'|").*?(?<!\\\)\2', // 's
127  '##\w+', // # (hash)
128  '#\.\w+', // . (class)
129  ':' // :
130  ]
131  ],
132 
133  // States.
134  [
135  // 1. Selectors group.
136  [
137  __, // error
138  'GO' // start
139  ],
140 
141  // 2. Selector.
142  [
143  __, // error
144  'GO' // start
145  ],
146 
147  // 3. Simple selector sequence.
148  [
149  __, // error
150  'GO', // start
151  'TU', // start type selector or universal
152  'OK' // terminal
153  ],
154 
155  // 4. Hacpn.
156  [
157  __, // error
158  'GO', // start
159  'OB', // open bracket: [
160  'NS', // namespace prefix
161  'ID', // identifier
162  'OP', // operator
163  'VA', // value
164  'PC', // pseudo-class (:)
165  'PE', // pseudo-element (::)
166  'OK' // terminal
167  ]
168  ],
169 
170  // Terminal.
171  [
172  // 1. Selectors group.
173  ['GO'],
174 
175  // 2. Selector.
176  ['GO'],
177 
178  // 3. Simple selector sequence.
179  ['GO', 'OK'],
180 
181  // 4. Hacpn.
182  ['GO', 'OK']
183  ],
184 
185  // Transitions.
186  [
187  // 1. Selectors group.
188  [
189  /* ,
190  /* __ */ [ __ ],
191  /* GO */ ['GO']
192  ],
193 
194  // 2. Selector.
195  [
196  /* + > ~ s
197  /* __ */ [ __, __, __, __ ],
198  /* GO */ ['GO', 'GO', 'GO', 'GO']
199  ],
200 
201  // 3. Simple selector sequence.
202  [
203  /* tu w | *
204  /* __ */ [ __, __, __, __ ],
205  /* GO */ ['TU', 'OK', 'TU', 'OK'],
206  /* TU */ [ __, 'OK', __, 'OK'],
207  /* OK */ [ __, __, __, __ ]
208  ],
209 
210  // 4. Hacpn.
211  [
212  /* [ ] tu f w ^ $ ~ * |= = | 's # . :
213  /* __ */ [ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __ ],
214  /* GO */ ['OB', __, __, __, __, __, __, __, __, __, __, __, __, 'OK', 'OK', 'PC'],
215  /* OB */ [ __, __, 'NS', __, 'ID', __, __, __, __, __, __, 'NS', __, __, __, __ ],
216  /* NS */ [ __, __, __, __, 'ID', __, __, __, __, __, __, __, __, __, __, __ ],
217  /* ID */ [ __, 'OK', __, __, __, 'OP', 'OP', 'OP', 'OP', 'OP', 'OP', __, __, __, __, __ ],
218  /* OP */ [ __, __, __, __, 'VA', __, __, __, __, __, __, __, 'VA', __, __, __ ],
219  /* VA */ [ __, 'OK', __, __, __, __, __, __, __, __, __, __, __, __, __, __ ],
220  /* PC */ [ __, __, __, 'OK', 'OK', __, __, __, __, __, __, __, __, __, __, 'PE'],
221  /* PE */ [ __, __, __, 'OK', 'OK', __, __, __, __, __, __, __, __, __, __, __ ],
222  /* OK */ [ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __ ]
223  ]
224  ],
225 
226  // Actions.
227  [
228  // 1. Selectors group.
229  [
230  /* ,
231  /* __ */ [ 0 ],
232  /* GO */ ['2,,']
233  ],
234 
235  // 2. Selector.
236  [
237  /* + > ~ s
238  /* __ */ [ 0, 0, 0, 0 ],
239  /* GO */ ['3,+', '3,>', '3,~', '3, ']
240  ],
241 
242  // 3. Simple selector sequence.
243  [
244  /* tu w | *
245  /* __ */ [ 0, 0, 0, 0 ],
246  /* GO */ [ '4,-1', '4,-1', '4,-1', '4,-1'],
247  /* TU */ [ 0, -1, 0, -1 ],
248  /* OK */ [ 0, 4, 0, 4 ]
249  ],
250 
251  // 4. Hacpn.
252  [
253  /* [ ] tu f w ^ $ ~ * |= = | 's # . :
254  /* __ */ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
255  /* GO */ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '#', '.', 0],
256  /* OB */ [0, 0, -3, 0, -3, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0],
257  /* NS */ [0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
258  /* ID */ [0, ']', 0, 0, 0, '^', '$', '~=', '*', '|', '=', 0, 0, 0, 0, 0],
259  /* OP */ [0, 0, 0, 0, 'v', 0, 0, 0, 0, 0, 0, 0, 'v', 0, 0, 0],
260  /* VA */ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
261  /* PC */ [0, 0, 0, ':f', ':', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
262  /* PE */ [0, 0, 0, '::f', '::', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
263  /* OK */ [0, 4, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]
264  ]
265  ]
266  );
267  }

Member Function Documentation

Hoa\Xml\CssToXPath::callPseudoClass (   $element,
  $pseudoClass 
)
protected

Call this method when a pseudo-class is unknown.

Parameters
string$elementElement.
string$pseudoClassPseudo-class.
Returns
string

Definition at line 736 of file CssToXPath.php.

737  {
738  throw new Compiler\Exception(
739  'The pseudo-class %s on the element %s is unknown.',
740  5,
741  [$pseudoClass, $element]
742  );
743  }

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::callPseudoClassFunction (   $element,
  $function 
)
protected

Call this method when a pseudo-class function is unknown.

Parameters
string$elementElement.
string$functionPseudo-class function.
Returns
string

Definition at line 768 of file CssToXPath.php.

769  {
770  throw new Compiler\Exception(
771  'The pseudo-class function %s on the element %s is unknown.',
772  7,
773  [$function, $element]
774  );
775  }

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::callPseudoElement (   $element,
  $pseudoElement 
)
protected

Call this method when a pseudo-element is unknown.

Parameters
string$elementElement.
string$pseudoElementPseudo-element.
Returns
string

Definition at line 752 of file CssToXPath.php.

753  {
754  throw new Compiler\Exception(
755  'The pseudo-element %s on the element %s is unknown.',
756  6,
757  [$pseudoElement, $element]
758  );
759  }

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::callPseudoElementFunction (   $element,
  $function 
)
protected

Call this method when a pseudo-element funcion is unknown.

Parameters
string$elementElement.
string$functionPseudo-element function.
Returns
string

Definition at line 784 of file CssToXPath.php.

785  {
786  throw new Compiler\Exception(
787  'The pseudo-element function %s on the element %s is unknown.',
788  8,
789  [$function, $element]
790  );
791  }

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::consume (   $action)
protected

Consume actions. Please, see the actions table definition to learn more.

Parameters
int$actionAction.
Returns
void

Definition at line 297 of file CssToXPath.php.

298  {
299  static $__element = '*';
300  static $_element = '*';
301  static $element = '*';
302  static $selector = [];
303  static $pseudo = null;
304  static $attribute = null;
305  static $operator = null;
306 
307  if (isset($this->buffers[0])) {
308  if (false !== strpos($this->buffers[0], '|')) {
309  $__element
310  = $_element
311  = $element
312  = str_replace('|', ':', $this->buffers[0]);
313  } else {
314  $__element = $this->buffers[0];
315 
316  if (null !== $p = $this->getDefaultNamespacePrefix()) {
317  $_element = $element = $p . ':' . $__element;
318  } else {
319  $_element = $element = $__element;
320  }
321  }
322 
323  unset($this->buffers[0]);
324  }
325 
326  switch ($action) {
327  case '__init':
328  $_element = '*';
329  $element = '*';
330  $selector = [];
331  $pseudo = null;
332  $attribute = null;
333  $operator = null;
334 
335  break;
336 
337  case '__flush':
338  $this->_current .= $this->flush($element, $selector, $pseudo);
339  $element = null;
340  $selector = [];
341  $pseudo = null;
342 
343  break;
344 
345  case '+':
346  $this->consume('__flush');
347  $this->_current .= '/following-sibling::*[1]/self::';
348 
349  break;
350 
351  case '>':
352  $this->consume('__flush');
353  $this->_current .= '/';
354 
355  break;
356 
357  case '~':
358  $this->consume('__flush');
359  $this->_current .= '/following-sibling::';
360 
361  break;
362 
363  case ' ':
364  $this->consume('__flush');
365  $this->_current .= '//';
366 
367  break;
368 
369  case '#':
370  $w = substr($this->buffers[-1], 1);
371  $selector[] = '@id = "' . $w . '"';
372 
373  break;
374 
375  case '.':
376  $w = substr($this->buffers[-1], 1);
377  $selector[] =
378  'contains(concat(' .
379  '" ", ' .
380  'normalize-space(@class), ' .
381  '" "' .
382  '), " ' . $w . ' ")';
383 
384  break;
385 
386  case '=':
387  case '^':
388  case '$':
389  case '~=':
390  case '*':
391  case '|':
392  $attribute = str_replace('|', ':', $this->buffers[1]);
393  unset($this->buffers[1]);
394  $operator = $action[0];
395 
396  break;
397 
398  case 'v':
399  $w =
400  '"' === $this->buffers[-1][0]
401  ? str_replace('\"', '"', substr($this->buffers[-1], 1, -1))
402  : str_replace('\\\'', '\'', substr($this->buffers[-1], 1, -1));
403 
404  switch ($operator) {
405  case '=':
406  $selector[] = '@' . $attribute . ' = "' . $w . '"';
407 
408  break;
409 
410  case '^':
411  $selector[] = 'starts-with(@' . $attribute . ', "' . $w . '")';
412 
413  break;
414 
415  case '$':
416  $length = strlen($w) - 1;
417  $selector[] =
418  'substring(@' . $attribute .
419  ', string-length(@' . $attribute . ') - ' .
420  $length . ') = "' . $w . '"';
421 
422  break;
423 
424  case '~':
425  $selector[] =
426  'contains(concat(" ", normalize-space(@' .
427  $attribute . '), " "), " ' . $w . ' ")';
428 
429  break;
430 
431  case '*':
432  $selector[] = 'contains(@' . $attribute . ', "' . $w . '")';
433 
434  break;
435 
436  case '|':
437  $selector[] =
438  '@' . $attribute . ' = "' . $w . '" or ' .
439  'starts-with(@' . $attribute . ', "' . $w .
440  '-")';
441 
442  break;
443  }
444 
445  $attribute = null;
446  $operator = null;
447 
448  break;
449 
450  case ']':
451  $w = str_replace('|', ':', $this->buffers[1]);
452  unset($this->buffers[1]);
453  $selector[] = '@' . $w;
454 
455  break;
456 
457  case ':':
458  $pc = $this->buffers[-1];
459 
460  switch ($pc) {
461  case 'root':
462  $this->_root = 'self::';
463 
464  break;
465 
466  case 'first-child':
467  if ('*' != $_element) {
468  $element = '*';
469  $selector[] = 'name() = "' . $__element . '"';
470  }
471  $selector[] = 'position() = 1';
472 
473  break;
474 
475  case 'last-child':
476  if ('*' != $_element) {
477  $element = '*';
478  $selector[] = 'name() = "' . $__element . '"';
479  }
480  $selector[] = 'position() = last()';
481 
482  break;
483 
484  case 'first-of-type':
485  if ('*' == $_element) {
486  throw new Compiler\Exception(
487  'Cannot have a :first-of-type without element.',
488  0
489  );
490  }
491 
492  $selector[] = 'position() = 1';
493 
494  break;
495 
496  case 'last-of-type':
497  if ('*' == $_element) {
498  throw new Compiler\Exception(
499  'Cannot have a :last-of-type without element.',
500  1
501  );
502  }
503 
504  $selector[] = 'position() = last()';
505 
506  break;
507 
508  case 'only-child':
509  if ('*' != $_element) {
510  $element = '*';
511  $selector[] = 'name() = "' . $_element . '"';
512  }
513  $selector[] = 'last() = 1';
514 
515  break;
516 
517  case 'only-of-type':
518  if ('*' == $_element) {
519  throw new Compiler\Exception(
520  'Cannot have a :only-of-type without element.',
521  2
522  );
523  }
524 
525  $selector[] = 'last() = 1';
526 
527  break;
528 
529  case 'empty':
530  $selector[] = 'not(*)';
531  $selector[] = 'not(normalize-space())';
532 
533  break;
534 
535  default:
536  $selector[] = $this->callPseudoClass($element, $pc);
537  }
538 
539  break;
540 
541  case '::':
542  $pe = $this->buffers[-1];
543  $selector[] = $this->callPseudoElement($element, $pe);
544 
545  break;
546 
547  case ':f':
548  $first = strpos($this->buffers[-1], '(');
549  $pcf = substr($this->buffers[-1], 0, $first);
550  $args = substr($this->buffers[-1], $first + 1, -1);
551 
552  switch ($pcf) {
553  case 'nth-child':
554  case 'nth-of-type':
555  preg_match(
556  '#^(?:([+|-])?\s*(\d+)?\s*(n))?\s*([+|-]?\s*\d+)?$#',
557  $args,
558  $matches
559  );
560 
561  $group =
562  !empty($matches[3])
563  ? '' !== $matches[2]
564  ? @$matches[1] . str_replace(' ', '', $matches[2])
565  : @$matches[1] . '1'
566  : '0';
567 
568  $offset =
569  isset($matches[4]) && null !== $matches[4]
570  ? str_replace(' ', '', $matches[4])
571  : '0';
572 
573  if (0 <= (int) $offset) {
574  $offset = '+' . trim($offset, '+');
575  }
576 
577  $tesffo =
578  '+' == $offset[0]
579  ? '- ' . substr($offset, 1)
580  : '+ ' . substr($offset, 1);
581 
582  if ('nth-child' == $pcf && '*' != $_element) {
583  $element = '*';
584  $selector[] = 'name() = "' . $_element . '"';
585  } elseif ('nth-of-type' == $pcf && '*' == $_element) {
586  throw new Compiler\Exception(
587  'Cannot have a :nth-of-type without element.',
588  3
589  );
590  }
591 
592  if (0 != (int) $group) {
593  if ('1' != $group) {
594  $selector[] = 'position() ' . $tesffo . ') mod ' .
595  $group . ' = 0';
596  }
597 
598  $selector[] = 'position() >= ' . (int) $offset;
599  } else {
600  $selector[] = 'position() = ' . (int) $offset;
601  }
602 
603  break;
604 
605  case 'nth-last-child':
606  case 'nth-last-of-type':
607  preg_match(
608  '#^(?:([+|-])?\s*(\d+)?\s*(n))?\s*([+|-]?\s*\d+)?$#',
609  $args,
610  $matches
611  );
612 
613  $group =
614  !empty($matches[3])
615  ? '' !== $matches[2]
616  ? @$matches[1] . str_replace(' ', '', $matches[2])
617  : @$matches[1] . '1'
618  : '0';
619 
620  $offset =
621  isset($matches[4]) && null !== $matches[4]
622  ? str_replace(' ', '', $matches[4])
623  : '0';
624 
625  if (0 <= (int) $group) {
626  $group = '+' . trim($group, '+');
627  }
628 
629  if (0 <= (int) $offset) {
630  $offset = '+' . trim($offset, '+');
631  }
632 
633  $puorg =
634  '+' == $group[0]
635  ? '-' . substr($group, 1)
636  : '+' . substr($group, 1);
637 
638  $tesffo =
639  '+' == $offset[0]
640  ? '- ' . substr($offset, 1)
641  : '+ ' . substr($offset, 1);
642 
643  if ('nth-last-child' === $pcf && '*' !== $_element) {
644  $element = '*';
645  $selector[] = 'name() = "' . $_element . '"';
646  } elseif ('nth-last-of-type' === $pcf && '*' === $_element) {
647  throw new Compiler\Exception(
648  'Cannot have a :nth-last-of-type without element.',
649  4
650  );
651  }
652 
653  if (0 !== (int) $group) {
654  if ('1' !== $group) {
655  $selector[] =
656  'position() ' . $offset . ') mod ' .
657  $puorg . ' = 0';
658  }
659 
660  $selector[] = 'position() <= (last() - ' . (int) $offset . ')';
661  } else {
662  $selector[] = 'position() = (last() - ' . (int) $offset . ')';
663  }
664 
665  break;
666 
667  default:
668  $selector[] = $this->callPseudoClassFunction($element, $pcf);
669  }
670 
671  break;
672 
673  case '::f':
674  $pef = $this->buffers[-1];
675  $this->_current .= $this->callPseudoElementFunction($element, $pef);
676 
677  break;
678  }
679  }
callPseudoClass($element, $pseudoClass)
Definition: CssToXPath.php:736
flush($element, $selector, $pseudo)
Definition: CssToXPath.php:277
callPseudoClassFunction($element, $function)
Definition: CssToXPath.php:768
callPseudoElement($element, $pseudoElement)
Definition: CssToXPath.php:752
callPseudoElementFunction($element, $function)
Definition: CssToXPath.php:784

Here is the call graph for this function:

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::end ( )
protected

Verify compiler state when ending the source code.

Returns
bool

Definition at line 701 of file CssToXPath.php.

702  {
703  $this->consume('__flush');
704  $this->_current = $this->_root . $this->_current;
705 
706  return true;
707  }

Here is the call graph for this function:

Hoa\Xml\CssToXPath::flush (   $element,
  $selector,
  $pseudo 
)
protected

Flush xpath current part.

Parameters
string$elementElement.
array$selectorSelectors collection.
string$pseudoPseudo-classes and pseudo-elements.
Returns
string

Definition at line 277 of file CssToXPath.php.

278  {
279  $out = $element;
280 
281  if (!empty($selector)) {
282  $out .= '[(' . implode(') and (', $selector) . ')]';
283  }
284 
285  $out .= $pseudo;
286 
287  return $out;
288  }

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::getDefaultNamespacePrefix ( )

Get the default namespace prefix.

Returns
string

Definition at line 812 of file CssToXPath.php.

813  {
814  return $this->_prefix;
815  }

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::getResult ( )

Get the result of the compiling.

Returns
string

Definition at line 714 of file CssToXPath.php.

715  {
716  return $this->getXPath();
717  }

Here is the call graph for this function:

Hoa\Xml\CssToXPath::getXPath ( )

Get result.

Returns
string

Definition at line 724 of file CssToXPath.php.

725  {
726  return $this->_current;
727  }

Here is the caller graph for this function:

Hoa\Xml\CssToXPath::pre ( $in)
protected

Compute source code before compiling it.

Parameters
string&$inSource code.
Returns
void

Definition at line 687 of file CssToXPath.php.

688  {
689  $this->_root = 'descendant-or-self::';
690  $this->_current = null;
691  $this->consume('__init');
692 
693  return;
694  }

Here is the call graph for this function:

Hoa\Xml\CssToXPath::setDefaultNamespacePrefix (   $prefix)

Set the default namespace prefix (e.g. __current_ns).

Parameters
string$prefixDefault prefix.
Returns
string

Definition at line 799 of file CssToXPath.php.

800  {
801  $old = $this->_prefix;
802  $this->_prefix = $prefix;
803 
804  return $old;
805  }

Member Data Documentation

Hoa\Xml\CssToXPath::$_current = null
protected

Definition at line 63 of file CssToXPath.php.

Hoa\Xml\CssToXPath::$_prefix = null
protected

Definition at line 70 of file CssToXPath.php.

Hoa\Xml\CssToXPath::$_root = null
protected

Definition at line 56 of file CssToXPath.php.


The documentation for this class was generated from the following file: