Büyük / küçük harfe duyarlı olmayan XPath () içerir mi?


95

DOM'umun tüm metin düğümleri üzerinde çalışıyorum ve nodeValue'nun belirli bir dize içerip içermediğini kontrol ediyorum.

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

Bu, büyük / küçük harfe duyarlıdır. Ancak, ben de yakalamak istiyorum Test, TESTya TesT. Bu XPath ile mümkün mü (JavaScript'te)?

Yanıtlar:


112

Bu XPath 1.0 içindir. Ortamınız XPath 2.0'ı destekliyorsa, buraya bakın .


Evet. Mümkün, ama güzel değil.

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

Bu, alfabenin önceden bilindiği arama dizeleri için işe yarar. Görmeyi beklediğiniz tüm aksanlı karakterleri ekleyin.


Yapabiliyorsanız, sizi ilgilendiren metni <span>, HTML oluştururken belirli bir sınıfa sahip bir metnin içine almak gibi başka yollarla işaretleyin . Bu tür şeyleri XPath ile bulmak, eleman metnindeki alt dizelerden çok daha kolaydır.

Bu bir seçenek değilse, JavaScript'in (veya XPath yürütmek için kullandığınız başka bir ana bilgisayar dilinin) dinamik bir XPath ifadesi oluşturmanıza yardımcı olmasına izin verebilirsiniz:

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'un cevabına şapka ipucu - elbette sadece gerçekten aradığınız karakterleri çevirmeniz gerekiyor .)

Bu yaklaşım, büyük bir artı olan alfabe hakkında önceden bilgi sahibi olmayı gerektirmeden herhangi bir arama dizisi için işe yarayacaktır.

Arama dizeleri tek tırnak içerebildiği zaman yukarıdaki yöntemlerin ikisi de başarısız olur, bu durumda işler daha karmaşık hale gelir .


Teşekkürler! Ek olarak, sadece gerekli karakterleri çevirmek güzel. Performans kazancının ne olduğunu merak ediyorum. XpathPrepare () işlevinin birden fazla kez görünen karakterleri farklı şekilde işleyebileceğini unutmayın (örneğin, TEEEEEST ve teeeeest alırsınız).
Aron Woost

@AronWoost: Bazı kazançlar olabilir, öğrenmek için hevesliyseniz, sadece kıyaslayın. translate()kendisi her karakteri ne sıklıkta tekrarladığınızla ilgilenmez - translate(., 'EE', 'ee')kesinlikle eşdeğerdir translate(., 'E', 'e'). Not: @KirillPolishchuk'a oy vermeyi unutmayın, fikir onundu.
Tomalak

2
System.
Stefan Steiger

1
Hayır. "Elbette sadece gerçekten aradığınız karakterleri çevirmeniz gerekiyor" bölümüne bakın.
Tomalak

62

Daha güzel:

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

4
+1 Kesinlikle. Bu düşünmediğim bir şey. (Bunu
cevabımda

4
sadece dönüşüp TESTolduğu gibi testgitmez Testmi?
Muhammad Adeel Zahid

7
@MuhammadAdeelZahid - Hayır, "T" yi "t" ile, "E" yi "e" ile değiştiriyor, vb. Bire bir eşleşme.
Daniel Haley

Yapması daha net olabilir translate(., 'TES', 'tes'). Bu şekilde insanlar bunun bir kelime çevirisi olmadığını, bunun bir harf çevirisi olduğunu anlayacaklar.
mlissner

veya 'EST,' est ', ancak (biraz şifreli de olsa) aranan terimin bir kısmının
eşlemede

56

XPath 2.0 Çözümleri

  1. Küçük harf () kullanın :

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

  2. Büyük / küçük harfe duyarlı olmayan bayrağıyla match () normal ifade eşleşmesini kullanın :

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


1
Bu sözdizimi Firefox ve Chrome'da desteklenmiyor mu? Konsolda denedim ve ikisi de sözdizimi hatası veriyor.
db

1
Firefox ve Chrome yalnızca XPath 1.0'ı uygular.
kjhughes

bunun beklendiği gibi çalışacağını nereden doğrulayabilirim?
Ankit Gupta

@AnkitGupta: XPath 2.0'ı destekleyen herhangi bir çevrimiçi veya çevrimdışı araç elbette bu yanıtı doğrulamak için kullanılabilir, ancak (1) araç önerileri SO'da konu dışıdır ve (2) 56 olumlu oy, 0 olumsuz oy ve hayır altı yıldan fazla bir süredir muhalif yorumlar yaparsanız, bu cevabın doğru olduğundan oldukça emin olabilirsiniz. ;-)
kjhughes

8

Evet. translateEşleştirmek istediğiniz metni aşağıdaki gibi küçük harfe dönüştürmek için kullanabilirsiniz :

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

6

XPath 2.0 kullanıyorsanız, contains () için üçüncü bağımsız değişken olarak bir harmanlama belirtebilirsiniz. Ancak, harmanlama URI'leri standartlaştırılmadığından ayrıntılar, kullandığınız ürüne bağlıdır.

Daha önce translate () kullanarak verilen çözümlerin hepsinin yalnızca 26 harfli İngilizce alfabe kullandığınızı varsaydığını unutmayın.

GÜNCELLEME: XPath 3.1, büyük / küçük harf görmeyen eşleştirme için standart bir harmanlama URI'sı tanımlar.


4

Bunu her zaman yaptığım yol XPath'deki "tercüme et" işlevini kullanmaktı. Çok güzel olduğunu söylemeyeceğim ama doğru çalışıyor.

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

Bu yardımcı olur umarım,

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.