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>

8 thoughts on “XML Path Language (XPath) на примерах

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

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

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

  4. Просто гениально.. перерыл весь инет в поиске чтото типа LIKE и чуть не свихнулся от документаций аля http://www.w3.org, этопросто вынос мозга. В этом примере изучение заняли пол минуты отсилы исраз у взакладки !!! низкий поклон

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

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

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