PHP XPath substring-after возвращает только первый результат - PullRequest
2 голосов
/ 18 сентября 2011

Я выполняю некоторые операции с HTML и ударился об стену с помощью этого одного запроса. Я пытаюсь вернуть набор значений из следующей структуры HTML-страницы:

<div id="product-grid">
    <ul>
        <li><div class="price">Cash Price: $20.00</div></li>
        <li><div class="price">Cash Price: $30.00</div></li>
        <li><div class="price">Cash Price: $40.00</div></li>
    </ul>
</div>

Я пытаюсь вернуть цены "$20.00" в списке. Если я использую следующий XPath:

id('product-grid')//p[@class="price"] 

Я получаю список результатов со всеми «Наличными ценами: 40,00 $». Если я попробую следующий запрос:

substring-after(id('product-grid')//p[@class="price"] , "Price: ")

Я получаю правильный вывод, но получаю только первый результат. Кто-нибудь знает, как я могу получить все результаты?

Я бегу PHP5.3.3 с libxml 2.7.8 для XPath. Я вызываю xpath следующим образом:

$xpath = new DOMXPath( $html ); 
$resultset= $xpath->query($query);

Я безумно гуглил, пытаясь выяснить, почему это происходит! Пожалуйста, помогите!

Ответы [ 3 ]

1 голос
/ 18 сентября 2011

Извините, но я не думаю, что это возможно за один шаг. Насколько я знаю, XPath 1.0 не поддерживает вызовы функций в конце пути XPath. Ответ здесь означает то же самое.

Кроме того, вы не должны использовать id('product-grid') в качестве первой части пути, поскольку идентификатор находится в корневом элементе и не требует специального выбора. Если ваш пример XML является просто фрагментом более крупного XML-документа, возможно, понадобится id().

Следующее работает как ожидалось:

$xml = new DOMDocument();
$xml->loadXML('<div id="product-grid">
 <ul>
  <li><div class="price">Cash Price: $20.00</div></li>
  <li><div class="price">Cash Price: $30.00</div></li>
  <li><div class="price">Cash Price: $40.00</div></li>
</ul>
</div>');
$xpath = new DOMXPath($xml);
foreach ($xpath->query('//div[@class="price"]') as $n) {
    var_dump(substr($n->nodeValue, strpos($n->nodeValue, '$')));
}   
1 голос
/ 18 сентября 2011

Требуемая обработка не может быть задана просто как одно выражение XPath 1.0 , потому что по определению любая функция, которая ожидает один строковый аргумент, но получает набор узлов, принимает строковое значение только первого(в порядке документа) узел этого набора узлов.

Также, в отличие от XPath 2.0 в XPath 1.0, нельзя указывать вызов функции в качестве шага расположения.

Поэтому одним из решений является выдача этого выражения XPath :

substring-after((id('product-grid')//p[@class="price"])[$k], "Price: ") 

N раз, заменяя $k в каждом выражении на 1,2,..., N, где N - это результат вычисления другогоВыражение XPath:

count(id('product-grid')//p[@class="price"])

Используя XPath 2.0, можно сделать это с помощью этого простого и единственного выражения :

id('product-grid')//p[@class="price"]/substring-after(., "Price: ")

, которое при оценке выдает именно требуемую последовательностьстроки.

1 голос
/ 18 сентября 2011

Вы должны использовать подстроку после получения списка.

 id('product-grid')//div[@class="price"][substring-after(., 'Price: ')]

Это должно работать.

РЕДАКТИРОВАТЬ: Кажется, это работает.Однако я не могу проверить возвращаемое значение, так как не знаю, как получить значение подстроки.Что вы используете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...