Преобразование Javascript XPath в действительный PHP-запрос() XPath | нормализовать JS XPath → PHP
Это действительный XPath в Javascript:
id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]
И это превратилось в действительный PHP XPath для использования с DOMXPath- > query() -
//*[@id="priceInfo"]//div[@class="standardProdPricingGroup"]//span[1]
- Знаете ли вы какие-либо библиотеки или пользовательские компоненты, которые уже делают это преобразование?
- Вы знаете доступную документацию, в которой перечислены две различия синтаксиса?
Моя основная забота заключается в том, что может быть много различий, и я хочу определить эти различия, и у меня есть проблемы с их выявлением.
Вопрос может быть поставлен также по-другому: Поскольку Javascript может иметь разные допустимые форматы XPath, как нормализовать их для работы с PHP.
В одном из обновлений также упоминается, что функция id() является действительной XPath, если существует допустимое DTD, которое содержит это определение. У меня нет власти над входным DTD, и если есть способ найти решение, которое работает без какого-либо конкретного DTD, это будет потрясающе.
Update:
Я хочу преобразовать первый формат во второй с помощью алгоритма. Мой вход - первый, а не второй. Невозможно изменить это.
Как отметил @Nison Maël, 2-й формат действителен Javascript XPath, представленный здесь: http://jsbin.com/elatum/2/edit, к сожалению, просто добавляет проблему фрагментации Javascript XPath ".
@salathe указал, что корректный запрос Javascript XPath отлично работает на PHP, если в документе, документированном, есть действительный DTD (@Dimitre Novatchev упомянул об этом в комментарии, но не обратил внимания на важность). К сожалению, я не контролирую входной DTD, поэтому теперь я должен исследовать способ преодоления этого или найти решение, которое работает даже без действительного DTD.
Ответы
Ответ 1
Просто увидев, что Salathe на самом деле ответил на то же самое, но принимая во внимание ваш комментарий и подчеркивая это немного больше:
Вам не нужно указывать DTD. Пока вы используете функции DOMDocument::loadHTML
или DOMDocument::loadHTMLFile
, атрибут HTML id
фактически зарегистрирован для функции xpath id()
. С демонстрационным HTML, приведенным в http://jsbin.com/elatum/2/edit, вы даже получаете сообщение об ошибке при загрузке документа:
Предупреждение: DOMDocument:: loadHTMLFile(): ID priceInfo, уже определенная в...
Это уже признак того, что это истинный атрибут идентификатора, потому что он копирует дубликаты. Соответствующий пример кода выглядит так:
$xpath = 'id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]';
$doc = new DOMDocument();
$doc->loadHTMLFile(__DIR__ . '/../data/file-11796340.html');
$xp = new DOMXPath($doc);
$r = $xp->query($xpath);
echo $xpath, "\n";
echo $r ? $r->length : 0, ' elements found', "\n";
if (!$r) return;
foreach($r as $node) {
echo " - ", $node->nodeValue, "\n";
}
Вывод:
id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]
1 elements found
- hello
Если вам нужно больше управления, сначала запустите xpath, чтобы пометить все атрибуты HTML id
как ID для xpath:
$r = $xp->query("//*[@id]");
if ($r) foreach($r as $node) {
$node->setIdAttribute('id', true);
}
Затем вы можете использовать один и тот же путь xpath с функцией id()
, не нужно его изменять.
Ответ 2
Не можете ли вы просто перевести id("...")
в //*[@id="..."][1]
в начале вашего выражения?
Например, если вы можете предположить, что в выражениях id(...)
у вас не будет круглых скобок:
$queryRewritten = preg_replace('/^id\(([^\)]+)\)/','//*[@id=$1][1]',$query);
Пример кода
EDIT: исправлена замена, id() imust будет первым в выражении
Ответ 3
Это не полный ответ, но он слишком большой, чтобы добавить комментарий, и это может помочь вам немного.
Если у вас есть контроль над входным XML, вместо использования DTD для объявления атрибутов id
вы можете объявить их явно в самом документе XML, префиксными атрибутами id
с помощью xml:
.
Например, если у вас есть XML
<foo id="x27"/>
и изменил его на
<foo xml:id="x27"/>
тогда функция id() распознает этот атрибут как формальный тип XML id
, а не только как атрибут с именем id
.
Я знаю, что этот "трюк" работает на саксонском процессоре, но я должен признать, что я не пробовал его с PHP.
W3C xml: id