-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathXPath.php
109 lines (97 loc) · 2.3 KB
/
XPath.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
/**
* @package s9e\TextFormatter
* @copyright Copyright (c) The s9e authors
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
namespace s9e\TextFormatter\Utils;
use InvalidArgumentException;
abstract class XPath
{
/**
* Export a literal as an XPath expression
*
* @param mixed $value Literal, e.g. "foo"
* @return string XPath expression, e.g. "'foo'"
*/
public static function export($value)
{
$callback = static::class . '::export' . ucfirst(gettype($value));
if (!is_callable($callback))
{
throw new InvalidArgumentException(__METHOD__ . '() cannot export non-scalar values');
}
return $callback($value);
}
/**
* Export given boolean value
*
* @param bool $value
* @return string
*/
protected static function exportBoolean(bool $value): string
{
return ($value) ? 'true()' : 'false()';
}
/**
* Export given float value
*
* @param float $value
* @return string
*/
protected static function exportDouble(float $value): string
{
if (!is_finite($value))
{
throw new InvalidArgumentException(__METHOD__ . '() cannot export irrational numbers');
}
// Avoid locale issues by using sprintf()
return preg_replace('(\\.?0+$)', '', sprintf('%F', $value));
}
/**
* Export given integer value
*
* @param integer $value
* @return string
*/
protected static function exportInteger(int $value): string
{
return (string) $value;
}
/**
* Export a string as an XPath expression
*
* @param string $str Literal, e.g. "foo"
* @return string XPath expression, e.g. "'foo'"
*/
protected static function exportString(string $str): string
{
// foo becomes 'foo'
if (strpos($str, "'") === false)
{
return "'" . $str . "'";
}
// d'oh becomes "d'oh"
if (strpos($str, '"') === false)
{
return '"' . $str . '"';
}
// This string contains both ' and ". XPath 1.0 doesn't have a mechanism to escape quotes,
// so we have to get creative and use concat() to join chunks in single quotes and chunks
// in double quotes
$toks = [];
$c = '"';
$pos = 0;
while ($pos < strlen($str))
{
$spn = strcspn($str, $c, $pos);
if ($spn)
{
$toks[] = $c . substr($str, $pos, $spn) . $c;
$pos += $spn;
}
$c = ($c === '"') ? "'" : '"';
}
return 'concat(' . implode(',', $toks) . ')';
}
}