XML Path Language (XPath) на примерах

XPath описан в стандарте XPath 1.0. Согласно написанному там «XPath is a language for addressing parts of an XML document … «. По русски можно сказать, что XPath нужен для разбора (parsing) XML документов.
В приведенных ниже примерах рассматриваются наиболее часто употребимые (по мнению автора) конструкции языка.

1 Если путь начинается с символа /, то он представляет абсолютный путь к заданному элементу.

/AAA /AAA/DDD/BBB
     <AAA>
<BBB/>
<CCC/>
<BBB/>
<DDD>
<BBB/>
</DDD>
<CCC/>
</AAA>
     <AAA>
<BBB/>
<CCC/>
<BBB/>
<DDD>
<BBB/>
</DDD>
<CCC/>
</AAA>

2 Если путь начинается с //, то будут выбраны все элементы, соответствующие указанному шаблону.

//BBB //DDD/BBB
     <AAA>
<BBB/>
<CCC/>
<BBB/>
<DDD>
<BBB/>
</DDD>
<CCC>
<DDD>
<BBB/>
<BBB/>
</DDD>
</CCC>
</AAA>
     <AAA>
<BBB/>
<CCC/>
<BBB/>
<DDD>
<BBB/>
</DDD>
<CCC>
<DDD>
<BBB/>
<BBB/>
</DDD>
</CCC>
</AAA>

3 Символ ‘*’ указывает, что надо выбрать все элементы, соответствующие пути перед ней.

/AAA/CCC/DDD/* /*/*/*/BBB //*
     <AAA>
<XXX>
<DDD>
<BBB/>
<BBB/>
<EEE/>
<FFF/>
</DDD>
</XXX>
<CCC>
<DDD>
<BBB/>
<BBB/>
<EEE/>
<FFF/>
</DDD>
</CCC>
<CCC>
<BBB>
<BBB>
<BBB/>
</BBB>
</BBB>
</CCC>
</AAA>
     <AAA>
<XXX>
<DDD>
<BBB/>
<BBB/>
<EEE/>
<FFF/>
</DDD>
</XXX>
<CCC>
<DDD>
<BBB/>
<BBB/>
<EEE/>
<FFF/>
</DDD>
</CCC>
<CCC>
<BBB>
<BBB>
<BBB/>
</BBB>
</BBB>
</CCC>
</AAA>
     <AAA>
<XXX>
<DDD>
<BBB/>
<BBB/>
<EEE/>
<FFF/>
</DDD>
</XXX>
<CCC>
<DDD>
<BBB/>
<BBB/>
<EEE/>
<FFF/>
</DDD>
</CCC>
<CCC>
<BBB>
<BBB>
<BBB/>
</BBB>
</BBB>
</CCC>
</AAA>

4 Выражение в квадратных скобках позволяет задавать более четкие критерии для элемента. Так число в квадратных скобках обозначает позицию элемента в выбранном множестве. Функция last() позволяет указать последний элемент в выборке.

/AAA/BBB[1] /AAA/BBB[last()]
     <AAA>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
</AAA>
     <AAA>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
</AAA>

5 Атрибуты определяются префиксом @.

//@id //BBB[@id] //BBB[@name]
     <AAA>
<BBB id = «b1″/>
<BBB id = «b2″/>
<BBB name = «bbb»/>
<BBB/>
</AAA>
     <AAA>
<BBB id = «b1″/>
<BBB id = «b2″/>
<BBB name = «bbb»/>
<BBB/>
</AAA>
     <AAA>
<BBB id = «b1″/>
<BBB id = «b2″/>
<BBB name = «bbb»/>
<BBB/>
</AAA>

Значения атрибутов могут служить критерием при выборке. Функция normalize-space() удаляет пробелы в начале и конце параметра, а все последовательности пробельных символов заменяет одиночным пробелом.

//BBB[@id=’b1′] //BBB[@name=’bbb’] //BBB[normalize-space(@name)=’bbb’]
     <AAA>
<BBB id = «b1″/>
<BBB name = » bbb «/>
<BBB name = «bbb»/>
</AAA>
     <AAA>
<BBB id = «b1″/>
<BBB name = » bbb «/>
<BBB name = «bbb»/>
</AAA>
     <AAA>
<BBB id = «b1″/>
<BBB name = » bbb «/>
<BBB name = «bbb»/>
</AAA>

6 Функция count() возвращает число элементов в указанном множестве.

//*[count(*)=3]

выбрать все, имеющие три дочерних элемента
//*[count(BBB)=2]

выбрать все, имеющие два дочерних элемента BBB
     <AAA>
<CCC>
<BBB/>
<BBB/>
<BBB/>
</CCC>
<DDD>
<BBB/>
<BBB/>
</DDD>
<EEE>
<CCC/>
<DDD/>
</EEE>
</AAA>
     <AAA>
<CCC>
<BBB/>
<BBB/>
<BBB/>
</CCC>
<DDD>
<BBB/>
<BBB/>
</DDD>
<EEE>
<CCC/>
<DDD/>
</EEE>
</AAA>

7 Функция name() возвращает имя элемента. Функция starts-with() возвращает истину, если строка первого аргумента начинается строкой второго аргумента. Функция contains() возвращает истину, если строка из первого аргумента содержит строку из второго.

//*[name()=’BBB’]

выбрать все с именем BBB, эквивалентно пути //BBB
//*[starts-with(name(),’B’)]

выбрать все, имя которых начинается с B
//*[contains(name(),’C’)]

выбрать все, имя которых содержит C
     <AAA>
<BCC>
<BBB/>
<BBB/>
<BBB/>
</BCC>
<DDB>
<BBB/>
<BBB/>
</DDB>
<BEC>
<CCC/>
<DBD/>
</BEC>
</AAA>
     <AAA>
<BCC>
<BBB/>
<BBB/>
<BBB/>
</BCC>
<DDB>
<BBB/>
<BBB/>
</DDB>
<BEC>
<CCC/>
<DBD/>
</BEC>
</AAA>
     <AAA>
<BCC>
<BBB/>
<BBB/>
<BBB/>
</BCC>
<DDB>
<BBB/>
<BBB/>
</DDB>
<BEC>
<CCC/>
<DBD/>
</BEC>
</AAA>

Функция string-length() возвращает число символов в строке.

//*[string-length(name()) = 3]

выбрать все, имя которых состоит из трех символов
//*[string-length(name()) < 3] //*[string-length(name()) > 3]
     <AAA>
<Q/>
<SSSS/>
<BB/>
<CCC/>
<DDDDDDDD/>
<EEEE/>
</AAA>
     <AAA>
<Q/>
<SSSS/>
<BB/>
<CCC/>
<DDDDDDDD/>
<EEEE/>
</AAA>
     <AAA>
<Q/>
<SSSS/>
<BB/>
<CCC/>
<DDDDDDDD/>
<EEEE/>
</AAA>

8 Несколько путей можно объединить с помощью разделителя |.

/AAA/EEE | //BBB /AAA/EEE | //DDD/CCC | /AAA | //BBB
     <AAA>
<BBB/>
<CCC/>
<DDD>
<CCC/>
</DDD>
<EEE/>
</AAA>
     <AAA>
<BBB/>
<CCC/>
<DDD>
<CCC/>
</DDD>
<EEE/>
</AAA>

9 Ось self содержит только сам элемент (//GGG/self::*). Ось child содержит дочерние элементы контекстного узла. Ось child является осью, применяемой по умолчанию, и может быть опущена, т.е. /child::AAA эквивалентно /AAA, /child::AAA/child::BBB эквивалентно /AAA/BBB и т.д.

9 Ось descendant содержит потомков контекстного узла.

/AAA/BBB/descendant::* //CCC/descendant::*

выбрать все, имеющие в качестве предка CCC
//CCC/descendant::DDD

выбрать DDD, имеющие в качестве предка CCC
     <AAA>
<BBB>
<DDD>
<CCC>
<DDD/>
<EEE/>
</CCC>
</DDD>
</BBB>
<CCC>
<DDD>
<EEE>
<DDD>
<FFF/>
</DDD>
</EEE>
</DDD>
</CCC>
</AAA>
     <AAA>
<BBB>
<DDD>
<CCC>
<DDD/>
<EEE/>
</CCC>
</DDD>
</BBB>
<CCC>
<DDD>
<EEE>
<DDD>
<FFF/>
</DDD>
</EEE>
</DDD>
</CCC>
</AAA>
     <AAA>
<BBB>
<DDD>
<CCC>
<DDD/>
<EEE/>
</CCC>
</DDD>
</BBB>
<CCC>
<DDD>
<EEE>
<DDD>
<FFF/>
</DDD>
</EEE>
</DDD>
</CCC>
</AAA>

10 Ось parent содержит родителя контекстного узла, если он существует.

//DDD/parent::*
     <AAA>
<BBB>
<DDD>
<CCC>
<DDD/>
<EEE/>
</CCC>
</DDD>
</BBB>
<CCC>
<DDD>
<EEE>
<DDD>
<FFF/>
</DDD>
</EEE>
</DDD>
</CCC>
</AAA>

11 Ось ancestor содержит предков контекстного узла.

/AAA/BBB/DDD/CCC/EEE/ancestor::* //FFF/ancestor::*
     <AAA>
<BBB>
<DDD>
<CCC>
<DDD/>
<EEE/>
</CCC>
</DDD>
</BBB>
<CCC>
<DDD>
<EEE>
<DDD>
<FFF/>
</DDD>
</EEE>
</DDD>
</CCC>
</AAA>
     <AAA>
<BBB>
<DDD>
<CCC>
<DDD/>
<EEE/>
</CCC>
</DDD>
</BBB>
<CCC>
<DDD>
<EEE>
<DDD>
<FFF/>
</DDD>
</EEE>
</DDD>
</CCC>
</AAA>

12 Ось following-sibling содержит все следующих братьев контекстного узла. Братьями называются те узлы, что имеют одного родителя с контекстным.

/AAA/BBB/following-sibling::* //CCC/following-sibling::*
     <AAA>
<BBB>
<CCC/>
<DDD/>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>
     <AAA>
<BBB>
<CCC/>
<DDD/>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>

13 Ось preceding-sibling содержит всех предыдущих братьев контекстного узла.

/AAA/XXX/preceding-sibling::* //CCC/preceding-sibling::*
     <AAA>
<BBB>
<CCC/>
<DDD/>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>
     <AAA>
<BBB>
<CCC/>
<DDD/>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>

14 Ось following содержит в том же порядке, что и в самом документе, все узлы, идущие после контекстного, за исключением всех предков, узлов атрибутов и пространств имен.

/AAA/XXX/following::* //ZZZ/following::*
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
<DDD>
<EEE/>
</DDD>
</ZZZ>
<FFF>
<GGG/>
</FFF>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
<DDD>
<EEE/>
</DDD>
</ZZZ>
<FFF>
<GGG/>
</FFF>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>

15 Ось preceding содержит в том же порядке, что и в самом документе, все узлы, идущие перед контекстным узлом, исключая любых предков, узлов атрибутов и пространств имен.

/AAA/XXX/preceding::* //GGG/preceding::*
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
</ZZZ>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
</ZZZ>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>

16 Ось descendant-or-self содержит контекстный узел и всех его потомков.

/AAA/XXX/descendant-or-self::* //CCC/descendant-or-self::*
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
</ZZZ>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
</ZZZ>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>

17 Ось ancestor-or-self содержит контекстный узел и всех его предков, таким образом, эта ось всегда содержит корневой узел.

/AAA/XXX/DDD/EEE/ancestor-or-self::* //GGG/ancestor-or-self::*
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
</ZZZ>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>
     <AAA>
<BBB>
<CCC/>
<ZZZ>
<DDD/>
</ZZZ>
</BBB>
<XXX>
<DDD>
<EEE/>
<DDD/>
<CCC/>
<FFF/>
<FFF>
<GGG/>
</FFF>
</DDD>
</XXX>
<CCC>
<DDD/>
</CCC>
</AAA>

18 Оператор div производит деление, оператор mod возвращает остаток от деления нацело. Функция floor — округление до ближайшего
целого в сторону увеличения. Функция ceiling — в сторону уменьшения.

//BBB[position() mod 2 = 0 ]

выбрать все, позиция которых кратна 2
//BBB[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5)] //CCC[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5)]
     <AAA>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<CCC/>
<CCC/>
<CCC/>
</AAA>
     <AAA>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<CCC/>
<CCC/>
<CCC/>
</AAA>
     <AAA>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<BBB/>
<CCC/>
<CCC/>
<CCC/>
</AAA>

7 Комментарии “XML Path Language (XPath) на примерах

  1. Да, всё красиво и просто. Но всё меняется, когда используются namespace-ы…

  2. Офигенно выручила статья, очень доступно, буду клацать на рекламу пока кнопка не сотрется…

  3. В оригинале этот набор примеров лучше смотрится и воспринимается.

  4. Очень хорошо! Суть. Сложное состоит из простого.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *