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.

Adesso, immagina di voler selezionare sia i tag <h1> che quelli <h2>. Per farlo, abbiamo bisogno di un costrutto XPath chiamato predicato. Un predicato è semplicemente un test usato per selezionare i tag. I test possono essere arbitrariamente potenti e continuando lungo questa guida vedrai degli esempi sempre più potenti. Un predicato si crea racchiudendo l’espressione di test in parentesi quadre:

//*[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.

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