XPath-Tutorial

In this tutorial, you will be given a gentle introduction to XPath, a query language that can be used to select arbitrary parts of HTML documents in calibre. XPath is a widely used standard, and googling it will yield a ton of information. This tutorial, however, focuses on using XPath for e-book related tasks like finding chapter headings in an unstructured HTML document.

Selecting by tag name

Die einfachste Form einer Auswahl ist die Auswahl von Tags durch deren Namen. Wenn man z. B. alle <h2>-Tags in einem Dokument finden möchte, ist die dazu passende XPath-Abfrage:

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

Das Präfix // bedeutet suche auf jeder Ebene des Dokuments. Angenommen, Sie möchten nun nach <span>-Tags suchen, die sich innerhalb von <a>-Tags befinden. Dies wird durch den folgenden Ausdruck erreicht:

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

Wenn Sie nach Tags einer bestimmten Ebene im Dokument suchen möchten, ändern Sie das Präfix wie folgt ab:

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

This will match only <p>A very short e-book to demonstrate the use of XPath.</p> in the Sample e-book but not any of the other <p> tags. The h: prefix in the above examples is needed to match XHTML tags. This is because internally, calibre represents all content as XHTML. In XHTML tags have a namespace, and h: is the namespace prefix for HTML tags.

Nehmen wir nun an, Sie möchten sowohl <h1> als auch <h2> Tags auswählen. Um dies zu erreichen, brauchen wir ein XPath-Konstrukt, welches Prädikat genannt wird. Ein Prädikat ist ein Test, um gesuchte Tags zu finden. Tests können beliebig umfangreich sein. Mit den weiteren Beispielen werden diese umfangreicher. Man erstellt ein Prädikat, indem der Testausdruck in eckigen Klammern eingeschlossen wird:

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

In diesem XPath-Ausdruck gibt es einige neue Eigenschaften. Die erste ist die Verwendung des Platzhalters *. Dieser bedeutet finde jeden Tag. Nun schauen wir uns den Testausdruck name()='h1' or name()='h2' an. name() ist ein Beispiel für eine integrierte Funktion. Hierbei wird der Name des angegebenen Tags ausgewertet. Wendet man dies wie in unserem Beispiel an, werden alle Tags mit dem Namen h1 oder h2 gefunden. Beachten Sie, dass die Funktion name() Namensräume ignoriert. Es besteht daher keine Notwendigkeit für die Anwendung des Präfix h:. XPath hat einige nützliche Funktionen integriert. Weitere werden in dieser Anleitung vorgestellt.

Auswahl über Attribute

Um Tags nach ihren Attributen auszuwählen, ist die Verwendung von Prädikaten erforderlich:

//*[@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")

Der @-Operator bezieht sich auf die Attribute eines Tags. Sie können einige der XPath built-in functions nutzen, um anspruchsvollere Abfragen auf Attributwerte auszuführen.

Auswahl nach Tag-Inhalt

Mithilfe von XPath können Sie auch Tags auswählen, die sich auf einen im Tag enthaltenen Text beziehen. Der beste Weg ist die Verwendung der Fähigkeiten von regulären Ausdrücken über die integrierte Funktion re:test():

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

Der .-Operator bezieht sich auf den Inhalt eines Tags, sowie sich der @-Operator auf seine Attribute bezieht.

Sample e-book

<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>

Integrierte XPath-Funktionen

name()
Der Name des aktuellen Tags.
contains()
contains(s1, s2) gibt true zurück wenn s1 s2 beinhaltet.
re:test()
re:test(src, pattern, flags) gibt true zurück, wenn die Zeichenfolge src den regulären Ausdruck mit dem Suchmuster pattern enthält. Ein besonders hilfreiches Kennzeichen ist i, es findet Zeichenfolgen unabhängig von der Groß-/Kleinschreibung. Eine gute Einführung in die Syntax für reguläre Ausdrücke finden Sie unter regexp syntax