¿Cómo acortar las expresiones XPath largas con muchas alternativas OR?

Estoy trabajando para que Selenium pase por un gran número de XPath condicionales alternativas, en busca de elementos que puedan coincidir , y que se lo transmitan al objeto elmnt .

Actualmente, al utilizar el operador OR ( | ), el código se vuelve repetitivo y exhaustivo rápidamente, especialmente cuando hay muchas variaciones posibles.

En el siguiente ejemplo, la única variación es que comienzo a buscar h1 , h2 o h3 . El rest es el mismo.

 for word in ["testString1", "testString2", "testString3"]: try: elmnt = driver.find_element_by_xpath( ( "//h1[text()[contains(., '%s')]]" % word + "/following::p" + "|" + "//h1[text()[contains(., '%s')]]" % word + "/following::span" + "|" + "//h2[text()[contains(., '%s')]]" % word + "/following::p" + "|" + "//h2[text()[contains(., '%s')]]" % word + "/following::span" + "|" + "//h3[text()[contains(., '%s')]]" % word + "/following::p" + "|" + "//h3[text()[contains(., '%s')]]" % word + "/following::span" ) ).text except: pass else: print elmnt break 

Pero en mi código real, veré aún más variaciones, incluidos varios tipos de nodo en /following:: además de p y span .

Pregunta: ¿Hay alguna manera de simplificar (acortar) esto?

Mi primera esperanza era que sería posible hacer algo como:

 "//[h1|h2|h3][text()[contains(., '%s')]]" % word 

es decir, que los operadores or pueden ser “incorporados” a la expresión XPath sin tener que usar concatenaciones de cadenas completamente exhaustivas como en el ejemplo. Y si es así, esa idea podría haber sido aplicada en todos los ámbitos.

Sin embargo, esto no parece ser posible.

¿La solución es crear algún tipo de función generativa que cree la cadena xPath completa o algo más?

Yo usaría este XPath acortado (aprovechando el self:: axis recomendado por @alecxe en un comentario ):

  "//*[self::h1 or self::h2 or self::h3][contains(., '%s')]" % word + "/following::*[self::p or self::span]" 

Tenga en cuenta que esto prueba que el valor de cadena de h1 o h2 o h3 contiene el valor de la word variable (en lugar del valor de cadena de los nodos de texto inmediato). Además, si desea probar realmente que el valor de la cadena de esos elementos es más que una word , use [.='%s'] lugar.