Ошибка Xpath с not () и заканчивается-with () - PullRequest
7 голосов
/ 29 мая 2011

У меня есть следующее выражение Xpath:

//*[not(input)][ends-with(@*, 'Copyright')]

Я ожидаю, что он даст мне все элементы - кроме ввода - с любым значением атрибута, которое заканчивается "Copyright".

Я выполняю его в Java API Selenium 2 с webDriver.findElements(By.xpath(expression)) и получаю следующую ошибку:

Выражение не является законным выражение

Но эти выражения работают без проблем:

//*[not(input)][starts-with(@*, 'Copyright')]
//*[ends-with(@*, 'Copyright')]

Есть идеи?

Ответы [ 4 ]

5 голосов
/ 29 мая 2011

У меня есть следующее выражение Xpath:

//*[not(input)][ends-with(@*, 'Copyright')]

Я ожидаю, что это даст мне все элементы - кроме ввода - с любым атрибутом значение, которое заканчивается на «Copyright».

Здесь есть несколько проблем :

  1. ends-with() - это только стандартная функция XPath 2.0, поэтому есть вероятность, что вы используете движок XPath 1.0, и он правильно вызывает ошибку, потому что не знает о функции с именем ends-with().

  2. Даже если вы работаете с процессором XPath 2.0, выражение ends-with(@*, 'Copyright') приводит к ошибке в общем случае, поскольку функция ends-with() определена так, чтобы принимать не более одной строки (xs:string?) как оба его операнда - однако @* создает последовательность из более чем одной строки в случае, когда элемент имеет более одного атрибута.

  3. //*[not(input)] не означает «выбрать все элементы, которые не названы input». Реальное значение: «Выбрать все элементы, у которых нет дочернего элемента с именем« input ».

Решение

  1. Используйте это выражение XPath 2.0: //*[not(self::input)][@*[ends-with(.,'Copyright')]]

  2. В случае XPath 1.0 используйте это выражение:

....

  //*[not(self::input)]
        [@*[substring(., string-length() -8) = 'Copyright']]

Вот краткая и полная проверка последнего выражения XPath с использованием XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:copy-of select=
     "//*[not(self::input)]
           [@*[substring(., string-length() -8)
              = 'Copyright'
              ]
          ]"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к следующему документу XML:

<html>
 <input/>
 <a x="Copyright not"/>
 <a y="This is a Copyright"/>
</html>

желаемый, правильный результат выдается :

<a y="This is a Copyright"/>

В случае, если документ XML находится в пространстве имен по умолчанию :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:x="http://www.w3.org/1999/xhtml"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:copy-of select=
     "//*[not(self::x:input)]
           [@*[substring(., string-length() -8)
              = 'Copyright'
              ]
          ]"/>
 </xsl:template>
</xsl:stylesheet>

при применении к этому документу XML :

<html xmlns="http://www.w3.org/1999/xhtml">
 <input z="This is a Copyright"/>
 <a x="Copyright not"/>
 <a y="This is a Copyright"/>
</html>

желаемый, правильный результат получается:

<a xmlns="http://www.w3.org/1999/xhtml" y="This is a Copyright"/>
1 голос
/ 29 мая 2011

Я не знаю Selenium, но если //*[not(input)][starts-with(@*, 'Copyright')] успешно проанализирован и если дополнительно поддерживается функция XPath 2.0 ends-with, то я не вижу никакой причины, по которой //*[not(input)][ends-with(@*, 'Copyright')] не принимается как юридическое выражение.Однако ваше словесное описание звучит так, как будто вы хотите, чтобы //*[not(self::input)][@*[ends-with(., 'Copyright')]].

//*[not(input)] выбирал любые элементы, не имеющие входных дочерних элементов, в то время как //*[not(self::input)] выбирал любые элементы, не являющиеся самими элементами input.Что касается сравнения [@*[ends-with(., 'Copyright')]] с тем, что у вас есть, мое предложение верно, если есть какой-либо узел атрибута, который заканчивается «Авторским правом», в то время как ваш тест будет работать, только если есть единственный атрибут, который заканчивается «Авторским правом», как заканчивается-с http://www.w3.org/TR/xquery-operators/#func-ends-with разрешить последовательность с единственным элементом в качестве первого аргумента или пустой последовательностью, но не несколькими элементами.

0 голосов
/ 13 ноября 2015
//*[not(self::input)][@*[substring(., string-length(.) -8) = 'Copyright']]

Может быть небольшая коррекция с string-length(.)

Теперь это может сработать.

0 голосов
/ 30 мая 2011

Наиболее вероятным объяснением является то, что вы используете процессоры XPath 1.0.Функция end-with () требует поддержки XPath 2.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...