У меня есть следующее выражение Xpath:
//*[not(input)][ends-with(@*, 'Copyright')]
Я ожидаю, что это даст мне все элементы -
кроме ввода - с любым атрибутом
значение, которое заканчивается на «Copyright».
Здесь есть несколько проблем :
ends-with()
- это только стандартная функция XPath 2.0, поэтому есть вероятность, что вы используете движок XPath 1.0, и он правильно вызывает ошибку, потому что не знает о функции с именем ends-with()
.
Даже если вы работаете с процессором XPath 2.0, выражение ends-with(@*, 'Copyright')
приводит к ошибке в общем случае, поскольку функция ends-with()
определена так, чтобы принимать не более одной строки (xs:string?
) как оба его операнда - однако @*
создает последовательность из более чем одной строки в случае, когда элемент имеет более одного атрибута.
//*[not(input)]
не означает «выбрать все элементы, которые не названы input
». Реальное значение: «Выбрать все элементы, у которых нет дочернего элемента с именем« input ».
Решение
Используйте это выражение XPath 2.0: //*[not(self::input)][@*[ends-with(.,'Copyright')]]
В случае 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"/>