Приклади XPath. Дивитися що таке "XPath" в інших словниках

(Предок) містить всіх предків контекстного вузла, включаючи батьків, дідусів, прадідусів і т.д. Ця вісь завжди містить кореневий вузол - якщо тільки контекстним вузлом не є сам кореневої вузол.

Погляньте на лістинг 7.3, в якому за допомогою осі

здійснюється пошук імен (збережених в елементі) всіх предків елементів. Лістинг 7.3. Застосування осі ancestor
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e

Ось результат застосування цієї таблиці стилів до

:

Застосування осі ancestor-or-self

містить всіх предків контекстного вузла, а також сам контекстний вузол. Це означає, крім іншого, що така вісь завжди містить кореневий вузол.

У лістингу 7.4 додані атрибути

зі значенням «Steve» в весь документ. Лістинг 7.4. planets.xml з атрибутами AUTHOR
.0553
58.65
1516
.983
43.4
.815
116.75
3716
.943
66.8
1
2107
1
128.4

Припустимо тепер, що я хочу перерахувати по імені всіх предків елементів

, Що мають атрибут, а також поточний елемент, якщо у нього є атрибут. Це можна зробити за допомогою осі і функції (лістинг 7.5). Лістинг 7.5. Застосування осі ancestor-or-self
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e

Ось результат; показані вибрані предки всіх трьох елементів

, Включаючи сам елемент, за умови, що у нього є атрибут:

Застосування осі descendant

(Нащадок) містить всіх нащадків контекстного вузла. Зауважте, що сюди не входять атрибути або вузли просторів імен, оскільки вони не вважаються дочірніми вузлами.

У наступному прикладі (лістинг 7.6) демонструється робота з цією віссю. На цей раз я хочу додати примітку до елементу

Меркурія:
(Вибачте, але Меркурій вибухнув і більше не доступний.). Щоб знайти Меркурій, мені достатньо лише перевірити, чи має будь-якої нащадок елемента строкове значення «», що я зроблю за допомогою виразу XPath всередині предиката вибору. Лістинг 7.6. Застосування осі descendant
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e
Sorry. Mercury has blown up and is no longer available.

Ось результуючий документ, доповнений новим елементом

тільки для Меркурія:
.0553
58.65
1516
.983
43.4
Sorry, Mercury has blown up and is no longer available.
.815
116.75
3716
.943
66.8

Застосування осі descendant-or-self

містить всіх нащадків контекстного вузла і сам контекстний вузол. Зауважте, однак, що вона не містить атрибутів і вузлів просторів імен.

У наступному прикладі (лістинг 7.7) демонструється робота з віссю. В цьому випадку я створив спрощену таблицю стилів (докладніше про спрощені таблицях стилів див. Розділ 2), яка обробляє всі елементи з використанням нащадків, генеруючи вже знайому нам HTML-таблицю даних про планетах.

Лістинг 7.7. Застосування осі descendant-or-self

От і все. Я застосував тут спрощену таблицю стилів, щоб підкреслити, що за допомогою таких осей нащадків, як

або, ви можете автоматично обробляти всі обрані вузли, багато в чому аналогічна тій, як це роблять елементи або.

Застосування осі following

Ось following (наступний) містить всі вузли, розташовані після контекстного вузла відповідно до встановленого в документі порядком (іншими словами, в порядку, в якому вони з'являються в документі, починаючи з його початку), виключаючи всіх нащадків контекстного вузла, а також виключаючи вузли атрибутів і просторів імен.

У цьому прикладі (лістинг 7.8) я вибираю кожен елемент І копіюю всі наступні елементи в результуючий документ.

Лістинг 7.8. Застосування осі following
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e
Меркурія, він копіює всі наступні елементи - тобто Венеру, потім всіх нащадків Венери, далі Землю і потім всіх нащадків Землі. Після цього він вибирає елемент Венери і копіює все наступні елементи, тобто Землю і всіх нащадків Землі:
.815
116.75
3716
.943
66.8
.815
116.75
3716
.943
66.8
1
2107
1
128.4
1
2107
1
128.4
1
2107
1
128.4
1
2107
1
128.4

З іншого боку, при використанні осі

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

Застосування осі following-sibling

містить всіх наступних братів контекстного вузла.

Наприклад, я можу вибрати кожен елемент

і скопіювати в результуючий документ все вузли в осі таким чином (лістинг 7.9). Лістинг 7.9. Застосування осі following-sibling
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e

При цьому спочатку копіюються два вузла-брата, наступні за Меркурієм (Венера і Земля), потім копіюється наступний вузол-брат Венери, Земля. У самій Землі немає таких з ним братів, тому результат виглядає так:

.815
116.75
3716
.943
66.8
1
2107
1
128.4
1
2107
1
128.4

Застосування осі namespace

містить вузли просторів імен контекстного вузла. Зауважте, що ця вісь порожня, якщо контекстним вузлом не є елемент. У елемента присутній вузол простору імен для:

Кожного атрибута елемента, чиє ім'я починається з «xmlns:»;

Кожного атрибута елемента-предка, чиє ім'я починається з «xmlns:» (звичайно, якщо сам елемент або найближчий предок не оголосить простір імен заново);

атрибуту

, Якщо елемент або предок має атрибут.

У наступному прикладі (лістинг 7.10) я хочу відобразити простір імен елемента

в результуючому документі, і в вихідному документі я присвоїв простору імен значення «http://www.starpowder.com». Лістинг 7.10. planets.xml з оголошенням простору імен
.0553
58.65
1516
.983
43.4

Ось таблиця стилів (лістинг 7.11), в якій я перевіряю простору імен, що використовуються в елементі

. Лістинг 7.11. Застосування осі namespace в planets.xml
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e

А ось результуючий документ (зауважте, що вид документа може змінюватися в залежності від процесора XSLT):

Застосування осі parent

Ось parent (батько) містить батька (і тільки одного з батьків) контекстного вузла, якщо такий є.

Припустимо, що я хочу змінити вміст елемента Землі

на «\u003e\u003e (Маса Землі приймається за 1). У наступному шаблоні (лістинг 7.12) для цього перевіряється, чи містить батько елемента елемент зі строковим значенням «Earth». Лістинг 7.12. Застосування осі parent
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e

The mass of Earth is set to 1.

І ось результат:

.0553
58.65
1516
.983
43.4
.815
116.75
3716
.943
66.8
The mass of Earth is set to 1.
2107
1
128.4

Застосування осі preceding

містить всі вузли, розташовані перед контекстним вузлом відповідно до встановленого в документі порядком, виключаючи всіх предків контекстного вузла, а також виключаючи вузли атрибутів і вузли просторів імен.

Нехай, наприклад, мені потрібно задати для вмісту елемента

текст «» (Ця планета розташована далі від Сонця, ніж Меркурій.), якщо розглянута планета дійсно далі від Сонця, ніж Меркурій. Один із способів зробити це - перевірити, чи розташований Меркурій перед розглянутої планетою відповідно до встановленого в документі порядком, за допомогою осі (лістинг 7.13). Лістинг 7.13. Застосування осі preceding
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e
This planet is farther from the Sun than Mercury.

Якщо поточна планета розташована після Меркурія, я можу вставити повідомлення в її елемент

. Результат наступний:
.0553
58.65
1516
.983
43.4
.815
116.75
3716
.943
This planet is farther from the Sun than Mercury.
1
2107
1
This planet is farther from the Sun than Mercury.

Застосування осі preceding-sibling

містить всіх попередніх братів контекстного вузла. Зауважте, що якщо контекстним вузлом є вузол атрибута або вузол простору імен, вісь буде порожня.

Що, якщо, наприклад, вам потрібно створити шаблон, який буде вибирати тільки елементи

в елементі Меркурія? Для цього можна перевірити, чи існують брати, попередні елементу, які є елементами зі строковим значенням «». Якщо застосувати вісь (лістинг 7.14), пошук буде обмежений поточним елементом, що означає, що Меркурій не буде вибрано, якщо ви тільки не перебуваєте в потрібному елементі. Лістинг 7.14. Застосування осі preceding-sibling
xmlns: xsl \u003d "http://www.w3.org/1999/XSL/Transform"\u003e

А ось результат:

.0553
58.65
1516
.983
This is the planet Mercury, closest to the Sun.
.815
116.75
3716
.943
66.8
1
2107
1
128.4

Застосування осі self

містить тільки контекстний вузол. Відповідно до одного з скорочень XPath, як ми побачимо далі, замість «» можна використовувати «.».

Цю вісь корисно мати на увазі, оскільки, як ви пам'ятаєте з глави 4, якщо не поставити вісь, віссю за замовчуванням буде

, А в деяких випадках вам може знадобитися звернутися до діючого вузла. Наприклад, прийме значення істини тільки якщо контекстним вузлом буде елемент.

У наступному прикладі я поєдную шаблони для елементів

і в один шаблон. Оскільки у цих елементів різний формат, я повинен звертатися з ними по-різному всередині одного і того ж шаблону (що можна зробити перевіркою значень осі, яка повертає непорожній набір вузлів, якщо контекстним, вузлом є елемент, і, що повертає непорожній набір вузлів, якщо контекстним вузлом є елемент):

На цьому ми завершуємо розгляд нових осей XPath. Давайте перейдемо до прикладів.

Приклади шляхів розташування

Ми вивчили досить теорії шляхів розташування. Але, зрозуміло, найкраще освоювати цей матеріал на прикладах, тому я наводжу наступний список прикладів шляхів розташування (скорочені варіанти розглядаються після цього списку):

. Повертає дочірні елементи контекстного вузла; . Повертає всі дочірні текстові вузли контекстного вузла; . Повертає всіх дітей контекстного вузла; . Повертає атрибут контекстного вузла; . Повертає всі елементи-нащадки контекстного вузла; . Повертає всіх предків контекстного вузла; . Повертає предків контекстного вузла. Якщо контекстним вузлом теж є, повертає також контекстний вузол; . Для отримання елементів-нащадки контекстного вузла. Якщо контекстним вузлом теж є, повертає також контекстний вузол; . Повертає контекстний вузол, якщо їм є елемент;
child :: PLANET / descendant :: NAME
. Для отримання елементів-нащадки дочірніх елементів контекстного вузла; . Повертає всіх онуків контекстного вузла; . Повертає кореневої вузол; . Повертає всі елементи в документі;
/ Descendant :: PLANET / child :: NAME
. Повертає всі елементи з батьком в документі; . Повертає третю дитину контекстного вузла;
child :: PLANET
. Повертає останню дитину контекстного вузла;
/ Descendant :: PLANET
. Повертає третій елемент в документі;
child :: PLANETS / child :: PLANET / child :: NAME
. Повертає третій елемент четвертого елемента елемента; . Повертає всіх дітей контекстного вузла після перших трьох;
preceding-sibling :: NAME
. Повертає другий попередній елемент-брат контекстного вузла;
child :: *
. Повертає дітей і контекстного вузла.
child :: *
. Повертає останню дитину або контекстного вузла.

Як бачите, синтаксис деяких виразів досить заплутаний, і набирати їх також досить довго. Але, як і для зразків, існує скорочена форма синтаксису XPath.

Скорочений синтаксис XPath

Скорочення синтаксису XPath можуть бути досить зручними. Нижче наведені правила:

може бути скорочено як; може бути скорочено як; може бути скорочено як; може бути скорочено як; може бути скорочено як.

Наприклад, шлях розташування

- скорочення для
self :: node () / descendant-or-self :: node () / child :: PLANET
. Можна також скоротити вираз предиката як, як і т.д. Працювати з шляхами розташування XPath за допомогою скороченого синтаксису значно простіше. У наступному списку перераховано ряд прикладів шляхів розташування з використанням скороченого синтаксису: повертає дочірні елементи контекстного вузла; повертає всі дочірні елементи контекстного вузла; повертає всі дочірні текстові вузли контекстного вузла; повертає атрибут контекстного вузла; повертає всі атрибути контекстного вузла; повертає третю дитину контекстного вузла; повертає останню дитину контекстного вузла; повертає всіх онуків контекстного вузла; повертає другий елемент третього елемента елемента; повертає всіх нащадків кореня документа; повертає елементи-нащадки дочірніх елементів контекстного вузла; повертає всі елементи, у яких є батько; повертає сам контекстний вузол; повертає елементи-нащадки контекстного вузла; повертає батька контекстного вузла; повертає атрибут батька контекстного вузла; повертає всіх батьків нащадка контекстного вузла і батька контекстного вузла; повертає дітей контекстного вузла, у яких є діти; повертає дітей контекстного вузла, у яких є діти з текстом, рівним «Venus»; повертає всіх дітей контекстного вузла, у яких є атрибут зі значенням «»; повертає шосту дитину контекстного вузла, тільки якщо у цієї дитини є атрибут зі значенням «days». Можна також написати; повертає всіх дітей контекстного вузла, у яких є атрибут і атрибут;
// PLANET
"Вибирає всі елементи, значення яких відмінно від значення будь-якого попереднього елемента; вибирає будь-який елемент, який є першою дитиною свого батька; вибирає перше п'ятьох дітей контекстного вузла, у яких є атрибут.

Перевірка виразів XPath

У пакет Xalan входить зручна програма-приклад, ApplyXPath.java, що дозволяє застосувати вираз XPath до документа і подивитися на результат, що дуже допомагає при тестуванні. Для запуску цього прикладу вам потрібно буде скомпілювати

в за допомогою утиліти java.exe, що входить в поставку Java.

Як приклад я застосую вираз XPath «

»До за допомогою. Нижче показаний результат, що відображає всі елементи, дочірні по відношенню до елементів (теги додані програмою ApplyXPath):
% Java ApplyXPath planets.xml PLANET / NAME
MercuryVenusEarth

XPath 2.0

XPath знаходиться в стадії відновлення, і в нього включаються кошти підтримки XSLT 2.0 (див. Www.w3.org/TR/xpath20req). Завдання XPath 2.0 наступні:

Спрощення операцій з вмістом типів, підтримуваних схемою XML;

Спрощення операцій зі строковим вмістом;

Підтримка відповідних стандартів XML;

Поліпшення зручності використання;

Поліпшення функціональної сумісності;

Поліпшення підтримки міжнародних мовних засобів;

Збереження зворотної сумісності;

Підвищена ефективність процесора.

Наступний список дає огляд вимог XPath. Головні пункти - підтримка схеми XML і регулярних виразів, що дає кошти роботи з рядками і пошуку в рядках. (Додаткову інформацію про регулярні вирази можна почерпнути за адресою http://www.perldoc.com/perl5.6/pod/perlre.html.) Відповідно до W3C, XPath 2.0:

Повинен підтримувати архітектуру XML W3C, добре взаємодіючи з іншими стандартами в сімействі XML;

Повинен виражати свою модель даних в термінах інформаційного безлічі (infoset) XML;

Повинен надавати загальний ключовий синтаксис для XSLT 2.0 і XML Query language 1.0;

Повинен підтримувати явне порівняння «

»Або« »і синтаксис рівності;

Повинен розширювати безліч функцій агрегації (наприклад, користувачі XSLT часто вимагали додати функції

і);

Повинен зберігати зворотну сумісність з XPath 1.0;

Повинен надавати функції перетину і різниці тобто - XPath 1.0 підтримує об'єднання двох наборів вузлів, і до цього повинні бути додані функції перетину і різниці;

Повинен підтримувати операцію унарна плюса (оскільки в схемі XML у десяткових чисел може бути присутнім лідируючий плюс);

Повинен покращувати зручність використання;

Повинен знизити обмеження на кроки розташування;

Повинен реалізовувати умовну операцію, що оперує трьома виразами - виразом 1 (логічна операція), виразом 2 і виразом 3. Якщо вираз 1 приймає значення «істина», має обчислюватися вираження 2, а якщо вираз 1 приймає значення «брехня», має обчислюватися вираження 3 ;

Повинен визначати послідовний синтаксис для подвираженій, обробних колекції елементів;

Повинен підтримувати додаткові рядкові функції. Наприклад, W3C розглядає питання додавання коштів для заміни в рядках, заповнення символами і перетворень регістра;

Повинен підтримувати функції агрегації при застосуванні до колекцій. Наприклад, деяким користувачам XPath 1.0 потрібно застосувати таку функцію агрегації, як

, До значень виразів, застосованих до наборів вузлів;

Повинен підтримувати регулярні вирази для пошуку в рядках з використанням нотації регулярних виразів, встановленої в схемі XML;

Повинен підтримувати елементарні типи даних схеми XML. Тобто на додаток до типів, підтримуваним моделлю даних XPath 1.0, - рядку, числа, логічного значення і набору вузлів - модель даних XPath 2.0 повинна підтримувати елементарні типи даних схеми XML;

Повинен підтримувати уявлення чисел з плаваючою точкою одинарної і подвійної точності, підтримувані схемою XML, яка використовує наукову нотацію;

Повинен визначати відповідний набір функцій для роботи користувача з елементарними типами даних схеми XML;

Повинен додавати в XPath тип даних «список» (оскільки схема XML дозволяє визначати прості типи, успадковані від списку);

Повинен підтримувати доступ до значень простих типів елементів і атрибутів. Оскільки схеми XML представляють багато нових типів, XPath 2.0 повинен підтримувати доступ до власного, простого типу, значенню елемента або атрибута;

Повинен визначати поведінку операторів для нульових аргументів;

Повинен мати кошти для вибору елементів або атрибутів на основі явного типу схеми XML;

Повинен мати кошти для вибору елементів або атрибутів на основі ієрархії типів схеми XML;

Повинен мати кошти для вибору елементів на основі груп підстановки схеми XML;

Повинен підтримувати засоби пошуку, засновані на унікальних обмеженнях і ключах схеми.

Хоча ми підійшли до кінця глави, про XPath сказано ще не все. Тема буде продовжена в наступному розділі, в якій ми уважніше розглянемо доступні в XPath функції і функції, вже вбудовані в XSLT.

Приклади використання xpath з практики парсинга інформації з сайтів. Наведено ділянки коду xpath.

Отримати текст Тема h1

// h1 / text ()

Отримати текст Тема з класом produnctName

// h1 [@ class \u003d "produnctName"] / text ()

Отримати значення певного span по класу

// span [@ class \u003d "price"]

Отримати значення атрибута title у кнопки з класом addtocart_button

// input [@ class \u003d "addtocart_button"] / @ title

// a / text ()

// a / @ href

зображення src

// img / @ src

Зображення відразу за певним елементом в DOM, вісь following

// h1 [@ class \u003d "produnctName"] // following :: div / img / @ src

Зображення в 4 div по рахунку

// div / img / @ src

XPath (XML Path Language) - мова запитів до елементів XML-документа. Розроблено для організації доступу до частин документа XML в файлах трансформації XSLT і є стандартом консорціуму W3C. XPath покликаний реалізувати навігацію по DOM в XML.

XML має деревоподібну структуру. У елемента дерева завжди існують нащадки і предки, крім кореневого елемента, у якого предків немає, а також тупикових елементів (листя дерева), у яких немає нащадків.

На кожному кроці шляху відбираються елементи, що відповідають умовам відбору на цьому кроці, і в результаті звернення по шляху до документа виходить безліч елементів, що задовольняють даному шляху.

Функції над множинами вузлів

  • * - позначає будь-який ім'я або набір символів за вказаною осі, наприклад: * - будь-який дочірній вузол; @ * - будь-який атрибут.
  • $ Name - звернення до змінної, де name - ім'я змінної або параметра.
  • - додаткові умови вибірки або, що те ж саме, предикат кроку адресації. Повинен містити логічне значення. Якщо містить числове, вважається що це порядковий номер вузла, що еквівалентно приписування перед цим числом вираження «position () \u003d»
  • () - якщо застосовується всередині тега іншої мови (наприклад HTML), то XSLT процесор розглядає вміст фігурних дужок як XPath.
  • / - визначає рівень дерева, тобто розділяє кроки адресації
  • | - об'єднує результат. Тобто, можна написати кілька шляхів розбору через знак | і в результат такого виразу увійде все, що буде знайдено будь-яким з цих шляхів.
  • node-set node()

Повертає всі вузли. Замість цієї функції часто використовують замінник "*", але, на відміну від зірочки, функція node () повертає і текстові вузли.

  • string text()

Повертає набір текстових вузлів;

  • node-set current()

Повертає безліч з одного елемента, який є поточним. Якщо ми робимо обробку безлічі з умовами, то єдиним способом дотягнутися з цієї умови до поточного елемента буде дана функція.

  • number position()

Повертає позицію елемента в множині. Коректно працює тільки в циклі

  • number last()

Повертає номер останнього елемента в множині. Коректно працює тільки в циклі

  • number count(Node-set)

Повертає кількість елементів у node-set.

  • string name(Node-set?)

Повертає повне ім'я першого тега в множині.

  • string namespace-uri(Node-set?)
  • string local-name(Node-set?)

Повертає ім'я першого тега в безлічі, без простору імен.

  • node-set id(Object)

Знаходить елемент з унікальним ідентифікатором

Осі - це база мови XPath. Для деяких осей існують скорочені позначення.

  • ancestor :: - Повертає безліч предків.
  • ancestor-or-self :: - Повертає безліч предків і поточний елемент.
  • attribute :: - Повертає безліч атрибутів поточного елемента. Це звернення можна замінити на «@»
  • child :: - Повертає безліч нащадків на один рівень нижче. Ця назва скорочується повністю, тобто його можна зовсім опускати.
  • descendant :: - Повертає повне безліч нащадків (тобто, як найближчих нащадків, так і всіх їх нащадків).
  • descendant-or-self :: - Повертає повне безліч нащадків і поточний елемент. Вираз «/ descendant-or-self :: node () /" можна скорочувати до «//» . За допомогою цієї осі, наприклад, можна другим кроком організувати відбір елементів з будь-якого вузла, а не тільки з кореневого: досить першим кроком взяти всіх нащадків кореневого. Наприклад, шлях «// span» відбере всі вузли span документа, незалежно від їх положення в ієрархії, глянувши як на ім'я кореневого, так і на імена всіх його дочірніх елементів, на всю глибину їх вкладеності.
  • following :: - Повертає необроблене безліч, нижче поточного елемента.
  • following-sibling :: - Повертає безліч елементів на тому ж рівні, що настають за поточним.
  • namespace :: - Повертає безліч, що має простір імен (тобто присутній атрибут xmlns).
  • parent :: - Повертає предка на один рівень назад. Це звернення можна замінити на «..»
  • preceding :: - Повертає безліч опрацьованих елементів виключаючи безліч предків.
  • preceding-sibling :: - Повертає безліч елементів на тому ж рівні, що передують поточному.
  • self :: - Повертає поточний елемент. Це звернення можна замінити на «.»

XPath - це мова для запису виразів. Він має фундаментальне значення для обробки XML-документів. Не можна опанувати XSLT, не знаючи XPath, точно так же, як не можна вивчити англійську мову, не знаючи алфавіту. Деякі читачі першого видання цієї книги нарікали мені за те, що я не включив в неї основ XPath. Ця глава додана частково, щоб задовольнити їх, але головним чином тому, що в специфікації XPath 2.0 виразна міць цієї мови була значно посилена. Втім, багато рецептів працюватимуть і з XPath 1.0.

У XSLT 1.0 мову XPath використовується трьома способами. По-перше, в шаблонах він служить для адресації частин перетворюється документа. По-друге, він застосовується для завдання зразків в правилах зіставлення. По-третє, за допомогою вбудованих в XPath операторів і функцій виконуються прості математичні операції і маніпуляції з рядками.

У XSLT 2.0 зв'язок з XPath 2.0 збережена і навіть стала міцніше. У ньому широко використовуються нові обчислювальні засоби, що з'явилися в XPath 2.0. Можна навіть сказати, що додаткові можливості XSLT 2.0 - багато в чому результат нововведень в XPath 2.0, до числа яких відносяться послідовності, регулярні вирази, умовні і ітеративні вираження, система типів, сумісна зі специфікацією XML Schema, а також безліч нових вбудованих функцій.

Кожен рецепт в цій главі - це добірка міні-рецептів для вирішення певного класу задач, що виникають в XPath в контексті XSLT. Все XPath-вирази прокоментовані відповідно до прийнятого в XPath 2.0 угодою (: коментар :), але користувачам XPath 1.0 слід мати на увазі, що це неприпустима синтаксична конструкція. Порожній результат обчислення XPath-вирази ми будемо позначати (), саме так в XPath 2.0 записується порожня послідовність.

Потрібно відібрати вузли XML-дерева з урахуванням складних взаємозв'язків в ієрархічній структурі.

У всіх наведених нижче прикладах використовуються осі. У кожній групі для демонстрації береться якийсь XML-документ, в якому контекстний вузол виділений напівжирним шрифтом. Пояснюється, що є результатом обчислення шляху, при цьому показано, які елементи відбираються щодо виділеного контексту. У деяких випадках для ілюстрації тонкощів обчислення конкретного вираження розглядаються і інші вузли, крім контекстного.

Дочірня вісь і вісь нащадків

Дочірня вісь приймається в XPath за замовчуванням. Іншими словами, явно вказувати вісь child :: необов'язково, але, якщо ви хочете бути педантом, то можете і вказати. Спуститися по XML-дереву глибше, ніж на один рівень, дозволяють

осі descendant :: і descendant-or-self ::. Перша не включає сам контекстний вузол, друга - включає.

(: Відібрати всі дочірні елементи з ім'ям X

X (: той же, що child :: X)

результат:

(: Відібрати перший дочірній елемент з ім'ям X X

результат:

(: Відібрати останній дочірній елемент з ім'ям X X

результат:

(: Відібрати перший дочірній елемент за умови, що його ім'я X. Інакше порожньо *

результат:

(: Відібрати останній дочірній елемент за умови, що його ім'я X. Інакше порожньо

*

Результат: ()

(: Відібрати останній дочірній елемент за умови, що його ім'я Y. Інакше порожньо

*

результат:

(: Відібрати всіх нащадків з ім'ям X descendant :: X

результат:

(: Відібрати контекстний вузол, якщо його ім'я X, а також всіх нащадків з ім'ям X descendant-or-self :: X

результат:

(: Відібрати контекстний вузол і всіх його нащадків descendant-or-self :: *

результат:

осі братів

Осі братів називаються preceding-sibling :: і following-sibling ::. Ось preceding-sibling містить братів, що передують контекстного вузла, а вісь following-sibling - наступних за ним. Братами, природно, називаються діти одного батька. Майже у всіх прикладах нижче використовується вісь preceding-sibling ::, але вам не важко буде обчислити результат і для осі following-sibling ::.

Майте на увазі, що в позиційному вираженні виду preceding- sibling :: * ви посилаєтеся на який безпосередньо передує брата в порядку зворотного відліку від контекстного вузла, а не першого брата в порядку документа. Деяких бентежить той факт, що результуюча послідовність повертається в порядку документа незалежно від того, використовується вісь preceding-sibling :: або following-sibling ::. У вираженні ../ X, строго кажучи, ніяка вісь не зазначена; це просто спосіб відібрати попереднього і наступного брата з ім'ям X, а також сам контекстний вузол, якщо він називається X. Формально це скорочений запис виразу parent :: node () / X. Відзначимо, що вирази (preceding-sibling :: *) і (following-sibling :: *) відбирають першого попереднього або наступного брата в порядку документа.

(: Відібрати всіх братів з ім'ям A, що передують контекстного вузла preceding-sibling :: A

результат:

(: Відібрати всіх братів з ім'ям A, наступних за контекстним вузлом following-sibling :: A

результат:

(: Відібрати всіх братів, що передують контекстного вузла preceding-sibling :: *

результат:

(: Відібрати першого попереднього брата з ім'ям A в зворотному порядку документа preceding-sibling :: A

результат:

(: Відібрати першого попереднього брата в зворотному порядку документа за умови, що його ім'я A preceding-sibling :: *

Результат: ()

(: Якби контекстним був вузол , То в результаті ми отримали б

(: Відібрати всіх попередніх братів, окрім елементів з ім'ям A preceding-sibling :: *

результат:

(: В наступних прикладах використовується такий тестовий документ

(: Елемент, що безпосередньо передує контекстного вузла за умови, що у того є дочірній елемент з ім'ям A

preceding-sibling :: * [A]

Результат: ()

(: Перший з попередніх контекстного вузла елементів, у якого є дочірній елемент з ім'ям A

preceding-sibling :: * [A]

результат:

(: XPath 2.0 дозволяє більш гнучко вибирати елементи з урахуванням просторів імен. У наступних прикладах використовується такий XML-документ

(: Відібрати всіх попередніх братів контекстного вузла, для яких простір імен асоційоване з префіксом NS preceding-sibling :: NS: *

результат:

(: Відібрати всіх попередніх братів контекстного вузла, для яких локальне ім'я одно A preceding-sibling :: *: A

результат:

Батьківська вісь і вісь предків

Батьківська вісь (parent: :) відноситься до батьків контекстного вузла. Не плутайте вираз parent :: X з ../ X. Перше породжує послідовність, яка містить в точності один елемент, якщо ім'я батька контекстного вузла - X, і порожня в іншому випадку. Друге - це скорочений запис виразу parent :: node () / X, яке відбирає всіх братів контекстного вузла з ім'ям X, в тому числі і сам цей вузол, якщо він називається X.

За допомогою осей ancestor :: і ancestor-or-self :: можна переміщатися вгору по XML-дереву (переходячи до батькові чи матері, діда, прадіда і т.д.). У першому випадку сам контекстний вузол виключається, у другому - включається.

(: Повертає батька контекстного вузла, за умови, що він називається X, в іншому випадку - порожню послідовність. Parent :: X

(: Повертає батька контекстного вузла. Результат може бути порожнім, тільки якщо контекстний вузол є елементом верхнього рівня. Parent :: *

(: Повертає батька, якщо його простір імен асоційоване з префіксом X. Префікс повинен бути визначений, інакше станеться помилка.

(: Повертає батька незалежно від його простору імен за умови, що локальне ім'я одно X. :) parent :: *: X

(: Повертає всіх предків (включаючи одного з батьків) з ім'ям X. ancestor :: X

(: Повертає контекстний вузол, якщо він називається X, а також всіх предків з ім'ям X. ancestor-or-self :: X

Осі попередників і послідовників

Осі preceding :: і following :: можуть відбирати дуже багато вузлів, оскільки враховуються всі вузли, що передують контекстного (або наступні за ним) в порядку документа, виключаючи предків в разі осі following :: або нащадків для осі preceding ::. Не забувайте також, що обидві осі не включають вузли, відповідні просторів імен і атрибутів.

(: Усі попередні вузли з ім'ям X. preceding :: X

(: Найближчий попередник з ім'ям X. preceding :: X

(: Найдовший послідовник з ім'ям X. following :: X

Обговорення

У мові XPath поняття осі служить для того, щоб виділити в дереві документа різні підмножини вузлів щодо деякого вузла, званого контекстним. У загальному випадку ці підмножини перетинаються, але осі ancestor, descendant, following, preceding і self розбивають документ на непересічні частини, в сукупності містять всі вузли (за винятком тих, що відповідають просторам імен та атрибутів). Контекстний вузол встановлюється мовою, в який занурений XPath. У разі XSLT контекстний вузол встановлюють такі конструкції:

Зіставлення з шаблоном ( );

Xsl: apply-templates.

Вільне володіння мовою написання подорожніх висловлювань - необхідна умова для виконання як простих, так і складних перетворень. Досвід програмування на традиційних мовах часто служить причиною плутанини і помилок при роботі з XPath. Наприклад, я часто ловив себе на тому, що писав щось типу , маючи на увазі . Можливо, це пояснюється тим, що останній вираз - інтуїтивно менш зрозумілий спосіб висловити таку умову: «якщо ім'я безпосередньо передує брата одно X».

Звичайно, немає ніякої можливості показати всі корисні комбінації осей в колійних виразах. Але, якщо ви зрозумієте наведені вище приклади, то зможете розібратися, що означає вираз preceding-sibling :: X / descendant :: Z і ще більш складні.

Мангано Сел XSLT. Збірник рецептів. - М .: ДМК Пресс, СПБ .: БХВ-Петербург, 2008. - 864 с .: іл.

Xpath - це мова запитів до елементів xml або xhtml документа. Також як SQL, xpath є декларативною мовою запитів. Щоб отримати дані, що цікавлять, необхідно всього лише створити запит, що описує ці дані. Всю «чорну» роботу за вас виконає інтерпретатор мови xpath.
Дуже зручно, чи не так? Давайте подивися які можливості пропонує xpath для доступу до вузлів веб-сторінок.

Створення запиту до вузлів веб-сторінок

Пропоную вашій увазі невелику лабораторну роботу, в ході якої я продемонструю створення xpath запитів до веб-сторінці. Ви зможете повторити наведені мною запити і, найголовніше, спробуєте виконати свої. Я сподіваюся, що завдяки цьому стаття буде однаково цікава новачкам і програмістам знайомим з xpath по xml.

Для лабораторної нам знадобляться:
- веб-сторінка xhtml;
- браузер Mozilla Firefox з доповненнями;
- firebug;
- firePath;
(Ви можете використовувати будь-який інший браузер з візуальної підтримкою xpath)
- трохи часу.

Як веб-сторінки для проведення експерименту пропоную головну сторінку сайту консорціуму всесвітньої павутини ( "http://w3.org"). Саме ця організація розробляє мови xquery (xpath), специфікацію xhtml і багато інших стандарти інтернету.

завдання
Отримати з xhtml-коду головної сторінки w3.org інформацію про конференції консорціуму за допомогою запитів xpath.
Приступимо до написання xpath запитів.
Перший Xpath запит
Відкриваємо закладку Firepath в FireBug, виділяємо з селектором елемент для аналізу, натискаємо: Firepath створив xpath запит до вибраного елементу.

Якщо ви виділили заголовок першої події, то запит буде таким:

/ a

Після видалення зайвих індексів запит стане відповідати всім елементам типу «заголовок».

Firepath підсвічує елементи, які відповідають запиту. Ви можете в реальному часі побачити, які вузли документа відповідають запиту.

Запит для отримання інформації про місця проведення конференцій:
.//*[@id\u003d"w3c_home_upcoming_events"]/ul/li/div/p

Так ми отримаємо список спонсорів:
.//*[@id\u003d"w3c_home_upcoming_events"]/ul/li/div/p

синтаксис xpath

Давайте повернемося до створених запитам і розберемося в тому, як вони влаштовані.
Розглянемо докладно перший запит

У цьому запиті я виділив три частини для демонстрації можливостей xpath. (Поділ на частини уловное)

Перша частина
.// - рекурсивний спуск на нуль або більше рівнів ієрархії від поточного контексту. У нашому випадку поточний контекст це корінь документа

Друга частина
* - будь-який елемент,
[@ Id \u003d "w3c_home_upcoming_events"] - предикат, на основі якого здійснюємо пошук вузла, що має атрибут id рівним "w3c_home_upcoming_events". Ідентифікатори елементів XHTML повинні бути унікальні. Тому запит «будь-який елемент з конкретним ID» повинен повернути єдиний шуканий нами вузол.

Ми можемо замінити * на точне ім'я вузла div в цьому запиті
div [@ id \u003d "w3c_home_upcoming_events"]

Таким чином, ми спускаємося по дереву документа до потрібного нам вузла div [@ id \u003d "w3c_home_upcoming_events"]. Нас абсолютно не хвилює, з яких вузлів складається DOM-дерево і скільки рівнів ієрархії залишилося вище.

Третя частина
/ Ul / li / div / p / a -xpath-шлях до конкретного елемента. Шлях складається з кроків адресації і умови перевірки вузлів (ul, li і т.д.). Кроки поділяються символом "/" (коса риска).

колекції xpath
Не завжди вдається отримати доступ до цікавого вузлу за допомогою предиката або кроків адресації. Дуже часто на одному рівні ієрархії знаходиться наскільки вузлів однакового типу і необхідно вибрати «тільки перші» або «тільки другі» вузли. Для таких випадків передбачені колекції.

Колекції xpath дозволяють отримати доступ до елементу по його індексу. Індекси відповідають тому порядку, в якому елементи були представлені в оригінальному документі. Порядковий номер у колекціях відраховується від одиниці.

Виходячи з того, що «місце проведення» завжди другий параграф після «назви конференції», отримуємо наступний запит:
.//*[@id\u003d"w3c_home_upcoming_events"]/ul/li/div/p
Де p - другий елемент в наборі для кожного вузла списку / ul / li / div.

Аналогічно список спонсорів ми можемо отримати запитом:
.//*[@id\u003d"w3c_home_upcoming_events"]/ul/li/div/p

Деякі функції хpath
У хpath існує безліч функцій для роботи з елементами всередині колекції. Я приведу тільки деякі з них.

last ():
Повертає останній елемент колекції.
Запит ul / li / div / p - поверне останні параграфи для кожного вузла списку «ul».
Функція first () не передбачена. Для доступу до першого елементу використовуйте індекс «1».

text ():
Повертає тестове зміст елемента.
.//a - отримуємо все посилання з текстом «Archive».

position () і mod:
position () - повертає позицію елемента в множині.
mod - залишок від ділення.

Комбінацією даних функцій можемо отримати:
- Чи не парні елементи ul / li
- парні елементи: ul / li

операції порівняння

  • < - логическое «меньше»
  • \u003e - логічне «більше»
  • <= - логическое «меньше либо равно»
  • \u003e \u003d - логічне «більше або дорівнює»
ul / li, ul / li - елементи списку починаючи з 3го номера і навпаки.

Чи правильно я розумію, що за допомогою XPath не можна отримати значення атрибута вузла?

text

/ Root / @ id

отримуємо:

А отримати 1 не можна? Адже отримати text можна.

В якому сенсі "де"? Це строкове значення об'єкта, що повертається при виконанні вираження XPath.

У всякому разі Perl "овий модуль XML :: LibXML і плагін XPath Tool до редактора jEdit повертають саме це.

Зрозуміло. В Перлі.

Хіба XPath "десь" працює по різному?

Ага. наприклад,

виведуть "1". Без лапок.

Данбала [досьє] Ви нічого не плутаєте?

System.out.println (document.getRootElement (). GetAttributeValue ( "id"));

де тут xPath?
Суть то в тому, що xPath вираз виду / root / @ id має повернути за всіма правилами об'єкт типу attribute-node, який, зрозуміло, не є просто текст. А вже якщо ви хочете за допомогою xPath вираження отримати текстовий вузол - то, будьте ласкаві, так йому і напишіть.

Данбала [досьє]

А ось "Perl" овий модуль XML :: LibXML і плагін XPath Tool до редактора jEdit "виведуть id \u003d" 1 ".

Так, перепрошую, лапки я випадково пропустив, з лапками виведуть. Але суть це не міняє.

щодо Ви, якщо я правильно розумію, помиляєтеся. Вираз Xpath поверне саме id \u003d "1", просто потім XSLT з id \u003d "1" якимось чином отримає 1.

А System.out.println (document.getRootElement (). GetAttributeValue ( "id")); це не XPath, це DOM, вроде?

Я ж кажу про "голом" XPath, неважливо, в контексті XSLT він застосовується або ще десь.

Суть то в тому, що xPath вираз виду / root / @ id має повернути за всіма правилами об'єкт типу attribute-node, який, зрозуміло, не є просто текст.
А вже якщо ви хочете за допомогою xPath вираження отримати текстовий вузол - то, будьте ласкаві, так йому і напишіть.
З чого б це? А чому не результат someting.do (...). ToString ()?

Який такий someting.do (...). ToString ()? Я про XPath кажу! XPath може повернути text (), якщо вузол є текстовим, або node (), незалежно від типу. Але тип тип attribute-node не є, зрозуміло, текстовим, відповідно, text () не працює. Ось чому не працює node () - не розумію, але не працює.

А ви хочете йому за всіма правилами видати text-node, який також об'єкт, т. Е., Зрозуміло, не просто текст?

text-node, звичайно, не текст, але це не суттєво, потім вже якось прочитаємо. attribute-node теж не текст, але його ми теж можемо потім прочитати. Різниця в тому, що text-node містить строго то, що ми хотіли, а attribute-node - немає.

Іванов Михайло aka Ivanych [досьє] Я зробив рівно ось так:

\u003cScript\u003e

В поле я ввів відповідно: / root / @ id / text () і набув значення id. Якщо вводити / root / @ id то виходить id \u003d "test".

Іванов Михайло aka Ivanych [досьє]

Який такий someting.do (...). ToString ()?

Приблизно такий:

String xpath \u003d ...; Node node \u003d возвращатель_узов_по_xpath.дай_узли (xpath); System.out.println (node.getNodeValue ());

Я не знаю перл, але аналог getNodeValue () зобов'язаний в ньому бути.
Іншими словами, працюйте ні з node, а з його value.

Аааа ... JavaScript ... Все одно приблизно також.
Що-небудь типу:

Xxx.selectNodes (...). NodeValue

Іванов Михайло aka Ivanych [досьє]
Я б пробігся по їх властивостями:

With (this.xml.documentElement) (for (var prop in selectNodes (elm.value)) alert (prop) for (var prop in selectNodes (elm.value) .xml) alert (prop))

да вже додому йду.

Спробую викласти думку інакше.

text

Вираз / root поверне text-node, який в текстовому поданні буде дорівнює text .

Вираз / root / text () поверне також text-node, який в текстовому поданні буде дорівнює text.

Тобто для отримання вмісту текстової ноди можна використовувати оператор (або як він там називається) text ().

Вираз / root / @ id поверне attribute-node, який в тестовому представленні буде дорівнює id \u003d "1".

Оператор text () для отримання вмісту attribute-node непридатний, бо attribute-node це не текстова нода. експеримент GRAy [досьє], Мені здається, не зовсім чистий, бо я не впевнений, що (elm.value) це саме текстове представлення attribute-node, а не результат подальшої його обробки як в XSLT. Ну, або, може бути, MSXML дійсно так робить, але у мене такого інструменту немає.

Я хочу докопатися до істини і зрозуміти, чи можна зробити так, щоб текстовим поданням attribute-node замість id \u003d "1" було саме 1, за аналогією з тим, як текстове значення text-node text можна зробити рівним text за допомогою оператора text ().

olpa [досьє] Ні, так все одно не вийде.
Іванов Михайло aka Ivanych [досьє] Ви чогось не до кінця зрозуміли в моєму прикладі що й не дивно;) - я забув ще один інпут, поспішав ...


elm.value це текст самого xPath вираження. Можете поекспериментувати. Хоча згідно специфікації xPath вузли атрибутів і не містять в собі "справжні" текстові вузли, там однозначно нічого і не сказано про те, як повинна вести себе функція text () в разі її застосування до атрибутного вузлу. Боюся що така поведінка це ініціатива MS, але мені вона здається досить логічною.

fetis [досьє]
Я працював з XML засобами модуля XML :: LibXML (Perl). У цьому модулі є функція toString (), яка повертає текстове значення Ноди, повернутої виразом XPath. Ця функція прекрасно працює з текстовими вузлами.

І ось постало завдання отримання списку значень атрибутів. Атрибут - НЕ текстова нода, тому витягувати значення треба функцією nodeValue (), а не toString (). Відповідно, виникла думка - а чи не можна змусити XPath повернути саме текстову ноду і працювати з усіма нодамі одноманітно.

Тобто моє запитання чисто академічний, проблеми, повторюю, немає.