मैं एक विशेषता पर कैसे मेल कर सकता हूं जिसमें एक निश्चित स्ट्रिंग है?


442

जब विशेषताओं में एक से अधिक शब्द होते हैं, तो मुझे विशेषता द्वारा नोड्स चुनने में समस्या होती है। उदाहरण के लिए:

<div class="atag btag" />

यह मेरी xpath अभिव्यक्ति है:

//*[@class='atag']

अभिव्यक्ति के साथ काम करता है

<div class="atag" />

लेकिन पिछले उदाहरण के लिए नहीं। मैं कैसे चयन कर सकता हूं <div>?


9
यह इंगित करने के लायक है, मुझे लगता है, कि "एटग बीटीएजी" एक ही विशेषता है, दो नहीं। आप xpath में मेल खाते सबस्ट्रिंग करने की कोशिश कर रहे हैं।
स्केफमैन

3
हाँ, आप सही हैं - जो मैं चाहता हूँ।
पागलखाने


1
यही कारण है कि आपको एक सीएसएस चयनकर्ता ... div.atagया का उपयोग करना चाहिए div.btag। सुपर सरल, स्ट्रिंग मिलान नहीं, और तेजी से (और ब्राउज़रों में बेहतर समर्थित)। XPath (HTML के विरुद्ध) को उस चीज़ के लिए पुनःप्राप्त किया जाना चाहिए जो इसके लिए उपयोगी है ... इसमें निहित पाठ द्वारा और DOM नेविगेशन के लिए तत्व खोजना है।
जेफसी

जवाबों:


486

यहां एक उदाहरण दिया गया है जिसमें उन दिव्यांग तत्वों को पाया गया है जिनके वर्गनाम में शामिल हैं atag:

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

यहां एक उदाहरण दिया गया है जिसमें उन दिव्यांग तत्वों को पाया गया है जिनके वर्गनाम में शामिल हैं atagऔर btag:

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

हालांकि, यह भी आंशिक मैचों की तरह ही मिलेगा class="catag bobtag"

यदि आप आंशिक मैच नहीं चाहते हैं, तो नीचे बॉबिन का उत्तर देखें।


123
@Redbeard: यह एक शाब्दिक उत्तर है, लेकिन आमतौर पर क्लास-मिलान समाधान के लिए क्या नहीं करना चाहिए। विशेष रूप से यह मेल खाएगा <div class="Patagonia Halbtagsarbeit">, जिसमें लक्ष्य तार होते हैं लेकिन दिए गए वर्गों के साथ एक तलाक नहीं है।
22

3
यह सरल परिदृश्यों के लिए काम करेगा - लेकिन यह देखें कि क्या आप इस उत्तर का उपयोग व्यापक संदर्भों में करना चाहते हैं जो आपके द्वारा जाँची जा रही विशेषता मानों पर कम या कोई नियंत्रण नहीं है। सही जवाब है बोबिन्स।
ओलिवर

16
क्षमा करें, यह एक वर्ग से मेल नहीं खाता, यह एक विकल्प से मेल खाता है
टिमो हुओवेनन

5
यह स्पष्ट रूप से गलत है क्योंकि यह भी पाता है: <div class = "annatag bobtag"> जिसे यह नहीं करना चाहिए।
अलेक्सेई विनोग्रादोव

6
सवाल यह था कि "एक निश्चित स्ट्रिंग शामिल है" "एक निश्चित वर्ग से मेल नहीं खाता"
अल्साटियन

303

mjv का उत्तर एक अच्छी शुरुआत है, लेकिन असफल होगा यदि atag सूचीबद्ध प्रथम श्रेणी का नाम नहीं है।

सामान्य दृष्टिकोण बल्कि अस्पष्ट है:

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

यह तब तक काम करता है जब तक कक्षाएं केवल रिक्त स्थान द्वारा अलग हो जाती हैं, न कि व्हाट्सएप के अन्य रूपों में। यह लगभग हमेशा मामला है। यदि यह नहीं हो सकता है, तो आपको इसे अभी भी अधिक अस्पष्ट बनाना होगा:

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

(क्लास-लाइक स्पेस-अलग स्ट्रिंग्स द्वारा चयन करना एक ऐसा सामान्य मामला है, यह आश्चर्यजनक है कि इसके लिए कोई विशिष्ट XPath फ़ंक्शन नहीं है, जैसे CSS3 का '[वर्ग ~ = "atag"]'।)


58
bah, xpath को कुछ सुधारों की आवश्यकता है
रैंडी एल

13
@Redbeard supra123 का उत्तर समस्याग्रस्त है यदि "atagnumbertwo" जैसी कोई css क्लास है जिसे आप सेलेक्ट नहीं करना चाहते हैं, हालाँकि मैं मानता हूँ कि यह संभव नहीं है: (
drevicko

7
@ क्रेजीफ्रिल्स: क्या आप इस उत्तर को सही उत्तर मान सकते हैं? यह भविष्य के खोजकर्ताओं को आपके प्रश्न द्वारा वर्णित समस्या के सही समाधान की पहचान करने में मदद करेगा। धन्यवाद!
ओलिवर

2
@ cha0site: हाँ वे XPath 2.0 और निम्नलिखित में कर सकते हैं। XPath 2.0 के आधिकारिक होने से पहले यह उत्तर लिखा गया था। देखें stackoverflow.com/a/12165032/423105 या stackoverflow.com/a/12165195/423105
LarsH

1
मेरे जैसा मत बनो और इस उदाहरण में जिस कक्षा की तलाश कर रहे हो उसके आसपास के रिक्त स्थान हटा दो; वे वास्तव में महत्वपूर्ण हैं। अन्यथा यह काम लग सकता है लेकिन उद्देश्य को हरा देता है।
CTS_AE

40

इसे इस्तेमाल करे: //*[contains(@class, 'atag')]


यदि वर्ग का नाम हो तो क्या होगा grabatagonabag? (संकेत: यह अभी भी मेल खाएगा।)
वेन

38

संपादित करें : bobince के समाधान जो का उपयोग करता है को देखने के शामिल करने के बजाय शुरू के साथ , एक चाल के साथ सुनिश्चित करने के लिए तुलना एक पूरा टोकन के स्तर पर किया जाता ( 'ATAG' पैटर्न ऐसा न हो कि एक और 'टैग' के हिस्से के रूप में पाया जा)।

"atag btag" वर्ग विशेषता के लिए एक अजीब मूल्य है, लेकिन कभी कम नहीं, कोशिश करें:

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

यदि आपका XPath इंजन स्टार्ट-विथ कमांड का समर्थन करता है, तो आप इसका उपयोग कर सकते हैं, उदाहरण के लिए JVM 6 इसका समर्थन नहीं करता है जहाँ तक मुझे याद है
मोहम्मद फ़रामवी

10
@mjv: कई गुणों को निर्दिष्ट करने के लिए सीएसएस वर्ग विशेषता के लिए यह सामान्य है। कि सीएसएस कैसे किया जाता है।
स्केफमैन

7
@mjv आप इस बात की गारंटी नहीं दे सकते हैं कि वर्ग विशेषता के प्रारंभ में वह नाम दिखाई देगा।
एलन क्रुएगर

@thuktun @skaffman धन्यवाद, शानदार टिप्पणियाँ। मैं तदनुसार समाधान के लिए बोबिसन को 'पुनर्निर्देशित' करता हूं।
mjv

<Div class = "btag atag"> के लिए काम नहीं करता है, जो कि ऊपर के बराबर है
अलेक्सई विनोग्रादोव

30

एक 2.0 XPath जो काम करता है:

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

या एक चर के साथ:

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

@classएक से अधिक तत्व होने पर यह कैसे काम कर सकता है ? क्योंकि यह शब्दों की एक सूची वापस करने जा रहा है और इसकी तुलना एक स्ट्रिंग में गलत कार्डिनलिटी के साथ विफल हो जाती है ।
एलेक्सिस विल्के

3
@AlexisWilke - युक्ति से ( w3.org/TR/xpath20/#id-general-comparisons ): सामान्य तुलना अस्तित्वगत मात्रा में तुलनात्मक होती है जो किसी भी लंबाई के ऑपरेंड अनुक्रमों पर लागू की जा सकती है। यह मैंने कोशिश की है कि हर 2.0 प्रोसेसर में काम किया है।
डैनियल हैली

1
ध्यान दें, XPath 3.1 में यह सरल किया जा सकता है//*[tokenize(@class)=$classname]
माइकल Kay

1
और पूर्णता के लिए, यदि आप एक स्कीमा-जागरूक XPath प्रोसेसर का उपयोग करने के लिए पर्याप्त भाग्यशाली हैं, और अगर @class में एक सूची-मूल्यवान प्रकार है, तो आप बस लिख सकते हैं//*[@class=$classname]
माइकल Kay

21

ध्यान रखें कि बॉबिन का उत्तर अत्यधिक जटिल हो सकता है यदि आप यह मान सकते हैं कि जिस वर्ग का नाम आप में रुचि रखते हैं, वह किसी अन्य संभावित वर्ग नाम का विकल्प नहीं है । यदि यह सही है, तो आप बस फ़ंक्शन के माध्यम से सबस्ट्रिंग मिलान का उपयोग कर सकते हैं। निम्नलिखित किसी भी तत्व से मेल खाएगा, जिसकी कक्षा में 'एटैग' का विकल्प है:

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

यदि ऊपर की धारणा धारण नहीं करती है, तो एक विकल्प मिलान उन तत्वों से मेल खाएगा जो आप इरादा नहीं करते हैं। इस मामले में, आपको शब्द सीमाएं ढूंढनी होंगी। कक्षा के नाम की सीमाओं को खोजने के लिए अंतरिक्ष सीमांकक का उपयोग करके, बॉबिन्स का दूसरा उत्तर सटीक मैचों को ढूंढता है:

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

यह मैच होगा atagऔर नहीं matag


यह वह उपाय है जिसकी मुझे तलाश थी। यह कक्षा = 'हैलो टेस्ट वर्ल्ड' में स्पष्ट रूप से 'टेस्ट' पाता है और 'हेलो टेस्ट-टेस्ट वर्ल्ड' से मेल नहीं खाता है। चूंकि मैं केवल XPath 1.0 का उपयोग करता हूं और कोई RegEx नहीं है, यह केवल समाधान है जो काम करता है।
14

7

बॉबसन के उत्तर में जोड़ने के लिए ... यदि आप Xpath 2.0 का उपयोग करते हुए जो भी उपकरण / पुस्तकालय का उपयोग करते हैं, आप यह भी कर सकते हैं:

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

गणना () को स्पष्ट रूप से आवश्यक है क्योंकि इंडेक्स-इन () प्रत्येक इंडेक्स का एक क्रम देता है जिसका स्ट्रिंग में एक मैच होता है।


1
मुझे लगता है कि आप $classnameउद्धरण के बीच चर नहीं डाल सकते हैं ? क्योंकि जैसा है, वैसा ही एक तार है।
एलेक्सिस विल्के

1
अंत में, getElementsByClassName का एक सही (JavasScript संगत) कार्यान्वयन ... '$classname'निश्चित रूप से स्ट्रिंग शाब्दिक से अलग ।
जोएल मेलन

1
यह स्थूल रूप से अधिक जटिल है। सही XPath 2.0 के जवाब के लिए @ डैनियल हैले की प्रतिक्रिया देखें।
माइकल


0

मैं यहां Ranorex Studio 9.0.1 के लिए समाधान खोज रहा हूं। वहाँ () अभी तक नहीं है। इसके बजाय हम regex का उपयोग कर सकते हैं जैसे:

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();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.