xpath — PHP DOMXPath работает с двойными кавычками, сбои с одинарными кавычками

Я написал небольшой скрипт, который извлекает информацию с веб-сайта с использованием PHP DOMXPath учебный класс.
Я запрашиваю <div class="sku" /> и выполнить substring-before на результат. Результат содержит текст, неразрывные пробелы, разрыв строки и другой текст.
Итак, что я пытаюсь сделать, это сократить до &nbsp;&nbsp;\r\n, Он отлично работает, когда я использую следующий запрос:

$query = "substring-before(//div[@class='sku'],'\xC2\xA0\xC2\xA0\r\n')";

но терпит неудачу, как только я изменяю кавычки (которые не должны иметь никакого значения):

$query = 'substring-before(//div[@class="sku"],"\xC2\xA0\xC2\xA0\r\n")';

или же

$query = 'substring-before(//div[@class=\'sku\'],\'\xC2\xA0\xC2\xA0\r\n\')';

Как это возможно и как я могу преодолеть это?

Живой пример здесь: http://codepad.viper-7.com/R1rCaj

0

Решение

Стиль цитат имеет значение, потому что когда строка заключена в двойные кавычки, PHP будет интерпретировать больше escape-последовательностей для специальных символов — включая то, что вы используете для неразрывного пространства \xC2\xA0, возврат каретки \rи перевод строки \n,

Когда они заключены в одинарные кавычки '\xC2\xA0\r\n'Как и во втором запросе, PHP обрабатывает их как буквальные символы — обратную косую черту, x, C, 2 … и т. д.


Небольшая дополнительная подсветка синтаксиса может помочь показать это, escape-последовательности оранжевого цвета:

введите описание изображения здесь


Если в вашей строке уже есть то, что должно быть escape-последовательностями в виде буквенных символов, и есть ни за что чтобы исправить это*, Вы в какой-то грязной ситуации, когда заменяете их сами.

это preg_replace_callback() позаботится о последовательности в вашем примере, и тривиально распространиться на остальные escape-последовательности, поддерживаемые двойными кавычками:

// Known good.
$query1 = "substring-before(//div[@class='sku'],'\xC2\xA0\xC2\xA0\r\n')";

// Known bad.
$query2 = 'substring-before(//div[@class=\'sku\'],\'\xC2\xA0\xC2\xA0\r\n\')';

$query2 = preg_replace_callback(
'/\\\\(?:[rn]|(?:x[0-9A-Fa-f]{1,2}))/',
function ($matches) {
switch (substr($matches[0], 0, 2)) {
case '\r':
return "\r";
case '\n':
return "\n";
case '\x':
return hex2bin(substr($matches[0], 2));
}
},
$query2
);

var_dump($query1 === $query2); // Now equal?

Выход:

bool(true)

(* Действительно, вы должны исправить это у источника.)

3

Другие решения

Вы можете сделать это легко с simple_html_dom
для скачивания: http://sourceforge.net/projects/simplehtmldom/files/
Руководство : http://simplehtmldom.sourceforge.net/manual.htm

    <?php
// include simple html dom library
include('./lib/simple_html_dom.php');
$url="http://www.vosteen-shop.de/p-261232-edelstahl-herz-acero-zum-hngen-lnge-10cm-breite-10cm-silber-glanz.aspx";
// get html in $html var
$html=file_get_html($url);
// find your class div.sku (plaintext) or you can get (innertext)
$results=$html->find('div.sku',0)->innertext;
$explode=explode("<b",$results);
$results=trim($explode[0]);
echo $results ;
?>
0

По вопросам рекламы [email protected]