如何使用许多OR替代方法缩短长XPath表达式?

时间:2016-06-19 18:25:25

标签: python html xml selenium xpath

我正在努力让Selenium经历大量替代条件XPath,寻找可能匹配的元素 - 并将其传递给对象elmnt

目前,使用OR运算符(|),代码很快就会变得非常重复和详尽,尤其是在存在大量可能的变体时。

在下面的示例中,唯一的变化是我开始寻找h1h2h3。其余的都一样。

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

但在我的实际代码中,除了/following::p之外,我还会考虑更多变体,包括span中的各种节点类型。

问题:有没有办法简化(缩短)这个?

我的第一个希望是可以做类似的事情:

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

即。 or运算符可以“烘焙到”XPath表达式,而不必像示例中那样使用完全详尽的字符串连接。如果是这样,那个想法可以全面应用。

然而,这似乎不可能。

解决方案是创建某种生成函数来创建整个xPath字符串,还是别的什么?

1 个答案:

答案 0 :(得分:2)

我会使用这个缩短的XPath(根据@alecxe in a comment的建议利用self::轴):

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

请注意,这会测试h1h2h3字符串值是否包含word变量的值(而不是直接文本节点的字符串值)。另外,如果您想要实际测试这些元素的字符串值而不是包含 word,请改用[.='%s']