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