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í:
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()
.
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.
//*[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:
Utilice esta XPath 2.0 expresión: //*[not(self::input)][@*[ends-with(.,'Copyright')]]
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"/>
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')]]'. –
Gracias por su comentario. ¿Cuál es la diferencia entre '// * [not (self :: input)] [@ * [ends-with (., 'Copyright')]]' y '// * [not (input)] [ends-with (@ *, 'Copyright')] '? – Alp
'// * [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. –