Frage Auswählen einer CSS-Klasse mit XPath


Ich möchte nur eine Klasse namens .date auswählen

Aus irgendeinem Grund kann ich das nicht zur Arbeit bringen. Wenn jemand weiß, was mit meinem Code falsch ist, würde es sehr geschätzt werden.

@$doc = new DOMDocument();
@$doc->loadHTML($html);
$xml = simplexml_import_dom($doc); // just to make xpath more simple
$images = $xml->xpath('//[@class="date"]');                             
foreach ($images as $img)
{
    echo  $img." ";
}

74
2018-01-10 19:00


Ursprung


Antworten:


Ich möchte die kanonische Antwort auf diese Frage schreiben, weil die obige Antwort ein Problem hat.

Unser Problem

Das CSS Wähler:

.foo

wählt ein beliebiges Element mit der Klasse aus foo.

Wie machst du das in XPath?

Obwohl XPath leistungsfähiger als CSS ist, XPath hat kein natives Äquivalent eines CSS-Klassenselektors. Es gibt jedoch eine Lösung.

Der richtige Weg, es zu tun

Der entsprechende Wahlschalter in XPath ist:

//*[contains(concat(" ", normalize-space(@class), " "), " foo ")]

Die Funktion Normalisieren-Raum löscht führende und nachfolgende Whitespaces (und ersetzt auch Sequenzen von Whitespace-Zeichen durch ein einzelnes Leerzeichen).

(In einem allgemeineren Sinn) entspricht dies auch dem CSS-Selektor:

*[class~="foo"]

welches zu jedem Element passt, dessen Klasse Attributwert ist eine Liste von durch Leerzeichen getrennten Werten, von denen einer genau gleich ist foo.

Ein paar offensichtliche, aber falsche Wege, es zu tun

Der XPath-Selektor:

//*[@class="foo"]

funktioniert nicht! weil es beispielsweise keinem Element entspricht, das mehr als eine Klasse enthält

<div class="foo bar">

Es wird auch nicht übereinstimmen, wenn um den Klassennamen herum zusätzliche Leerzeichen vorhanden sind:

<div class="  foo ">

Der "verbesserte" XPath-Selektor

//*[contains(@class, "foo")]

funktioniert auch nicht! weil es Elemente mit der Klasse falsch zusammenbringt foobar, beispielsweise

<div class="foobar">

Kredit geht an diesen Kerl, der die früheste veröffentlichte Lösung für dieses Problem war, die ich im Internet fand: http://dubinko.info/blog/2007/10/01/simple-parsing-of-space-seprated-attributes-in-xpathxslt/ 


221
2018-02-03 18:24



//[@class="date"] ist kein gültiger XPath.

Versuchen //*[@class="date"]oder wenn du weißt, dass es ein Bild ist, //img[@class="date"]


9
2018-01-10 19:04



XPath 3.1 führt eine Funktion ein enthält Token und löst damit endlich "offiziell". Es ist so konzipiert, um Support-Klassen.

Beispiel:

//*[contains-token(@class, "foo")]

Diese Funktion stellt sicher, dass Leerzeichen (nicht nur  (U + 0020)) wird korrekt behandelt, funktioniert bei Klassennamenwiederholung und deckt in der Regel die Kantenfälle ab.


Hinweis: Ab heute (2016-12-13) hat XPath 3.1 den Status Empfehlung des Kandidaten.


7
2017-12-13 17:09



In XPath 2.0 können Sie:

//*[count(index-of(tokenize(@class, '\s+' ), 'foo')) = 1]

wie von Christian Weiske in: https://cweiske.de/tagebuch/XPath%3A%20Select%20element%20by%20class.htm


3
2018-03-09 13:33



HTML erlaubt die Groß- und Kleinschreibung von Element- und Attributnamen und die Klasse ist eine durch Leerzeichen getrennte Liste von Klassennamen. Hier gehen wir für eine img Tag und die class genannt date:

//*['IMG' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')]/@*['CLASS' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') and contains(concat(' ', normalize-space(.), ' '), concat(' ', 'date', ' '))]

Siehe auch: CSS-Auswahl zur XPath-Konvertierung


1
2018-06-13 16:36



ACHTUNG MINUS ZEICHEN IN SCHABLONE !!! Wenn Sie in DOM nach "meine-eigene Klasse" suchen:

<ul class="my-ownclass"><li>...</li></ul>
<ul class="someother"><li>...</li></ul>
<ul><li>...</li></ul>

$finder = new DomXPath($dom);
$nodes = $finder->query(".//ul[contains(@class, 'my-ownclass')]"); // This will NOT behave as expected! This will strangely match all the <ul> elements in DOM.
$nodes = $finder->query(".//ul[contains(@class, 'ownclass')]"); // This will match the element.

1
2018-04-30 07:43