대소 문자를 구분하지 않는 XPath contains () 가능?


94

내 DOM의 모든 텍스트 노드에서 실행 중이며 nodeValue에 특정 문자열이 포함되어 있는지 확인합니다.

/html/body//text()[contains(.,'test')]

대소 문자를 구분합니다. 그러나 나는 또한 잡으려면 Test, TEST또는 TesT. XPath (JavaScript)로 가능합니까?

답변:


111

이것은 XPath 1.0 용입니다. 사용자 환경에서 XPath 2.0을 지원하는 경우 여기를 참조 하십시오 .


예. 가능하지만 아름답지는 않습니다.

/html/body//text()[
  contains(
    translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
    'test'
  )
]

이것은 알파벳이 미리 알려진 검색 문자열에 대해 작동합니다. 예상되는 악센트 부호가있는 문자를 추가하십시오.


가능하다면 <span>HTML을 빌드하는 동안 특정 클래스가있는 텍스트를 포함하는 것과 같은 다른 방법으로 관심있는 텍스트를 표시하십시오 . 이러한 것들은 요소 텍스트의 하위 문자열보다 XPath로 찾기가 훨씬 쉽습니다.

이것이 옵션이 아닌 경우 JavaScript (또는 XPath를 실행하는 데 사용하는 다른 호스트 언어)를 사용하여 동적 XPath 표현식을 작성할 수 있습니다.

function xpathPrepare(xpath, searchString) {
  return xpath.replace("$u", searchString.toUpperCase())
              .replace("$l", searchString.toLowerCase())
              .replace("$s", searchString.toLowerCase());
}

xp = xpathPrepare("//text()[contains(translate(., '$u', '$l'), '$s')]", "Test");
// -> "//text()[contains(translate(., 'TEST', 'test'), 'test')]"

( @KirillPolishchuk의 답변에 대한 모자 팁 -물론 실제로 검색 하는 문자 만 번역하면됩니다 .)

이 접근 방식은 알파벳에 대한 사전 지식이 없어도 모든 검색 문자열에 대해 작동하며 이는 큰 장점입니다.

검색 문자열에 작은 따옴표가 포함될 수있는 경우 위의 두 방법 모두 실패합니다.이 경우 상황이 더 복잡해집니다 .


감사! 또한 필요한 문자 만 번역하여 추가하는 것이 좋습니다. 성능이 무엇인지 궁금합니다. xpathPrepare ()는 한 번 이상 나타나는 문자를 다르게 처리 할 수 ​​있습니다 (예 : TEEEEEST 및 teeeeest를 얻음).
Aron Woost 2011

@AronWoost : 글쎄, 약간의 이득이있을 수 있습니다. 알아 내고 싶다면 벤치마킹하십시오. translate()- 자체가 얼마나 자주 각 문자를 반복 상관하지 않는다 translate(., 'EE', 'ee')절대적으로 동일합니다 translate(., 'E', 'e'). 추신 : @KirillPolishchuk에 찬성 투표하는 것을 잊지 마세요. 아이디어는 그의 것이 었습니다.
Tomalak 2011

2
System.Xml.XmlNodeList x = mydoc.SelectNodes ( "// * [contains (translate (text (), 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜÉÈÊÀÁÂÒÓÔÙÚÛÇÅÏÕÑŒ', 'abcdefghijklmnopqrstuvwxyz)");
Stefan Steiger 2013

1
아니요. "물론 실제로 검색하는 문자 만 번역하면됩니다 . " 부분을 ​​참조하십시오.
Tomalak 2013

61

더 아름다운:

/html/body//text()[contains(translate(., 'TES', 'tes'), 'test')]

4
+1 물론입니다. 그것은 내가 생각하지 못한 것입니다. (내 대답에 사용하겠습니다. 이것은 제가 작성한 원래 JavaScript 루틴보다 훨씬 낫습니다.)
Tomalak

4
그냥 변환하지 않을 TESTtest하고 휴가 Test그대로?
Muhammad Adeel Zahid

6
@MuhammadAdeelZahid-아니요, "T"를 "t"로, "E"를 "e"로 바꾸는 등 일대일 일치입니다.
Daniel Haley

수행하는 것이 더 명확 할 수 translate(., 'TES', 'tes')있습니다. 그렇게하면 사람들은 그것이 단어 번역이 아니라 문자 번역이라는 것을 깨닫게 될 것입니다.
mlissner

55

XPath 2.0 솔루션

  1. 사용 ) (소문자를 :

    /html/body//text()[contains(lower-case(.),'test')]

  2. 대소 문자를 구분하지 않는 플래그와 일치하는 matches () 정규식을 사용하십시오 .

    /html/body//text()[matches(.,'test', 'i')]


1
이 구문은 Firefox 및 Chrome에서 지원되지 않습니까? 방금 콘솔에서 시도했는데 둘 다 구문 오류를 반환합니다.
db

1
Firefox와 Chrome은 XPath 1.0 만 구현합니다.
kjhughes

8

예. 를 사용 translate하여 다음과 같이 일치시킬 텍스트를 소문자로 변환 할 수 있습니다 .

/html/body//text()[contains(translate(., 
                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                                      'abcdefghijklmnopqrstuvwxyz'),
                   'test')]

6

XPath 2.0을 사용하는 경우 contains ()에 대한 세 번째 인수로 데이터 정렬을 지정할 수 있습니다. 그러나 데이터 정렬 URI는 표준화되지 않으므로 세부 정보는 사용중인 제품에 따라 다릅니다.

이전에 translate ()를 사용하여 제공된 솔루션은 모두 26 자 영어 알파벳 만 사용한다고 가정합니다.

업데이트 : XPath 3.1은 대소 문자 구분없이 일치하는 표준 데이터 정렬 URI를 정의합니다.


3

내가 항상이 작업을 수행 한 방법은 XPath에서 "번역"기능을 사용하는 것입니다. 나는 그다지 예쁘다고 말하지는 않을 것이지만 올바르게 작동합니다.

/html/body//text()[contains(translate(.,'abcdefghijklmnopqrstuvwxyz',
                                        'ABCDEFGHIJKLOMNOPQRSTUVWXYZ'),'TEST')]

도움이 되었기를 바랍니다,

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.