2011-05-29 20 views
7

tengo la siguiente expresión XPath:error Xpath con no() y termina-con()

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

espero que me dan todos los elementos - a excepción de entrada - con cualquier valor de atributo que termina con "Derechos de autor ".

ejecuto en la API Java con Selenio 2 webDriver.findElements(By.xpath(expression)) y sale el siguiente error:

The expression is not a legal expression

Pero estas expresiones trabajan sin problemas:

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

¿Alguna idea?

+0

No sé Selenium, pero si '// * [not (input)] [starts-with (@ *, 'Copyright')]' se analiza correctamente y si además la función XPath 2.0 'ends-with' es compatible entonces no veo ningún motivo por el que '// * [not (input)] [ends-with (@ *, 'Copyright')]' no se acepte como una expresión legal. Sin embargo, su descripción verbal suena como si quisiera '// * [not (self :: input)] [@ * [ends-with (., 'Copyright')]]'. –

+0

Gracias por su comentario. ¿Cuál es la diferencia entre '// * [not (self :: input)] [@ * [ends-with (., 'Copyright')]]' y '// * [not (input)] [ends-with (@ *, 'Copyright')] '? – Alp

+0

'// * [not (input)]' selecciona cualquier elemento que no tenga ningún elemento secundario 'input', mientras que' // * [not (self :: input)] 'selecciona cualquier elemento que no sea un elemento' input'. En cuanto a comparar '[@ * [ends-with (., 'Copyright')]]' con lo que tienes, mi sugerencia es verdadera siempre que haya cualquier nodo de atributo que termine con 'Copyright' mientras tu prueba solo funcione si hay un solo atributo que termina con 'Copyright', como ends-with (http://www.w3.org/TR/xquery-operators/#func-ends-with) permite una secuencia con un solo elemento como su primer argumento o una secuencia vacía pero no varios elementos. –

Respuesta

5

I have the following Xpath expression:

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

I expect it to give me all elements - except input - with any attribute value which ends with "Copyright".

Hay algunas cuestiones aquí:

  1. ends-with() es sólo una función estándar de XPath 2.0, por lo que lo más probable es que usted está usando un 1.0 motor de XPath y correctamente genera un error porque no conoce una función llamada ends-with().

  2. Incluso si se está trabajando con un procesador XPath 2.0, la expresión ends-with(@*, 'Copyright') resultados de error en el caso general, ya que la función ends-with() se define a aceptar atmost una sola cadena (xs:string?) como sus dos operandos - sin embargo, @* produce una secuencia de más de una cadena en el caso cuando el elemento tiene más de un atributo.

  3. //*[not(input)] no significa "seleccionar todos los elementos que no se denominan input. El verdadero significado es:" Seleccionar todos los elementos que no tengan un elemento secundario denominado "entrada".

Solución:

  1. Utilice esta XPath 2.0 expresión: //*[not(self::input)][@*[ends-with(.,'Copyright')]]

  2. En el caso de XPath 1.0 utilizar esta expresión:

....

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

Aquí es una verificación corta y completa de la última expresión XPath, XSLT usando:

<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> 

cuando esta transformación se aplica en el siguiente documento XML:

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

del resultado deseado, adecuados, se produce:

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

En el caso del documento XML estar en un espacio de nombres predeterminado:

<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> 

cuando se aplica en este XML documento:

<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> 

el, resultado correcto querido se produce:

<a xmlns="http://www.w3.org/1999/xhtml" y="This is a Copyright"/> 
+0

Gracias, comprobaré esto más tarde. – Alp

+0

Lamentablemente no funciona: la expresión no es una expresión legal: xpath = // * [not (self :: input)] [@ * [subscring (., String-length() - 8) = 'Copyright')] ] – Alp

+0

@Alp: Parece que no está trabajando con un procesador XPath compatible; de ​​ser así, su pregunta se abordará mejor en una etiqueta más específica, no en la etiqueta "xpath", que asume que la pregunta es una pregunta XPath. –

1

No sé Selenio pero si //*[not(input)][starts-with(@*, 'Copyright')] se ha analizado correctamente y si, además, se admite la función de XPath 2.0 ends-with entonces yo no veo ninguna razón por la //*[not(input)][ends-with(@*, 'Copyright')] no se acepta como una expresión legal. Sin embargo, su descripción verbal suena como si quisiera //*[not(self::input)][@*[ends-with(., 'Copyright')]].

//*[not(input)] selecciona cualquier elemento que no tenga ningún elemento secundario de entrada, mientras que //*[not(self::input)] selecciona elementos que no sean ellos mismos input elementos. En cuanto a comparar [@*[ends-with(., 'Copyright')]] con lo que tienes, mi sugerencia es verdadera siempre y cuando haya cualquier nodo de atributo que termine con 'Copyright' mientras que tu prueba solo funcionará si hay un solo atributo que termina con 'Copyright', como ends-with http://www.w3.org/TR/xquery-operators/#func-ends-with permite una secuencia con un solo elemento como primer argumento o una secuencia vacía, pero no varios elementos.

+0

Obtuvo el mismo error para '// * [not (self :: input)] [@ * [ends-with (., 'Copyright')]]'. – Alp

+0

¿Estás seguro de que Selenium admite una función XPath 2.0 como 'ends-with'? –

+0

Sí, porque sin la condición no funciona bien. – Alp

0

explicación más probable es que usted está utilizando un XPath 1.0 procesadores. La función ends-with() requiere el soporte de XPath 2.0.

+0

comienza, ¿también? – Alp

+0

Sí, 'starts-with' también es de XPath 2.0 – yegor256

+0

No, starts-with estaba disponible en 1.0. ends-with era nuevo en 2.0. –

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

puede ser pequeña corrección con string-length(.)

Ahora, es posible que funcione.