Підручник з XPath

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

Вибір за назвою теґу

Найпростішою формою вибору є вибір теґів за назвою. Наприклад, припустімо, що вам хочеться вибрати усі теґи <h2> у документі. Запит XPath для цього буде дуже простим:

//h:h2        (Selects all <h2> tags)

Префікс «//» означає шукати на усіх рівнях документа. Тепер, припустімо, що ви хочете знайти теґи <span>, які перебувають всередині теґів <a>. Зробити це можна ось так:

//h:a/h:span    (Selects <span> tags inside <a> tags)

Якщо ви хочете шукати теґи на певному рівні у документі, змініть префікс:

/h:body/h:div/h:p (Selects <p> tags that are children of <div> tags that are
             children of the <body> tag)

Буде знайдено лише <p>A very short ebook to demonstrate the use of XPath.</p> у Зразок книги, але не буде знайдено жодного іншого теґу <p>. Префікс h: у наведених вище прикладах потрібен для встановлення відповідності теґам XHTML. Він потрібен, тому що на внутрішньому рівні calibre представляє усі дані як XHTML. У теґів XHTML є власний простір назв, і h: є префіксом простору назв для теґів HTML.

Тепер, припустімо, вам потрібно вибрати одразу теґи <h1> і теґи <h2>. Для виконання цього завдання нам знадобиться конструкція XPath, яка називається предикатом. предикат є простою перевіркою, яка використовується для вибору теґів. Перевірки можуть мати довільну потужність. У межах цього розділу ми наведемо і потужніші приклади. Предикат створюється взяттям виразу перевірки у квадратні дужки:

//*[name()='h1' or name()='h2']

У цьому виразі XPath є декілька нових особливостей. Першою є використання замінника *. Цей замінник означає знайти будь-який теґ. Далі, зверніть увагу на вираз перевірки name()='h1' or name()='h2'. name() є прикладом вбудованої функції. Ця функція просто повертає назву теґу. Отже, за її допомогою ми можемо вибрати теґи, назвами яких є h1 або h2. Зауважте, що функція name() ігнорує простори назв, отже, у додаванні префікса h: немає потреби. У XPath є декілька корисних вбудованих функцій. Ще декілька буде представлено у цьому розділі.

Вибір за атрибутами

Для вибору тегу на основі його атрибутів слід користуватися предикатами:

//*[@style]              (Select all tags that have a style attribute)
//*[@class="chapter"]    (Select all tags that have class="chapter")
//h:h1[@class="bookTitle"] (Select all h1 tags that have class="bookTitle")

Тут оператор @ посилається на атрибути теґу. Ви можете скористатися деякими з вбудованих функцій XPath для встановлення складних відповідностей із значеннями атрибутів.

Вибір за вмістом теґу

За допомогою XPath ви навіть можете вибирати теґи на основі тексту, який у них міститься. Найкращим способом це зробити є використання потужності формальних виразів, тобто вбудованої функції re:test():

//h:h2[re:test(., 'chapter|section', 'i')] (Selects <h2> tags that contain the words chapter or
                                          section)

Тут оператор . посилається на вміст теґу, так само, як оператор @ посилається на його атрибути.

Зразок книги

<html>
    <head>
        <title>A very short e-book</title>
        <meta name="charset" value="utf-8" />
    </head>
    <body>
        <h1 class="bookTitle">A very short e-book</h1>
        <p style="text-align:right">Written by Kovid Goyal</p>
        <div class="introduction">
            <p>A very short e-book to demonstrate the use of XPath.</p>
        </div>

        <h2 class="chapter">Chapter One</h2>
        <p>This is a truly fascinating chapter.</p>

        <h2 class="chapter">Chapter Two</h2>
        <p>A worthy continuation of a fine tradition.</p>
    </body>
</html>

Вбудовані функції XPath

name()
Назва поточного теґу.
contains()
contains(s1, s2) повертає «true», якщо s1 містить s2.
re:test()
re:test(джерело, взірець, прапорці) повертає true, якщо рядок джерело відповідає формальному виразу взірець. Одним із особливо корисних прапорців є i, прапорець, який вимикає врахування регістру символів під час порівняння. Чудовий підручник із синтаксису формальних виразів можна знайти на сторінці синтаксису формальних виразів