Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

JOOX: XML fluent API in java

Introduciamo JOOX: una libreria per utilizzare XML tramite una fluent api
Introduciamo JOOX: una libreria per utilizzare XML tramite una fluent api
Link copiato negli appunti

JOOX è una libreria che permette di creare, leggere e manipolare documenti xml (può essere considerata un wrapper del package org.w3c.dom) utilizzando delle fluent api, concatenando ad esempio una sequenza di operazioni in cascata.

Il funzionamento di JOOX è incentrato su poche classi di fondamentale importanza:

  • JOOX: costituisce l'entry point per l'accesso a tutte le altre funzionalità fornite dalla libreria.
  • Match: rappresenta una collezione di elementi DOM corrispondendi ad un particolare filtro di selezione (Filter).
  • Filter e FastFilter: rappresentano i filtri che vengono applicati ai Match per selezionare un sottoinsieme degli elementi del Match in base ai criteri di filtraggio definiti.
  • Each: è la classe mediante la quale è possibile definire delle funzioni di callback che vengono invocare per tutti gli elementi all'interno di un Match.

Accesso JQuery-like

Dal momento che JOOX trae ispirazione da JQuery può essere utile definire, per chi ha avuto già a che fare con la famosa libreria javascript, delle modalità di accesso simili.

In particolare a partire da Java 5 è possibile utilizzare il costrutto “import static” per importare una o più classi e procedere quindi all'invocazione dei metodi statici senza fare riferimento al nome della classe statica che li contiene.

import static org.joox.JOOX.*;

Parsing di un documento xml

Per effettuare il parsing di un documento xml si usa il metodo $ della classe static JOOX.

Come detto è possibile accedere a tale metodo facendo riferimento direttamente alla classe JOOX (quindi JOOX.$(...)) oppure una volta effettuato l'import static della classe senza fare riferimento a questa (quindi direttamente con $(...)).

Quindi supponendo di voler effettuare il parsing di un documento xml memorizzato nel file documento.xml utilizzeremo la seguente istruzione:

Match m = $(new File("c:/documento.xml"));

Come vediamo il risultato di questa istruzione produce un'istanza della classe Match che wrappa una lista ordinata di elementi DOM senza duplicati fornendo operazioni utili effettuabili su tutti gli elementi in essa contenuti.

Per gli esempi successivi utilizzeremo il seguente documento xml:

<documento>
	<libri>
		<libro id="1">
			<nome>Io uccido</nome>
			<autori>
				<autore>Giorgio Faletti</autore>
			</autori>
		</libro>
		<libro id="2">
			<nome>I promessi sposi</nome>
			<autori>
				<autore>Alessandro Manzoni</autore>
			</autori>
		</libro>
		<libro id="3">
			<nome>Flatlandia</nome>
			<autori>
				<autore>Edwin Abbott</autore>
			</autori>
		</libro>
	</libri>
	<films>
		<film id="1">
			<nome>La vita è bella</nome>
			<attori>
				<attore>Roberto Benigni</attore>
				<attore>Nicoletta Braschi</attore>
			</attori>
		</film>
	</films>
</documento>

Funzioni di base (prima parte)

Alcune delle principali funzioni di base che è possibile applicare sulle istanze della classe Match (e quindi su tutti gli elementi DOM in esse contenuti) sono:

  • isEmpty(): restituisce true se l'istanza Match non contiene elementi DOM
  • isNotEmpty(): restituisce true se l'istanza Match non contiene elementi DOM
  • size(): restituisce il numero di elementi DOM presenti all'interno del Match
  • tag(): estrae il nome del tag da ogni elemento DOM presente all'interno del Match
  • content(): restituisce il contenuto di ogni elemento DOM presente all'interno del Match

Utilizzo delle classi Filter e FastFilter

A partire da una classe Match è possibile selezionare un subset degli elementi DOM in essa contenuta (ottenendo una nuova istanza della classe Match) attraverso l'utilizzo delle funzioni filter e find:

  • filter: agisce direttamente sugli elementi DOM presenti all'interno della classe Match
  • find: agisce sui figli di ogni elemento DOM presente all'interno della classe Match

Entrambi questi metodi utilizzano come argomenti un Filter (o FastFilter) rappresentante le condizioni di selezione degli elementi del Match.

Alcuni dei filtri più comuni e semplici da utilizzare sono:

tag

estrae tutti gli elementi corrispondenti ad un dato tag

m.find(tag("libro"));

leaf

estrae tutti gli elementi che sono nodi-foglia

m.find(leaf());

ids

estrae tutti gli elementi che hanno id fra quelli passati come argomenti

m.find(ids(1,3));

odd

estrae gli elementi di posto dispari

m.find(tag("libro")).find(odd());

even

estrae gli elementi di posto pari

m.find(tag("libro")).find(odd());

E' possibile effettuare una composizione logica di due o più filtri mediante and, or, not come negli esempi seguenti:

m.find(or(tag("libro"), tag("film")));
m.find(and(tag("libro"), ids("1")));
m.find(and(tag("libro"), not(ids("1"))));

Funzioni di base (seconda parte)

Ovviamente attraverso JOOX è possibile navigare direttamente attraverso gli elementi del documento xml.

child(n)

recupera il figlio n-esimo di tutti gli elementi del Match

Match secondo_libro = m.find(tag("libri")).child(1);

next()

recupera l'elemento immediatamente successivo a ciascuno degli elementi del Match

Match terzo_libro = secondo_libro.next();

prev()

recupera l'elemento immediatamente precedente a ciascuno degli elementi del Match

Match primo_libro = secondo_libro.prev();

sibling()

recupera tutti gli elementi adiacenti a ciascuno degli elementi del Match

Match adiacenti = primo_libro.siblings();

parent()

recupera l'elemento padre di ciascuno degli elementi del Match

Match padre = primo_libro.parent();

parents()

recupera tutti gli antenati di ciascun elemento del Match

Match antenati = adiacenti.parents();

Modifica del documento xml

E' possibile infine modificare la struttura di un documento xml attraverso apposite funzioni:

prepend(...)

inserisce in testa al contenuto di ogni elemento DOM del Match il codice xml passato come argomento

primo_libro.prepend("primo");

append(...)

inserisce in coda al contenuto di ogni elemento DOM del Match il codice xml passato come argomento

primo_libro.append("ultimo");

append(...)

inserisce in coda al contenuto di ogni elemento DOM del Match il codice xml passato come argomento

primo_libro.append("ultimo");

content(...)

costituisce il contenuto di ogni elemento DOM del Match con il codice passato come argomento

primo_libro.content("contenuto");

attr(attributo, valore)

modifica il contenuto dell'attributo di ogni elemento DOM del Match con quello passato come secondo argomento

secondo_libro.attr("attributo", "valore");

Eseguire una funzione per ogni elemento DOM di un Match

Per eseguire una funzione personalizzata per ogni elemento DOM all'interno dell'istanza di un Match è possibile utilizzare la funzione each(...) passando come argomento l'istanza di una classe che implementa l'interfaccia Each.

Tale interfaccia è sostanzialmente costituita da un metodo con la seguente firma:

public void each(Context context)

che viene invocato per ogni elemento del Match dove Context è rappresentativo dell'elemento DOM corrente e costituisce il punto di accesso per recuperare le informazioni su di esso.

La seguente implementazione ad esempio stampa il contenuto testuale di tutti gli elementi del Match in grassetto:

public class BoldEach implements Each {
	@Override
	public void each(Context context) {
		System.out.println(""+context.element().getTextContent()+"");
	}
}

E viene utilizzata nel seguente modo:

istanza_match.each(new BoldEach());

In questo modo è particolarmente semplice l'implementazione di funzioni di parsing avanzate, concettualmente simili a dei callback: per esempi più sofisticati (utilizzo di xslt, associazione con ORM, etc) rimandiamo ad articoli successivi.

Ti consigliamo anche