如何用许多OR选项缩短长XPath表达式? [英] How to shorten long XPath expressions with many OR alternatives?

查看:192
本文介绍了如何用许多OR选项缩短长XPath表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正努力让Selenium通过大量可选的条件XPath,寻找可能匹配的元素 - 并将它传递给对象 elmnt code>。



目前,使用 OR 运算符( | code>),代码很快变得非常重复和详尽,尤其是当有很多可能的变化时。



在下面的例子中,唯一的变化是我开始寻找 h1 h2 h3 。其余部分是一样的。



pre $ 在[testString1,testString2,testString3]中为单词:

try:
elmnt = driver.find_element_by_xpath(

// h1 [text()[contains(。,'%s')]]%word +
/ follow:p+
|+
// h1 [text()[contains(。,'%s')]]%word +
/ following:span+

|+

// h2 [text()[contains(。,'%s')]] %word +
/ follow :: p+
|+
// h2 [text()[contains(。,'%s')]]%word +
/ following :: span+

|+

// h3 [text()[contains(。,'%s')]]%word +
/ following :: p+
|+
// h3 [text()[contains(。,'%s')]]%word +
/ following:span

).text
除外:
传递
else:
print elmnt
break

但是在我的实际代码中,我会看到更多的变体,包括 / following :: 中的各种节点类型,除了 p span 。问题:有什么方法可以简化(缩短)吗?



我的第一个希望能够做到这样的事情:

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

即可以将运算符烘焙到XPath表达式中,而不必像示例中那样使用完全详尽的字符串连接。如果是这样的话,这个想法可能会被应用于所有人。



然而,这似乎是不可能的。



解决方案是创建某种生成函数来创建整个xPath字符串,还是其他的东西?

>我会使用这个缩短的XPath(利用 self :: @ b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b pre $ // * [self :: h1或self :: h2或self :: h3] [contains(。,'%s')]%word
+ / following :: * [self :: p or self :: span]

注意这个测试 h1 h2 字符串值 > h3 包含变量的值(而不是直接文本节点的字符串值)。另外,如果要实际测试这些元素的字符串值是而不是包含 word ,请使用 [。='%s'] 改为。


I am working to get Selenium to go through a large number of alternative conditional XPaths, looking for elements that may match – and pass that on to the object elmnt.

Currently, using the OR operator (|), the code quickly gets very repetitive and exhaustive, especially when there are a lot of possible variations.

In the example below, the only variation is that I start looking for h1, h2, or h3. The rest is the same.

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

But in my actual code, I will be looking at even more variations, including various node types in /following:: besides p and span.

Question: Is there some way to simplify (shorten) this?

My first hope was that it'd be possible to do something like:

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

i.e. that the or operators could be "baked into" the XPath expression without having to use fully exhaustive string concatenations like in the example. And if so, that idea could've been applied across the board.

However, this does not seem to be possible.

Is the solution to create some sort of generative function that creates the entire xPath string, or something else?

解决方案

I would use this shortened XPath (leveraging the self:: axis as recommended by @alecxe in a comment):

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

Note that this tests that the string value of h1, or h2, or h3 contains the value of the word variable (rather than the string value of the immediate text nodes). Also, if you want to actually test that the string value of those elements are rather than contains word, use [.='%s'] instead.

这篇关于如何用许多OR选项缩短长XPath表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆