[php] xpath로 CSS 클래스 선택

.date라는 클래스 만 선택하고 싶습니다.

어떤 이유로이 작업을 수행 할 수 없습니다. 누군가 내 코드에 무엇이 잘못되었는지 알고 있다면 대단히 감사하겠습니다.

@$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." ";
}



답변

위의 답변에 문제가 있기 때문에이 질문에 대한 정식 답변을 작성하고 싶습니다.

우리의 문제

CSS의 선택 :

.foo

foo 클래스를 가진 모든 요소를 ​​선택합니다 .

XPath에서이 작업을 어떻게 수행합니까?

XPath는 CSS보다 강력하지만 XPath 에는 CSS 클래스 선택기에 해당하는 기본 기능이 없습니다 . 그러나 해결책이 있습니다.

그것을하는 올바른 방법

XPath 에서 동등한 선택기는 다음과 같습니다 .

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

normalize-space 함수는 선행 및 후행 공백을 제거하고 공백 문자 시퀀스를 단일 공백으로 바꿉니다.

(보다 일반적인 의미에서) 이것은 또한 CSS 선택자와 동일합니다.

*[class~="foo"]

클래스 속성 값이 공백으로 구분 된 값 목록 인 모든 요소와 일치 하며 그중 하나는 foo 와 정확히 동일합니다 .

몇 가지 분명하지만 잘못된 방법

XPath 선택기 :

//*[@class="foo"]

작동하지 않습니다! 예를 들어 둘 이상의 클래스가있는 요소와 일치하지 않기 때문입니다.

<div class="foo bar">

클래스 이름 주위에 추가 공백이 있으면 일치하지 않습니다.

<div class="  foo ">

‘개선 된’XPath 선택기

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

작동하지 않습니다! 예를 들어 foobar 클래스와 요소를 잘못 일치시키기 때문입니다.

<div class="foobar">

신용은 웹에서 찾은이 문제에 대한 가장 초기에 발표 된 솔루션 인이 친구에게 돌아갑니다.
http://dubinko.info/blog/2007/10/01/simple-parsing-of-space-seprated-attributes- in-xpathxslt /


답변

//[@class="date"] 유효한 xpath가 아닙니다.

을 시도 //*[@class="date"]하거나 이미지 인 것을 알고 있으면//img[@class="date"]


답변

XPath 3.1 은 함수 포함 토큰을 도입 하여 마침내이를 ‘공식적으로’해결합니다. 클래스지원 하도록 설계되었습니다 .

예:

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

이 함수는 공백 ( (U + 0020) 뿐만 아니라 )이 올바르게 처리되고 클래스 이름이 반복되는 경우 작동하며 일반적으로 가장자리 케이스를 덮도록합니다.


참고 : 오늘 (2016-12-13) 현재 XPath 3.1은 후보 추천 상태입니다 .


답변

XPath 2.0에서는 다음을 수행 할 수 있습니다.

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

Christian Weiske가 https://cweiske.de/tagebuch/XPath%3A%20Select%20element%20by%20class.htm 에서 언급했습니다.


답변

HTML은 대소 문자를 구분하지 않는 요소 및 속성 이름을 허용하며 class는 공백으로 구분 된 클래스 이름 목록입니다. 여기에 img태그와 class이름이 있습니다 date.

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

참조 : CSS 선택기를 XPath로 변환


답변

템플릿에서 마이너스 기호를 조심하십시오! DOM에서 “my-ownclass”를 쿼리하는 경우 :

<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.


답변