web-dev-qa-db-fra.com

xpath insensible à la casse contient () possible?

J'exécute tous les nœuds de texte de mon DOM et vérifie si la propriété nodeValue contient une certaine chaîne.

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

Ceci est sensible à la casse. Cependant, je veux aussi attraper Test, TEST oder TesT. Est-ce possible avec XPath (en JavaScript)?

81
Aron Woost

Ceci est pour XPath 1.0. Si votre environnement prend en charge XPath 2.0, voir here .


Oui. Possible, mais pas beau.

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

Si vous le pouvez, marquez les portions de texte qui vous intéressent avec un autre moyen, comme les enfermer dans un <span> qui a une certaine classe.

Si ce n'est pas possible, JavaScript peut vous aider à créer une expression XPath appropriée:

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')]"

(Pointe du chapeau à réponse de @ KirillPolishchuk - bien sûr, vous ne devez traduire que les caractères pour lesquels vous êtes recherche)

95
Tomalak

Plus beau:

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

Solutions XPath 2.0

  1. Utilisez minuscule () :

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

  2. Utilisez matches () correspondant au regex avec son drapeau ne respectant pas la casse:

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

47
kjhughes

Oui. Vous pouvez utiliser translate pour convertir le texte que vous souhaitez faire correspondre en minuscule comme suit:

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

Si vous utilisez XPath 2.0, vous pouvez spécifier un classement comme troisième argument de contains (). Cependant, les URI de classement ne sont pas normalisés, donc les détails dépendent du produit que vous utilisez.

Notez que les solutions données précédemment à l'aide de translate () supposent toutes que vous utilisez uniquement l'alphabet anglais de 26 lettres.

PDATE: XPath 3.1 définit un URI de classement standard pour la mise en correspondance sans distinction de la casse.

6
Michael Kay

J'ai toujours fait cela en utilisant la fonction "traduction" de XPath. Je ne dirai pas que c'est très joli mais cela fonctionne correctement.

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

j'espère que cela t'aides,

3
Marvin Smit