Aktualizacja: wersja Xpath *[@class~='my-class']selektora css
Więc po moim komentarzu poniżej w odpowiedzi na komentarz hakre, zaciekawiło mnie i zajrzałem do kodu Zend_Dom_Query. Wygląda na to, że powyższy selektor został skompilowany do następującej ścieżki xpath (nieprzetestowana):
Zasadniczo wszystko, co tutaj robimy, to znormalizowanie classatrybutu, tak aby nawet pojedyncza klasa była ograniczona spacjami, a cała lista klas była ograniczona spacjami. Następnie dodaj spację do szukanej klasy. W ten sposób skutecznie szukamy i znajdujemy tylko wystąpienia my-class.
znajduje również klasę my-class2, ale całkiem fajną. Czy jest jakiś sposób, aby wybrać tylko pierwsze elementy?
hakre
Nie sądzę, żebyś mógł bez xpath2 ... Jednak przykład Zend_Dom_Query robi dokładnie to. JEŚLI nie chcesz używać tego compkenetu w swoim projekcie, możesz chcieć zobaczyć, jak tłumaczą ten selektor css na xpath. Może DomXPath obsługuje xpath 2.0 - nie jestem tego pewien.
prodigitalson
1
ponieważ classmoże mieć więcej niż jedną klasę, na przykład: <a class="my-link link-button nav-item">.
prodigitalson
2
@prodigitalson: To jest niepoprawne, ponieważ nie odzwierciedla spacji, spróbuj //*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')](Bardzo pouczające: selektory CSS i wyrażenia XPath ).
hakre
1
@babonk: tak, musisz użyć containsw połączeniu z concat... my tylko omawiamy szczegóły wypełniania spacji po obu stronach klasy, której szukasz, lub wypełnienia tylko z jednej strony. Jednak oba powinny działać.
prodigitalson
20
Jeśli chcesz uzyskać innerhtml klasy bez zend, możesz użyć tego:
To wspaniale. Mam element z klasą. Teraz chcę edytować zawartość elementu, na przykład dołączyć child do elementu zawierającego klasę. Jak dołączyć dziecko i odtworzyć cały HTML? Proszę pomóż. Oto, co zrobiłem. $classResult = getElementByClass($dom, 'div', 'm-signature-pad'); $classResult->nodeValue = ''; $enode = $dom->createElement('img'); $enode->setAttribute('src', $signatureImage); $classResult->appendChild($enode);
Istnieje również inne podejście bez użycia DomXPathlub Zend_Dom_Query.
Opierając się na oryginalnej funkcji dav, napisałem następującą funkcję, która zwraca wszystkie dzieci węzła nadrzędnego, którego tag i klasa pasują do parametrów.
załóżmy, że masz zmienną $htmlnastępujący kod 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>
użycie getElementsByClassjest tak proste, jak:
$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".
Odpowiedzi:
Aktualizacja: wersja Xpath
*[@class~='my-class']
selektora cssWięc po moim komentarzu poniżej w odpowiedzi na komentarz hakre, zaciekawiło mnie i zajrzałem do kodu
Zend_Dom_Query
. Wygląda na to, że powyższy selektor został skompilowany do następującej ścieżki xpath (nieprzetestowana):[contains(concat(' ', normalize-space(@class), ' '), ' my-class ')]
więc php wyglądałoby tak:
Zasadniczo wszystko, co tutaj robimy, to znormalizowanie
class
atrybutu, tak aby nawet pojedyncza klasa była ograniczona spacjami, a cała lista klas była ograniczona spacjami. Następnie dodaj spację do szukanej klasy. W ten sposób skutecznie szukamy i znajdujemy tylko wystąpieniamy-class
.Użyć selektora xpath?
Jeśli jest to tylko jeden typ elementu, można go zastąpić
*
konkretną zmienną.Jeśli chcesz zrobić dużo tego z bardzo złożonym selektorem, polecam,
Zend_Dom_Query
który obsługuje składnię selektora CSS (a la jQuery):źródło
my-class2
, ale całkiem fajną. Czy jest jakiś sposób, aby wybrać tylko pierwsze elementy?class
może mieć więcej niż jedną klasę, na przykład:<a class="my-link link-button nav-item">
.//*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')]
(Bardzo pouczające: selektory CSS i wyrażenia XPath ).contains
w połączeniu zconcat
... my tylko omawiamy szczegóły wypełniania spacji po obu stronach klasy, której szukasz, lub wypełnienia tylko z jednej strony. Jednak oba powinny działać.Jeśli chcesz uzyskać innerhtml klasy bez zend, możesz użyć tego:
źródło
$classname = 'main-article'
Myślę, że przyjęty sposób jest lepszy, ale myślę, że to również może działać
źródło
$classResult = getElementByClass($dom, 'div', 'm-signature-pad'); $classResult->nodeValue = ''; $enode = $dom->createElement('img'); $enode->setAttribute('src', $signatureImage); $classResult->appendChild($enode);
Istnieje również inne podejście bez użycia
DomXPath
lubZend_Dom_Query
.Opierając się na oryginalnej funkcji dav, napisałem następującą funkcję, która zwraca wszystkie dzieci węzła nadrzędnego, którego tag i klasa pasują do parametrów.
załóżmy, że masz zmienną
$html
następujący kod HTML:użycie
getElementsByClass
jest tak proste, jak:źródło
DOMDocument wolno pisze, a phpQuery ma poważne problemy z wyciekiem pamięci. Skończyło się na:
https://github.com/wasinger/htmlpagedom
Aby wybrać zajęcia:
Mam nadzieję, że pomoże to również komuś innemu
źródło