Обновление: версия Xpath *[@class~='my-class']селектора css
Поэтому после моего комментария ниже в ответ на комментарий Хакре мне стало любопытно, и я заглянул в код Zend_Dom_Query. Похоже, что приведенный выше селектор скомпилирован в следующий xpath (непроверенный):
По сути, все, что мы здесь делаем, - это нормализуем classатрибут, так что даже один класс ограничен пробелами, а полный список классов ограничен пробелами. Затем добавьте пробел в класс, который мы ищем. Таким образом, мы эффективно ищем и находим только экземпляры my-class.
Если это только один тип элемента, вы можете заменить *его конкретным тэгом.
Если вам нужно сделать много этого с помощью очень сложного селектора, я бы порекомендовал, Zend_Dom_Queryкоторый поддерживает синтаксис селектора CSS (а-ля jQuery):
находит и класс my-class2, но довольно мило. Есть ли способ выбрать только первый из всех элементов?
hakre
Я не думаю, что можно обойтись без xpath2 ... Однако пример для Zend_Dom_Query делает именно это. ЕСЛИ вы не хотите использовать этот compkenet в своем проекте, тогда вы можете посмотреть, как они переводят этот селектор css в xpath. Возможно, DomXPath поддерживает xpath 2.0 - я в этом не уверен.
prodigitalson
1
потому что classможет иметь более одного класса, например: <a class="my-link link-button nav-item">.
prodigitalson
2
@prodigitalson: это неверно, поскольку оно не отражает пробелы, попробуйте //*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')](очень информативно: селекторы CSS и выражения XPath ).
hakre
1
@babonk: да, вам нужно использовать containsв сочетании с concat... мы просто обсуждаем особенности заполнения пробелов с обеих сторон класса, который вы ищете, или заполнения только одной стороны. Либо должно работать.
prodigitalson
20
Если вы хотите получить innerhtml класса без zend, вы можете использовать это:
Замечательно. Я получил элемент с классом. Теперь я хочу отредактировать содержимое элемента, например добавить дочерний элемент к элементу, содержащему класс. Как добавить дочерний элемент и воссоздать весь HTML? Пожалуйста помоги. Вот что я сделал. $classResult = getElementByClass($dom, 'div', 'm-signature-pad'); $classResult->nodeValue = ''; $enode = $dom->createElement('img'); $enode->setAttribute('src', $signatureImage); $classResult->appendChild($enode);
Есть и другой подход без использования DomXPathили Zend_Dom_Query.
На основе исходной функции dav я написал следующую функцию, которая возвращает всех дочерних элементов родительского узла, тег и класс которого соответствуют параметрам.
предположим, у вас есть переменная $htmlследующего HTML:
<html><body><divid="content_node"><pclass="a">I am in the content node.</p><pclass="a">I am in the content node.</p><pclass="a">I am in the content node.</p></div><divid="footer_node"><pclass="a">I am in the footer node.</p></div></body></html>
использование getElementsByClassтак же просто, как:
$dom =newDOMDocument('1.0','utf-8');
$dom->loadHTML($html);
$content_node=$dom->getElementById("content_node");
$div_a_class_nodes=getElementsByClass($content_node,'div','a');//will contain the three nodes under "content_node".
Ответы:
Обновление: версия Xpath
*[@class~='my-class']
селектора cssПоэтому после моего комментария ниже в ответ на комментарий Хакре мне стало любопытно, и я заглянул в код
Zend_Dom_Query
. Похоже, что приведенный выше селектор скомпилирован в следующий xpath (непроверенный):[contains(concat(' ', normalize-space(@class), ' '), ' my-class ')]
так что php будет:
По сути, все, что мы здесь делаем, - это нормализуем
class
атрибут, так что даже один класс ограничен пробелами, а полный список классов ограничен пробелами. Затем добавьте пробел в класс, который мы ищем. Таким образом, мы эффективно ищем и находим только экземплярыmy-class
.Использовать селектор xpath?
Если это только один тип элемента, вы можете заменить
*
его конкретным тэгом.Если вам нужно сделать много этого с помощью очень сложного селектора, я бы порекомендовал,
Zend_Dom_Query
который поддерживает синтаксис селектора CSS (а-ля jQuery):источник
my-class2
, но довольно мило. Есть ли способ выбрать только первый из всех элементов?class
может иметь более одного класса, например:<a class="my-link link-button nav-item">
.//*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')]
(очень информативно: селекторы CSS и выражения XPath ).contains
в сочетании сconcat
... мы просто обсуждаем особенности заполнения пробелов с обеих сторон класса, который вы ищете, или заполнения только одной стороны. Либо должно работать.Если вы хотите получить innerhtml класса без zend, вы можете использовать это:
источник
$classname = 'main-article'
Я думаю, что принятый способ лучше, но я думаю, что это тоже может сработать
источник
$classResult = getElementByClass($dom, 'div', 'm-signature-pad'); $classResult->nodeValue = ''; $enode = $dom->createElement('img'); $enode->setAttribute('src', $signatureImage); $classResult->appendChild($enode);
Есть и другой подход без использования
DomXPath
илиZend_Dom_Query
.На основе исходной функции dav я написал следующую функцию, которая возвращает всех дочерних элементов родительского узла, тег и класс которого соответствуют параметрам.
предположим, у вас есть переменная
$html
следующего HTML:использование
getElementsByClass
так же просто, как:источник
DOMDocument медленно набирает, а phpQuery имеет проблемы с утечкой памяти. В итоге я использовал:
https://github.com/wasinger/htmlpagedom
Чтобы выбрать класс:
Надеюсь, это поможет и кому-то другому
источник