Tecnologie Web: Parte 6m [Martedì, 6 Giugno 2006]

Home /  Teaching

Creare file XML

Abbiamo visto come sia possibile leggere ed utilizzare in una pagina JSP un file XML esterno (ad esempio un file di configurazione). L'approccio può sicuramente essere efficace e più conveniente di un database tradizionale allorquando i dati a cui accedere siano in quantità limitata.

E se invece volessimo scrivere un file XML? Le librerie di TAG non ci vengono incontro. Né è possibile farlo tramite tag JSP. Dobbiamo utilizzare una servlet o almeno una scriplet e utilizzare direttamente Java.

Vediamolo con un esempio. Per farlo funzionare è necessario completare l'installazione del parser XML Xalan, copiando dal file di installazione [che potete trovare all'indirizzo http://www.apache.org/dist/xml/xalan-j/, ad esempio scaricate xalan-j_2_7_0-bin.zip] il file serializer.jar che va nella cartella lib della vostra applicazione.

Sempre nella cartella lib dovete anche copiare il file commons-jxpath-x.x.jar che scaricate dal sito http://jakarta.apache.org/site/downloads/downloads_commons-jxpath.cgi

Nell'esempio seguente, esempioScritturaXml.jsp, leggeremo un file XML esterno che salveremo nuovamente dopo averlo modificato. È un utile esercizio di ripasso di quanto visto durante il corso. Utili indicazioni ulteriori su come manipolare file XML da Java le trovate in forma succinta in questo tutorial on-line: http://totheriver.com/learn/xml/xmltutorial.html.

<%@ page import="org.w3c.dom.*" %>
<%@ page import="org.apache.commons.jxpath.*" %>
<%@ page import="java.io.*" %>
<%@ page import="javax.xml.transform.*" %>
<%@ page import="javax.xml.transform.dom.*" %>
<%@ page import="javax.xml.transform.stream.*" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>

<c:set var="nomeFileIn" value="gestioneAsilo.xml" />
<c:set var="nomeFileOut" value="gestioneAsiloModificato.xml" />
<c:import var="MioFile" url="${nomeFileIn}" />
<x:parse varDom="domMioFile" doc="${MioFile}" />

<html>
<head>
  <title>Esempio di manipolazione di file XML in JSP</title>
</head>
<body>
In questo esempio vedremo come modificare un file XML. L'operazione non 
viene effettuata tramite TAG standard, ma direttamente in Java.

Lavoreremo sul file XML <b>${nomeFileIn}</b> che 
contiene il seguente documento:
<pre>
<c:out value="${MioFile}" />
</pre>
Il terzo bambino non ha configurato il valore dell'identificativo: 
<x:out select="$domMioFile/asilo/bambino[3]/@id"/>
<br /><br />

<%
// Document --> org.w3c.dom.Document
// JXPathContext --> org.apache.commons.jxpath.JXPathContext
// Pointer --> org.apache.commons.jxpath.Pointer
// Element --> org.w3c.dom.Element
// Text --> org.w3c.dom.Text
Document documentoXml = (Document) pageContext.getAttribute("domMioFile");
JXPathContext contextMioFile = JXPathContext.newContext(documentoXml);
Pointer puntatoreElemento = contextMioFile.getPointer("asilo/bambino[3]");
Element elementoDaModificare = (Element) puntatoreElemento.getNode();
elementoDaModificare.setAttribute("id", "palla");

// Crea un elemento figlio "Nome" e gli associa il valore testuale "Mario"
Element sottoElementoNome = documentoXml.createElement("nome");
Text valoreSottoElementoNome = documentoXml.createTextNode("Mario");
sottoElementoNome.appendChild(valoreSottoElementoNome);

//Crea un elemento figlio "Cognome" e gli associa il valore testuale "Rossi"
Element sottoElementoCognome = documentoXml.createElement("cognome");
Text valoreSottoElementoCognome = documentoXml.createTextNode("Rossi");
sottoElementoCognome.appendChild(valoreSottoElementoCognome);

//Associa i sotto elementi all'elemento da modificare selezionato in precedenza
elementoDaModificare.appendChild(sottoElementoNome);
elementoDaModificare.appendChild(sottoElementoCognome);
%>

Il documento XML in memoria è stato opportunamente modificato. 
Per il terzo bambino ora abbiamo: <br />
<b>Identificativo</b>: <x:out select="$domMioFile/asilo/bambino[3]/@id"/> <br />
<b>Nome</b>: <x:out select="$domMioFile/asilo/bambino[3]/nome"/> <br />
<b>Cognome</b>: <x:out select="$domMioFile/asilo/bambino[3]/cognome"/> <br /><br />

<%
File fileOutput = new File(application.getRealPath((String) pageContext.getAttribute("nomeFileOut")));
// DOMSource --> javax.xml.transform.dom.DOMSource
// StreamResult --> javax.xml.transform.stream.StreamResult
DOMSource source = new DOMSource(documentoXml);
StreamResult result = new StreamResult(fileOutput);
// [22/12/2006] Utilizzando Windows può essere necessario: 
// StreamResult result = new StreamResult(fileOutput.toURI().getPath());
    
// Per scrivere il file usiamo un Transformer identità 
// (non compie alcuna operazione sul file)
// TransformerFactory --> javax.xml.transform.TransformerFactory
// Transformer --> javax.xml.transform.Transformer
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 

transformer.transform(source, result); 
%>

Il file ${nomeFileOut} modificato
è stato scritto in <%=application.getRealPath("/")%>

</body>
</html>

Il file XML di input era: gestioneAsilo.xml. mentre il file prodotto è il seguente: gestioneAsiloModificato.xml.

Architettura MVC

Durante il corso abbiamo appreso due importanti tecnologie, le servlet Java e le pagine JSP. Ma come utilizzarle in pratica? Nel gergo Sun esistono due architetture: "Model 1" e "Model 2". Vediamolo in due figure, tratte da un ottimo articolo http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html (anche se oramai datato)

Two-Tier Architecture

Three-Tier Architecture

L'architettura "Model 2" è di fatto l'implementazione in questo contesto una architettura a più ampia diffusione, l'architettura MVC, dove M="Model", V="View" e C="Controller".

Alternativamente, si può presentare una visione a "stack" dell'architettura. Un ottimo articolo è http://www.onjava.com/pub/a/onjava/2003/10/15/php_scalability.html, da cui sono tratte le figure seguenti.

Two-Tier Architecture

Three-Tier Architecture

Tipicamente, il blocco controller viene implementato tramite il framework "Apache Struts" (http://struts.apache.org/). Struts offre una servlet di controllo standard: tutte le richieste che terminano in .do vengono opportunamente mappate ad endpoints, che ad esempio possono essere semplicemente file jsp che hanno lo stesso nome (es: pagina.do --> pagina.jsp).

Mappare semplicemente le pagine può essere utile per permettere una facile rilocazione delle risorse ma serve poco. La cosa importante è che dobbiamo dire alla nostra servlet di controllo come operare sui dati (il modello) prima di passare il controllo alla pagina JSP. In breve, dobbiamo opportunamente estendere la classe org.apache.struts.action.Action e prevedere i mapping opportuni tra le classi che abbiamo preparato e lo stato delle risposte alle richieste ricevute

<action-mappings>
...
<action
path="/addnews"
type="com.jspbook.AddNewsAction">
<forward name="success" path="/addnews_thanks.jsp"/>
<forward name="failure" path="/addnews.jsp"/>
</action>
...
</action-mappings>

Resta ancora da chiarire come operare l'astrazione relativa all'accesso a dati di database esterni. Una delle tecnologie (non l'unica) oggi in voga è Hibernate (http://www.hibernate.org). Semplificando la situazione, l'idea è quella di provvedere un mapping opportuno tra un oggetto Java Bean e la tabella di un database e poi lasciare ad Hibernate il resto del lavoro.

<hibernate-mapping>
   <class name="org.sassi.Item" table="item" >
      <id name="id" column="id" type="java.lang.Long" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <property name="name" column="name" type="java.lang.String" />
      <property name="description" column="description" type="java.lang.String" />
   </class>
</hibernate-mapping>

Un breve tutorial, se siete interessati lo trovate a questo indirizzo: http://www.laliluna.de/first-hibernate-example-tutorial.html