Я пытаюсь фильтровать html-таблицы с регулярным выражением, соответствующим их атрибуту id. Что я делаю не так? Код, который я пытаюсь реализовать:
$this->xpath = new DOMXPath($this->dom); $this->xpath->registerNamespace("php", "http://php.net/xpath"); $this->xpath->registerPHPFunctions(); foreach($xpath->query("//table[php:function('preg_match', '/post\d+/', @id)]") as $key => $row) { }
Ошибка, которую я получаю: preg_match ожидает, что вторым параметром будет строка, заданная массивом.
Атрибут по-прежнему является сложным элементом в соответствии с DOM (имеет пространство имен и т. Д.). Использование:
//table[php:function('preg_match', '/post\d+/', string(@id))]
Теперь нам нужно логическое возвращение, так что:
function booleanPregMatch($match,$string){ return preg_match($match,$string)>0; } $xpath->registerPHPFunctions(); foreach($xpath->query("//table[@id and php:function('booleanPregMatch', '/post\d+/', string(@id))]") as $key => $row){ echo $row->ownerDocument->saveXML($row); }
Кстати: для более сложных вопросов вы можете, конечно, проницательно проверить, что происходит с этим:
//table[php:function('var_dump',@id)]
Жаль, что у нас нет доступных функций XPATH 2.0, но если вы сможете справиться с этим требованием с более ненадежным starts-with
, я всегда предпочел бы, что за импорт функций PHP.
Что я делаю не так?
Выражение xpath @id
(второй параметр) возвращает массив, но preg_match
ожидает строку.
Сначала преобразуйте его в строку: string(@id)
.
Рядом с этим вам нужно фактически сравнить вывод с 1, поскольку preg_match
возвращает 1
при обнаружении:
foreach($xpath->query("//table[@id and 1 = php:function('preg_match', '/post\d+/', string(@id))]") as $key => $row) { var_dump($key, $row, $row->ownerDocument->saveXml($row)); }
Объяснение / Что происходит здесь ?:
По умолчанию выражение xpath возвращает список узлов (точнее набор узлов). Если вы сопоставляете функцию PHP с такими выражениями, эти множества представлены в виде массива. Вы можете легко проверить, что с помощью var_dump
:
$xpath->query("php:function('var_dump', //table)"); array(1) { [0]=> object(DOMElement)#3 (0) { } }
То же самое для выражения xpath @id
в контексте каждого элемента таблицы:
$xpath->query("//table[php:function('var_dump', @id)]"); array(1) { [0]=> object(DOMAttr)#3 (0) { } }
Вы можете изменить это на результат с типизированной строкой, используя функцию string
xpath :
Набор узлов преобразуется в строку, возвращая строковое значение узла в наборе узлов, которое является первым в порядке документа. Если набор узлов пуст, возвращается пустая строка.
$xpath->query("//table[php:function('var_dump', string(@id))]"); string(4) "test"
(таблица имеет id="test"
)