Подтвердить что ты не робот

Преобразование 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.

4b9b3361

Ответ 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