2014-02-06 2 views
2

Я использую xmlstarlet для извлечения changeSet узлов из liquibase XML-журнал изменений, где viewName заканчивается на «v».Почему xmlstarlet говорит, что нет функции «концы с»?

Однако XMLStarlet жалуется, что функция ends-with XPATH не существует:

$ xmlstarlet sel -N x="http://www.liquibase.org/xml/ns/dbchangelog" -t -m \ 
"/x:databaseChangeLog/x:changeSet[x:createView[ends-with(@viewName, 'v')]]" \ 
-c . public.db.changelog.xml 

xmlXPathCompOpEval: function ends-with not found 
Unregistered function 
Stack usage errror 
xmlXPathCompiledEval: 3 objects left on the stack. 
runtime error: element for-each 
Failed to evaluate the 'select' expression. 
None of the XPaths matched; to match a node in the default namespace 
use '_' as the prefix (see section 5.1 in the manual). 
For instance, use /_:node instead of /node 

XML-выглядит как это:

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"> 
    <changeSet id="1391529990457-3"> 
    <createView viewName="myviewnamev"><!-- view definition here --></createView> 
    </changeSet> 
    <changeSet id="1391529990457-4"> 
    <createView viewName="anotherviewname"><!-- view definition here --></createView> 
    </changeSet> 
</databaseChangeLog> 

Я знаю, что выражение XPATH иначе правильно , потому что, если я изменю критерии выбора на x:createView[@viewName="myviewnamev"], тогда он правильно выбирает только запись changeLog.

Как получить xmlstarlet для правильного использования ends-with? Или, есть ли альтернативный способ выполнить то, что я хочу сделать?

+0

Где вы видите функцию 'end-with' в спецификации [XPath] (http://www.w3.org/TR/xpath/)? –

+0

@ O.R.Mapper right [здесь] (http://www.w3.org/TR/xquery-operators/#func-ends-with), но ниже ответ Йенса пояснил, что xmlstarlet не поддерживает XPath 2.0. – Jonathan

+0

Действительно, точно. –

ответ

3

xmlstarlet поддерживает только XPath 1.0, который не предлагает функцию ends-with($string, $token). Вы должны использовать substring, string-length и и сравнения строк, чтобы построить свой собственный, используя этот шаблон:

substring($string, string-length($string) - string-length($token) + 1) = $token] 

Примененные на ваш запрос, он должен выглядеть следующим образом (I «предвычисленными» длина строки):

/x:databaseChangeLog/x:changeSet[x:createView[ 
    substring(@viewName, string-length(@viewName)) = 'v'] 
] 

В качестве альтернативы вам может потребоваться более мощный движок XPath 2.0/XQuery.

+0

Спасибо! Поскольку это одноразовое решение, это будет здорово. – Jonathan

Смежные вопросы