Verwenden von XPATH zum Suchen von Text mit & nbsp;


120

Ich verwende den XPather-Browser , um meine XPATH-Ausdrücke auf einer HTML-Seite zu überprüfen.

Mein Endziel ist es, diese Ausdrücke in Selenium zum Testen meiner Benutzeroberflächen zu verwenden.

Ich habe eine HTML-Datei mit einem ähnlichen Inhalt erhalten:

<tr>
  <td> abc </ td>
  <td> </ td>
</ tr>

Ich möchte einen Knoten mit einem Text auswählen, der die Zeichenfolge " &nbsp;" enthält.

Mit einer normalen Zeichenfolge wie "abc" gibt es kein Problem. Ich benutze einen XPATH ähnlich wie //td[text()="abc"].

Wenn ich es mit einem XPATH versuche //td[text()="&nbsp;"], gibt es nichts zurück. Gibt es eine spezielle Regel für Texte mit " &"?


Gibt Ihre tatsächliche XSL-Umwandlung nichts zurück? Oder nur Xpather?
Zack The Human

Antworten:


89

Es scheint, dass OpenQA , Leute hinter Selenium, dieses Problem bereits angesprochen haben. Sie definierten einige Variablen, um explizit mit Leerzeichen übereinzustimmen. In meinem Fall muss ich einen ähnlichen XPATH verwenden //td[text()="${nbsp}"].

Ich habe hier den Text von OpenQA zu diesem Thema wiedergegeben ( hier zu finden ):

HTML normalisiert Leerzeichen innerhalb von Elementen automatisch, ignoriert führende / nachfolgende Leerzeichen und konvertiert zusätzliche Leerzeichen, Tabulatoren und Zeilenumbrüche in ein einzelnes Leerzeichen. Wenn Selenium Text aus der Seite liest, versucht es, dieses Verhalten zu duplizieren, sodass Sie alle Registerkarten und Zeilenumbrüche in Ihrem HTML-Code ignorieren und Aussagen treffen können, die darauf basieren, wie der Text beim Rendern im Browser aussieht. Dazu ersetzen wir alle nicht sichtbaren Leerzeichen (einschließlich des nicht unterbrechenden Leerzeichens " &nbsp;") durch ein einzelnes Leerzeichen. Alle sichtbaren Zeilenumbrüche ( <br>, <p>und <pre>formatiert neue Linien) sollte beibehalten werden.

Wir verwenden dieselbe Normalisierungslogik für den Text von HTML-Selenese-Testfalltabellen. Dies hat eine Reihe von Vorteilen. Zunächst müssen Sie nicht auf die HTML-Quelle der Seite schauen, um herauszufinden, wie Ihre Aussagen lauten sollten. " &nbsp;" Symbole sind für den Endbenutzer unsichtbar, sodass Sie sich beim Schreiben von Selenese-Tests keine Sorgen machen müssen. (Sie müssen keine " &nbsp;" Markierungen in Ihren Testfall einfügen, um Text in ein Feld zu versetzen, das " &nbsp;" enthält .) Sie können auch zusätzliche Zeilenumbrüche und Leerzeichen in Ihre Selenese- <td>Tags einfügen . Da wir im Testfall dieselbe Normalisierungslogik verwenden wie im Text, können wir sicherstellen, dass Zusicherungen und der extrahierte Text genau übereinstimmen.

Dies ist in den seltenen Fällen ein Problem, in denen Sie wirklich zusätzliche Leerzeichen in Ihren Testfall einfügen möchten / müssen. Beispielsweise müssen Sie möglicherweise Text in ein Feld wie das folgende eingeben: " foo ". Wenn Sie jedoch einfach <td>foo </td>in Ihren Selenese-Testfall schreiben , ersetzen wir Ihre zusätzlichen Leerzeichen durch nur ein Leerzeichen.

Dieses Problem hat eine einfache Problemumgehung. Wir haben eine Variable in Selenese definiert ${space}, deren Wert ein einzelnes Leerzeichen ist. Sie können ${space}Folgendes verwenden , um ein Leerzeichen einzufügen, das nicht automatisch gekürzt wird : <td>foo${space}${space}${space}</td>. Wir haben auch eine Variable hinzugefügt ${nbsp}, mit der Sie ein nicht unterbrechendes Leerzeichen einfügen können.

Beachten Sie, dass XPaths Leerzeichen nicht wie wir normalisieren. Wenn Sie einen XPath wie schreiben müssen, //div[text()="hello world"]der HTML- Code des Links jedoch wirklich " hello&nbsp;world" ist, müssen Sie ein echtes " &nbsp;" in Ihren Selenese-Testfall einfügen, damit er übereinstimmt : //div[text()="hello${nbsp}world"].


1
OpenQA Link wird nicht mehr erfolgreich
geladen

1
Ich möchte nur darauf hinweisen, dass $ {nbsp} in Selenium- oder Chrome-Entwicklertools für mich nicht funktioniert und auch nicht \u00a0. Was für mich funktionierte, war die Eingabe eines nicht unterbrechenden Leerzeichens auf dem Mac Alt+Shift+Space. Web-Suche sagt Alt+0160auf Windows.
Zyniker

25

Ich habe festgestellt, dass ich die Übereinstimmung herstellen kann, wenn ich einen fest codierten, nicht unterbrechenden Bereich (U + 00A0) eingebe, indem ich unter Windows Alt + 0160 zwischen den beiden Anführungszeichen eingebe ...

//table[@id='TableID']//td[text()=' ']

arbeitete für mich mit dem speziellen Char.

Soweit ich weiß, kann der XPath 1.0-Standard keine Unicode-Zeichen maskieren. In XPath 2.0 scheint es Funktionen dafür zu geben, aber es sieht so aus, als würde Firefox dies nicht unterstützen (oder ich habe etwas falsch verstanden). Sie haben also mit lokaler Codepage zu tun. Hässlich, ich weiß.

Eigentlich sieht es so aus, als ob der Standard sich auf die Programmiersprache mit XPath verlässt, um die richtige Unicode-Escape-Sequenz bereitzustellen ... Also habe ich irgendwie das Richtige getan.


Bei Verwendung von Xpather 1.4.1 in Firefox 2 liefert // td [text () = ''] keine Ergebnisse.
Zack The Human

Es tut uns leid. Es funktioniert nicht bei mir. Mein Endziel ist es, es in Selen für die Tests meiner Webschnittstellen zu verwenden. Selenium selbst hält die Testausdrücke in einer XML-Struktur und die Alt Windows-Typisierung scheint im Weg verloren zu sein. Auch meine & # 160; Gibt als in XML zurück.
Bergeroy

Zack, wie ich geschrieben habe, müssen Sie das Leerzeichen zwischen den beiden Anführungszeichen durch das von Alt + 0160 (auf dem Ziffernblock) erzeugte Zeichen ersetzen.
PhiLho

4
$col = $xpath->query("//p[text()=\"\xC2\xA0\"]");
Ich muss

@Bergory Dies funktioniert mit Winkelmesser mit Selenium-Treiber
Damian Green


2

Beachten Sie, dass ein standardkonformen XML - Prozessor wird alle Entitätsverweise andere als XML fünf Standard diejenigen ersetzt hat ( &amp;, &gt;, &lt;, &apos;, &quot;) mit dem entsprechenden Zeichen in der Zielcodierung durch die Zeit , XPath - Ausdrücke ausgewertet werden. Angesichts dieses Verhaltens sind die Vorschläge von PhiLho und jsulak der richtige Weg, wenn Sie mit XML-Tools arbeiten möchten. Wenn Sie &#160;den XPath-Ausdruck eingeben , sollte er in die entsprechende Bytesequenz konvertiert werden, bevor der XPath-Ausdruck angewendet wird.


1
Nicht, wenn Sie XPath in XPather (GUI) oder in JavaScript versuchen / verwenden (keine automatische Ersetzung von Entitäten, da wir nicht in XML sind). Guter Rat in anderen XML-Umgebungen (XSTL?).
PhiLho

1

Ich kann mit Xpather keine Übereinstimmung erzielen, aber Folgendes funktionierte für mich mit einfachen XML- und XSL-Dateien im XML-Editor von Microsoft:

<xsl:value-of select="count(//td[text()='&nbsp;'])" />

Der zurückgegebene Wert ist 1, was in meinem Testfall der richtige Wert ist.

Allerdings musste ich nbsp als Entität in meinem XML und XSL wie folgt deklarieren :

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#160;"> ]>

Ich bin nicht sicher , ob das hilft dir, aber ich konnte tatsächlich finden nbsp einen XPath - Ausdruck verwendet wird .

Bearbeiten: Mein Codebeispiel enthält tatsächlich die Zeichen '& nbsp;' Das JavaScript-Syntax-Highlight konvertiert es jedoch in das Leerzeichen. Lass dich nicht irreführen!


Sie können Ihr Codebeispiel so bearbeiten, wie es für das Beispiel in meiner Frage gemacht wurde. Ersetzen Sie Ihre nbsp-Entität durch & amp; nbsp;.
Bergeroy

1

Suche nach &nbsp;oder nur nbsp- hast du das versucht?


Ich erkenne, dass dies funktionieren sollte, aber es ist nicht genau sicher, was ich finde. In XPATH muss es eine Möglichkeit geben, eine bestimmte Methode zu codieren, die dem entspricht, wonach ich suche.
Bergeroy

Vielleicht sollte ich auf einen regulären Ausdruck schauen.
Bergeroy

1

Gemäß dem von Ihnen bereitgestellten HTML:

<tr>
  <td>abc</td>
  <td>&nbsp;</td>
</tr>

Um den Knoten mit der Zeichenfolge zu finden &nbsp;, können Sie eine der folgenden Methoden verwenden basierte Lösungen:

  • Verwenden von text():

    "//td[text()='\u00A0']"
  • Verwenden von contains():

    "//td[contains(., '\u00A0')]"

Idealerweise möchten Sie jedoch den NO-BREAK SPACE- Charakter vermeiden und eine der folgenden Locator-Strategien verwenden :

  • Verwenden des übergeordneten <tr>Knotens und following-sibling:

    "//tr//following-sibling::td[2]"
  • Verwenden von starts-with():

    "//tr//td[last()]"
  • Verwenden des vorhergehenden <td>Knotens und des followingnode andfolgenden Geschwisters`:

    "//td[text()='abc']//following::td[1]"

Referenz

Eine relevante ausführliche Diskussion finden Sie in:


tl; DR

Unicode-Zeichen 'NO-BREAK SPACE' (U + 00A0)


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.