Учебник по XPath

Этот учебник - введение в XPath, язык запросов, который можно использовать для выбора произвольных частей HTML в calibre. XPath является широко используемым стандартом, и при поиске в google он даст тонну информации. Однако в этом учебнике основное внимание уделяется использованию 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> Очень короткая электронная книга, для демонстрации использования XPath.</p> в Образец электронной книги, но не какие-либо другие теги``<p>``. Префикс h:``в приведённых выше примерах необходим для соответствия тегам XHTML. Потому что внутреннее представление всего контента в calibre - в XHTML. В тегах XHTML есть *namespace*, а ``h: - префикс пространства имен для HTML-тегов.

Теперь предположим, что вы хотите выбрать теги <h1> и <h2>. Для этого нам нужна конструкция XPath, называемая predicate. A predicate - это просто тест, который используется для выбора тегов. Тесты могут быть произвольно мощными, и по мере продвижения по этому учебнику вы увидите более мощные примеры. Предикат создается путем заключения тестового выражения в квадратные скобки

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

В этом выражении XPath имеется несколько новых функций. Во-первых, это использование подстановочного символа *. Это означает соответствие любому тегу. Теперь посмотрим на тестовое выражение name()='h1' or name()='h2'. name() это пример built-in function (встроенной функции). Это просто оценка имени тега. Используя этот пример мы можем выбрать теги, имена которых либо 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 built-in functions (встроенных функций 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(src, pattern, flags) возвращает true, если строка src соответствует регулярному выражению pattern. Особенно полезен флаг i: он отвечает за нечувствительность к регистру. Хороший учебник синтаксиса регулярных выражений для начинающих можно найти по ссылке regexp syntax.