Итак, у меня есть HTML-строка вроде этого:
<td class="name"> <a href="/blah/somename23123">Some Name</a> </td> <td class="name"> <a href="/blah/somename28787">Some Name2</a> </td>
Используя XPath, я могу получить значение атрибута href, используя этот запрос Xpath:
$domXpath = new \DOMXPath($this->domPage); $hrefs = $domXpath->query("//td[@class='name']/a/@href"); foreach($hrefs as $href) {...}
И еще проще получить текстовое значение, например:
// Xpath auto. strips any html tags so we are // left with clean text value of a element $domXpath = new \DOMXPath($this->domPage); $names = $domXpath->query("//td[@class='name']/"); foreach($names as $name) {...}
Теперь мне любопытно узнать, как я могу объединить эти два запроса, чтобы получить оба значения только с одним запросом (если это что-то вроде этого даже возможно?).
получать
//td[@class='name']/a
а затем вырвать текст с помощью nodeValue
и атрибута getAttribute('href')
.
Кроме того, вы можете комбинировать запросы Xpath с оператором Union |
поэтому вы можете использовать
//td[@class='name']/a/@href|//td[@class='name']
также.
Чтобы уменьшить код до одного цикла, попробуйте:
$anchors = $domXpath->query("//td[@class='name']/a"); foreach($anchors as $a) { print $a->nodeValue." - ".$a->getAttribute("href")."<br/>"; }
Как указано выше 🙂 Слишком медленно ..
evaluate
для этой задачи! Самый простой способ получить значение – методом evaluate()
:
$xp = new DOMXPath($dom); $v = $xp->evaluate("string(/etc[1]/@stringValue)");
Примечание: важно ограничить XPath возвращает 1 элемент (первый a
в этом случае) и отличает значение с помощью string()
или round()
и т. Д.
Таким образом, в наборе нескольких элементов, используя ваш код foreach
,
$names = $domXpath->query("//td[@class='name']/"); foreach($names as $contextNode) { $text = $domXpath->evaluate("string(./a[1])",$contextNode); $href = $domXpath->evaluate("string(./a[1]/@href)",$contextNode); }
PS: этот пример предназначен только для иллюстрации evaluate
… Когда информация уже существует в узле, используйте то, что предлагает лучшую производительность , как методы getAttribute()
, saveXML()
и т. Д. И свойства как $nodeValue
, $textContent
, и т. д., поставляемые DOMNode
.
См. Ответ @ Gordon для этой конкретной проблемы.
Подзапрос XPath (в контексте) хорош для сложных случаев – или смягчает ваш код, избегая проверки hasChildNodes () + цикла для $ childNodes и т. Д. Без значительного усиления производительности.