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>
|
Комментарии:
Алексей 23.01.11 00:10
Да, всё красиво и просто. Но всё меняется, когда используются namespace-ы...
Zik 02.06.11 18:47
Спасибо за статью, очень помогла.
Zlodey 15.07.11 17:03
Офигенно выручила статья, очень доступно, буду клацать на рекламу пока кнопка не сотрется...
Если вам помогла или просто понравилась эта статья вы можете отблагодарить автора кликнув
по рекламе. Спасибо!
комментировать:
прежде чем писать комментарий убедитесь, пожалуйста, что он не попадает в нижеследующие категории:
не стоит писать "я чайник, помогите ..." или "я начинающий, объясните ..." - уважайте себя!
может вы и новичок, но ведь не тупой же! сами вполне способны во всем разобраться, тем более, что
материал здесь изложен весьма доступно
не пишите вопросы типа "как мне сделать такую же менюху как наверху?", "куда вставлять этот код?", "как устроен интернет?" и т.д. - уважайте время автора!
- комментарии вида "все, что здесь написано - бред" будут оставлены только если будут подписаны "я такой-то, разработчик сайта такого-то с посещаемостью 1000 хостов в день" и т.п. Если вы не согласны с чем-то - обоснуйте, напишите как правильно, а писать простые ругательства не надо, это не забор
прямые оскорбления кого бы то ни было будут удалятся! здоровая критика приветствуется!
|
|