特定の文字列を含む属性をどのように照合できますか?


442

属性に複数の単語が含まれている場合、属性でノードを選択するときに問題が発生します。例えば:

<div class="atag btag" />

これは私のxpath式です:

//*[@class='atag']

式は

<div class="atag" />

前の例ではありません。どうすれば選択できます<div>か?


9
「atag btag」は2つではなく1つの属性であることを指摘しておく価値はあります。xpathで部分文字列マッチングを実行しようとしています。
skaffman 2009

3
はい、そうです。それが私が望んでいることです。
crazyrails 2009


1
これが、CSSセレクターを使用する必要がある理由です... div.atagまたはdiv.btag。文字列マッチングではなく、非常にシンプルで、WAYが高速です(ブラウザでのサポートが向上しています)。XPath(HTMLに対する)は、含まれているテキストによる要素の検索やDOMナビゲーションに役立つものに委任する必要があります。
JeffC 2018年

回答:


486

次に、classNameに含まれるdiv要素を見つける例を示しますatag

//div[contains(@class, 'atag')]

次に、classNameにatagand が含まれるdiv要素を見つける例を示しますbtag

//div[contains(@class, 'atag') and contains(@class ,'btag')]

ただし、のような部分一致も検出されますclass="catag bobtag"

部分一致が必要ない場合は、下のbobinceの回答を参照してください。


123
@Redbeard:文字通りの答えですが、通常、クラスマッチングソリューションが目指すべきものではありません。特に<div class="Patagonia Halbtagsarbeit">、ターゲット文字列を含むが、指定されたクラスのdivではないと一致します。
11

3
これは単純なシナリオで機能しますが、この回答を、チェックする属性値をほとんどまたはまったく制御せずに幅広いコンテキストで使用する場合は注意してください。正解はボビンスです。
Oliver

16
申し訳ありませんが、これはクラスとは一致しません。部分文字列と一致します
Timo Huovinen '20

5
また、<div class = "annatag bobtag">も検出されるため、明らかに間違っています。
Alexei Vinogradov 2016

6
問題は、「特定の文字列を含む」ではなく「特定のクラスに一致する」でした
Alsatian

303

mjvの答えは良いスタートですが、atagがリストされている最初のクラス名でない場合は失敗します。

通常のアプローチはかなり扱いにくいです:

//*[contains(concat(' ', @class, ' '), ' atag ')]

これは、クラスがスペースでのみ区切られていて、他の形式の空白ではない場合に機能します。これはほとんどの場合当てはまります。そうでない場合は、さらに扱いにくくする必要があります。

//*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')]

(クラス名のようにスペースで区切られた文字列で選択するのは、CSS3の '[class〜= "atag"]'のような特定のXPath関数がないのは驚くべき一般的なケースです。)


57
ええと、xpathにはいくつかの修正が必要です
Randy L

13
@Redbeard supra123の答えは、「atagnumbertwo」のような選択したくないcssクラスがある場合、問題になる可能性があります(:
drevicko

7
@crazyrails:この答えを正しい答えとして受け入れてもらえますか?これは、将来の検索ユーザーが質問で説明されている問題の正しい解決策を特定するのに役立ちます。ありがとうございました!
オリバー

2
@ cha0site:はい、XPath 2.0以降では可能でした。この回答は、XPath 2.0が公式になる前に書かれました。stackoverflow.com/a/12165032/423105またはstackoverflow.com/a/12165195/423105を
LarsH

1
私のようではなく、この例で探しているクラスの周りのスペースを削除してください。それらは実際に重要です。さもなければそれは働くように見えるかもしれませんが目的を無効にします。
CTS_AE 2017


38

編集:完全なトークンのレベルで比較が確実に行われるようにするトリックとともにstart-withではなくcontainsを使用するbobinceのソリューションを参照してください(「atag」パターンが別の「タグ」の一部として検出されないようにします)。

"atag btag"はクラス属性の奇数の値ですが、それでもそれよりも少ないことを試してください:

//*[starts-with(@class,"atag")]

XPathエンジンがstarts-withコマンドをサポートしている場合、これを使用できます。たとえば、JVM 6は私が覚えている限りこれをサポートしていません
Mohamed Faramawi

10
@mjv:CSSクラス属性が複数の値を指定することは一般的です。これがCSSの完成です。
skaffman 2009

7
@mjvその名前がクラス属性の先頭に表示されることは保証できません。
アランクルーガー、

@thuktun @skaffman。ありがとう、素晴らしいコメント。私はそれに応じてボビンスソリューションに「リダイレクト」しました。
mjv 2009年

上記と同等の<div class = "btag atag">では機能しません
Alexei Vinogradov

30

動作する2.0 XPath:

//*[tokenize(@class,'\s+')='atag']

または変数を使って:

//*[tokenize(@class,'\s+')=$classname]

@class複数の要素がある場合、これはどのように機能しますか?単語のリストを返し、それを文字列と比較すると、カーディナリティ正しくないため失敗します
Alexis Wilke 2014

3
@AlexisWilke-仕様から(w3.org/TR/xpath20/#id-general-comparisons):一般的な比較は、任意の長さのオペランドシーケンスに適用できる実存的に定量化された比較です。私が試したすべての2.0プロセッサで動作します。
Daniel Haley

1
また、XPath 3.1ではこれを次のように簡略化できます//*[tokenize(@class)=$classname]
Michael Kay

1
そして、完全を期すために、スキーマ対応のXPathプロセッサを使用できる幸運で、@ classにリスト値型がある場合は、単純に次のように書くことができます//*[@class=$classname]
Michael Kay

21

関心のあるクラス名が別の可能なクラス名の部分文字列ではないと想定できる場合、ボビンスの答えは非常に複雑になる可能性があることに注意してください。これに該当する場合は、contains関数を使用して部分文字列マッチングを使用できます。以下は、クラスにサブストリング「atag」を含むすべての要素に一致します。

//*[contains(@class,'atag')]

上記の仮定が満たされない場合、部分文字列の一致は意図しない要素と一致します。この場合、単語の境界を見つける必要があります。スペース区切り文字を使用してクラス名の境界を見つけることにより、bobinceの2番目の答えは完全一致を見つけます。

//*[contains(concat(' ', normalize-space(@class), ' '), ' atag ')]

これは一致しatag、一致しませんmatag


これは私が探していたソリューションです。class = 'hello test world'で 'test'が明確に検出され、 'hello test-test world'と一致しません。XPath 1.0のみを使用し、RegExを使用していないため、これは機能する唯一のソリューションです。
Jan Stanicek 2016年

7

bobinceの答えに追加するには...使用しているツール/ライブラリがXpath 2.0を使用している場合は、次のようにすることもできます。

//*[count(index-of(tokenize(@class, '\s+' ), $classname)) = 1]

index-of()は文字列内で一致する各インデックスのシーケンスを返すため、count()は明らかに必要です。


1
$classname変数を引用符で囲まないことを意図していたと思いますか?というのも、それは文字列だからです。
Alexis Wilke 2014

1
最後に、'$classname'もちろん、文字列リテラルは別として、getElementsByClassName ...の正しい(JavasScript互換)実装。
Joel Mellon

1
これは非常に複雑です。正しいXPath 2.0の回答については、@ DanielHaleyの応答を参照してください。
Michael Kay


0

Ranorex Studio 9.0.1のソリューションを探してここに来ました。contains()はまだありません。代わりに、次のように正規表現を使用できます。

div[@class~'atag']

-1

共通のURLを含むリンクについては、変数でコンソールする必要があります。その後、順番に試してください。

webelements allLinks=driver.findelements(By.xpath("//a[contains(@href,'http://122.11.38.214/dl/appdl/application/apk')]"));
int linkCount=allLinks.length();
for(int i=0; <linkCount;i++)
{
    driver.findelement(allLinks[i]).click();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.