[xpath] 특정 문자열이 포함 된 속성에서 어떻게 일치시킬 수 있습니까?

속성에 둘 이상의 단어가 포함 된 경우 속성별로 노드를 선택하는 데 문제가 있습니다. 예를 들면 다음과 같습니다.

<div class="atag btag" />

이것은 내 xpath 표현입니다.

//*[@class='atag']

표현은

<div class="atag" />

그러나 이전 예제에는 해당되지 않습니다. 를 어떻게 선택할 수 <div>있습니까?



답변

다음은 className에 포함 된 div 요소를 찾는 예입니다 atag.

//div[contains(@class, 'atag')]

다음은 className이 포함 atag하고 div 요소를 찾는 예제입니다 btag.

//div[contains(@class, 'atag') and contains(@class ,'btag')]

그러나와 같은 부분 일치도 찾습니다 class="catag bobtag".

부분적으로 일치하지 않으려면 아래 bobince의 답변을 참조하십시오.


답변

mjv의 대답은 좋은 시작이지만 atag가 나열된 첫 번째 클래스 이름이 아닌 경우 실패합니다.

일반적인 접근 방식은 다소 다루기 힘든 것입니다.

//*[contains(concat(' ', @class, ' '), ' atag ')]

이것은 클래스가 공백으로 만 분리되고 다른 형태의 공백이 아닌 한 작동합니다. 이것은 거의 항상 그렇습니다. 그렇지 않은 경우 여전히 다루기 힘들어 야합니다.

//*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')]

(클래스 이름과 같이 공백으로 구분 된 문자열로 선택하는 것은 일반적인 경우입니다. CSS3의 ‘[class ~ = “atag”]’와 같이 특정 XPath 함수가없는 것은 놀라운 일입니다.)


답변

이 시도: //*[contains(@class, 'atag')]


답변

편집 : 완전한 토큰 수준에서 비교를 수행하는 트릭과 함께 start-with 대신 contains 를 사용하는 bobince의 솔루션을 참조하십시오 ( ‘atag’패턴은 다른 ‘tag’의 일부로 찾을 수 있어야 함).

“atag btag”는 클래스 속성에 대한 홀수 값이지만 결코 적습니다.

//*[starts-with(@class,"atag")]


답변

작동하는 2.0 XPath :

//*[tokenize(@class,'\s+')='atag']

또는 변수와 함께 :

//*[tokenize(@class,'\s+')=$classname]


답변

관심있는 클래스 이름이 다른 가능한 클래스 이름의 하위 문자열이 아니라고 가정 할 수 있으면 bobince의 답변이 지나치게 복잡 할 수 있습니다 . 이것이 사실이라면, contains 함수를 통해 부분 문자열 매칭을 사용할 수 있습니다. 다음은 클래스에 하위 문자열 ‘atag’가 포함 된 모든 요소와 일치합니다.

//*[contains(@class,'atag')]

위의 가정이 유지되지 않으면 하위 문자열 일치가 의도하지 않은 요소와 일치합니다. 이 경우 단어 경계를 찾아야합니다. 공백 구분 기호를 사용하여 클래스 이름 경계를 찾으면 bobince의 두 번째 답변이 다음과 정확히 일치합니다.

//*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')]

일치 atag하지 않습니다 matag.


답변

bobince의 답변에 추가하려면 … 사용하는 도구 / 라이브러리가 Xpath 2.0을 사용하는 경우 다음을 수행 할 수도 있습니다.

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

index-of ()는 문자열에서 일치하는 각 인덱스의 시퀀스를 반환하므로 count ()는 분명히 필요합니다.