programing

xpath를 사용하는 css 클래스 선택

nicegoodjob 2023. 1. 16. 20:18
반응형

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.1contains-token 함수를 도입하여 최종적으로 이 문제를 해결합니다.수업을 지원하도록 설계되어 있습니다.

예:

//*[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에서는 대소문자를 구분하지 않는 요소 및 속성 이름을 사용할 수 있으며 클래스는 공백으로 구분된 클래스 이름 목록입니다., 그럼 ㅇㅇ, ㅇㅇ.img와 " " "class '''date:

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

'CSS Selector에서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.

언급URL : https://stackoverflow.com/questions/8808921/selecting-a-css-class-with-xpath

반응형