Guida di XPath

In questa guida ti sarà fornita un’introduzione graduale a XPath, un linguaggio per query che può essere utilizzato per selezionare parti arbitrarie di documenti HTML in calibre. XPath è uno standard ampiamente utilizzato e una ricerca su Google rivelerà parecchie informazioni. Questa guida, tuttavia, si concentra sull’utilizzo di XPath per compiti relativi agli e-book, come trovare le intestazioni dei capitoli in un documento HTML non strutturato.

Selezione per nome del tag

La forma più semplice di selezione è selezionare i tag per nome. Ad esempio, immagina di voler selezionare tutti i tag «<h2>» in un documento. La query di XPath per farlo è semplicemente:

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

Il prefisso // significa cerca ad ogni livello del documento. Adesso immagina di dover cercare dei tag <span> che si trovano dentro tag <a>. Ciò si può ottenere con:

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

Se vuoi cercare dei tag in un livello particolare del documento, modifica il prefisso:

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

Questo troverà solo <p>A very short e-book to demonstrate the use of XPath.</p> nel Libro di esempio, ma nessuno degli altri tag <p>. Il prefisso h: negli esempi precedenti è richiesto per trovare i tag XHTML. Ciò è necessario perché, internamente, calibre rappresenta tutti i contenuti come XHTML. In XHTML i tag hanno un namespace e h: è il prefisso di namespace per i tag HTML.

Now suppose you want to select both <h1> and <h2> tags. To do that, we need an XPath construct called predicate. A predicate is simply a test that is used to select tags. Tests can be arbitrarily powerful and as this tutorial progresses, you will see more powerful examples. A predicate is created by enclosing the test expression in square brackets:

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

Ci sono diverse nuove funzionalità in questa espressione XPath. La prima è l’uso del carattere jolly *. Significa trova qualsiasi tag. Ora dai un’occhiata all’espressione di test name()='h1' or name()='h2'. name() è un esempio di funzione interna. Essa valuta semplicemente il nome del tag. Quindi, usandola, possiamo selezionare tag i cui nomi sono h1 o h2. Tieni presente che la funzione name() ignora gli spazi di nomi in modo che non sia necessario il prefisso h:. XPath ha diverse utili funzioni interne. Alcune di loro saranno introdotte in questa guida.

Selezione per attributi

Per selezionare i tag in base alle loro caratteristiche, è richiesto l’uso di predicati

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

Qui, l’operatore @ si riferisce agli attributi del tag. È possibile utilizzare alcune delle funzioni incorporate di XPath per eseguire una corrispondenza più sofisticata sui valori degli attributi.

Nota

When XPath expressions are used for conversion options such as chapter detection or the start reading at position, they are evaluated against the input document, before calibre flattens the CSS. CSS flattening rewrites class names, so the class names you see in the converted output (things like calibre1) do not exist yet when your expression runs. Copy class names from the input document, not from the converted book. If in doubt, match on tag names and text content instead, as these are not changed by the conversion.

Selezione per contenuto del tag

Usando XPath, puoi persino selezionare i tag in base al testo che contengono. Il modo migliore per farlo è usare la potenza delle espressioni regolari tramite la funzione integrata re: test():

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

Qui l’operatore . si riferisce al contenuto del tag, proprio come l’operatore @ si riferiva ai suoi attributi.

Libro di esempio

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

Funzioni interne di XPath

name()

Il nome del tag attuale

contains()

contains(s1, s2) restituisce true se s1 contiene s2.

re:test()

`re:test(src, pattern, flags) restituisce true se la stringa src corrisponde all’espressione regolare pattern. Un flag particolarmente utile è i, che non considera la differenza MAIUSCOLE/minuscole. Un primo aiuto sulla sintassi per le espressioni regolari è disponibile in sintassi delle regexp<https://docs.python.org/2.7/library/re.html> _