DOMXpath – получить атрибут href и текстовое значение элемента a

Итак, у меня есть 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 и т. Д. Без значительного усиления производительности.