Christian Castelli
a- a+

Validazione documenti XML

COLDFUSION E XML

Validazione dei documenti XML

ColdFusion fornisce funzioni per controllare se un documento XML è ben formato o valido secondo un XML Schema o un DTD fornito. ci sono funzioni addizionali per controllare differenti parti di un documento XML. Queste funzioni vengono spiegate qui sotto.

IsXML()

La funzione IsXML() determina se la stringa passata come argomento è un documento XML ben formato. Ritorna true se lo è, altrimenti false. L'esempio seguente mostra come usare tale funzione.

Es 10: IsXML.cfm

<cfparam name="FORM.XmlText" 
          default="<Name>
                   <FirstName>George</FirstName>
                   <LastName>Washington</LastName>
                   </Name>">
  <html>
  <head>
  <title>IsXML()</title>
  </head>
  <body>
  <h1>XML Test</h1>
  <cfoutput>
  <form method="post" action="#CGI.SCRIPT_NAME#">
  <textarea name="XmlText" cols="60" rows="10">#FORM.XmlText#</textarea>
  <br>
  <input name="SubmitButton" type="submit" value="Check XML">
  <cfif isDefined("FORM.SubmitButton")>
   <cfif IsXML(FORM.XmlText)>
    <span style="margin-left:200px;color:green">XML is well formed.</span>
   <cfelse>
    <span style="margin-left:200px;">XML is not well formed.</span>
   </cfif>
  </cfif>
  </form>
  </cfoutput>
  </body>
  </html>

 

<a href="/img/22/iframe_CF_xml10.html" title= "Vedi esempio">Vedi codice</a>;

 

La pagina mostra semplicemente un form contenente una textarea per contenenre il documento XML. quando il form viene sottomesso, la pagina usa la funzione isXML() per controllare se il testo inserito rappresenta un documento ben formato e mostra un messaggio con il risultato di tale validazione.

Quando la pagina viene aperta per la prima volta, appare così:

isxml1
Fig 6a: documento xml risultante dall'esempio 10

Quando si sottomette il form con un documento ben formato, la pagina mostra un messaggio di successo in basso a destra:

isxml2
Fig 6b: risultato della validazione dell'esempio 10

Quando si sottomette il form con un documento XML non ben formato, la pagina mostra un messaggio di errore in rosso:

isxml3
Fig 6c: risultato della validazione dell'esempio 10

XmlValidate()

La funzione XmlValidate() viene usata per validare un documento XML partendo da un XML Schema o un DTD. La funzione prende i seguenti parametri:

I parametri di XmlValidate()

Parametro

Descrizione

xmlDoc Obbligatorio. Può assumere uno qualsiasi dei seguenti valori:
  • una stringa XML
  • un percorso assoluto o un URL ad un file XML
  • un XML DOM
validator Opzionale. Può assumere uno qualsiasi dei seguenti valori:
  • una stringa contenente un DTD o un XML Schema
  • un percorso assoluto o un URL ad un DTD o un XML Schema

La funzione ritorna una struttura contenente i seguenti campi:

  • Status - un valore booleano indicante se la validazione ha avuto successo;
  • Errors - un array contenente gli errori;
  • FatalErrors - un array contenente errori fatali, di solito indicanti che il documento XML non è ben formato;
  • Warnings - un array contenete gli avvertimenti.

Per illustrare quanto esposto fin'ora, useremo il seguente semplice XML Schema:

Es. 11a: Name.xsd

<?xml version="1.0" encoding="UTF-8"?>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="Name">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="FirstName" type="xs:string"/>
      <xs:element name="LastName" type="xs:string"/
     </xs:sequence>
     <xs:attribute name="Title" type="xs:string" use="optional"/>
    </xs:complexType>
   </xs:element>
  </xs:schema>

 

<a href="/img/22/iframe_CF_xml11a.html" title= "Vedi esempio">Vedi codice</a>;

 

Tale schema richiede che l'elemento Name del documento abbia due nodi figli, FirstName and LastName, e un attributo opzionale, Title.

ColdFusion usa il parser Xerces per validare i documenti XML. Per effettuare correttamente la validazione quando viene usato il parametro di validazione, il parser richiede l'utilizzo degli attributi xmlns:xsi e xsi:noNamespaceSchemaLocation. Per illustrare quanto detto, viene presentata una dimostrazione dell'utilizzo di IsXML().

Es. 11b: XmlValidate.cfm

<cfparam name="FORM.XmlText"
          default="<Name xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                    xsi:noNamespaceSchemaLocation=''>
                   <FirstName>George</FirstName>
                   <LastName>Washington</LastName>
                   </Name>">
  <html>
  <head>
  <title>XmlValidate()</title>
  </head>
  <body>
  <h1>XML Validation Test</h1>
  <cfoutput>
  <form method="post" action="#CGI.SCRIPT_NAME#">
  <textarea name="XmlText" cols="60" rows="10">#FORM.XmlText#</textarea>
  <br>
<input name="SubmitButton" type="submit" value="Validate XML">
  <cfif isDefined("FORM.SubmitButton")>
   <cfset structResults = XmlValidate(FORM.XmlText,ExpandPath("Name.xsd"))>
   <cfif structResults.status>
    <span style="margin-left:200px;color:green">XML is valid.</span>
   <cfelse>
    <span style="margin-left:200px;">XML is not valid.</span>
    <div style="margin-top:10px">
    <cfif ArrayLen(structResults.Errors)>
     <b>Errors:</b>
     <ol style="margin-top:0px">
      <cfloop index="i" from="1" to="#ArrayLen(structResults.Errors)#">
       <li>#structResults.errors[i]#</li>
      </cfloop>
     </ol>
    </cfif> 
   <cfif ArrayLen(structResults.FatalErrors)>
     <b>Fatal Errors:</b>
     <ol style="margin-top:0px">
      <cfloop index="i" from="1" to="#ArrayLen(structResults.FatalErrors)#">
       <li>#structResults.fatalErrors[i]#</li>
      </cfloop>
     </ol>
    </cfif>
    <cfif ArrayLen(structResults.Warnings)>
     <b>Warnings:</b>
     <ol style="margin-top:0px">
      <cfloop index="i" from="1" to="#ArrayLen(structResults.Warnings)#">
       <li>#structResults.warnings[i]#</li>
      </cfloop>
     </ol>
    </cfif>
    </div>
   </cfif>
  </cfif>
  </form>
  </cfoutput>
  </body> 
 </html>

 

<a href="/img/22/iframe_CF_xml11b.html" title= "Vedi esempio">Vedi codice</a>;

 

quando la pagina viene aperta per la prima volta, appare così:

xmlvaltest1
Fig 7a: output iniziale dell'esempio 11

Quando il form viene sottomesso con un documento XML validom la pagina mostra un messaggi odi successo in basso a destra...

xmlvalidtest2
Fig 7b: risultato della validazione per l'esempio 11

altrimenti vengono mostrati gli errori presenti nel documento:

xmlvalidtest3
Fig 7c: risultato della validazione per l'esempio 11

Il documento XML ha svariati problemi:

  • Gli errori sono problemi con la validità del documento XML in accordo allo schema specificato. In questo caso, l'attributo title dovrebbe avere la "T" maiuscola e non è permesso utilizzare l'elemento MiddleName;
  • Gli errori fatali sono problemi legati alla well-formedness di un documento XML. In questo caso, l'elemento di chiusura di LastName dovrebbe avere la "N" maiuscola;
  • non ci sono avvertimenti, che generalmente sono difficili da produrre nella validazione del parser.

IsXmlDoc(), IsXmlRoot(), IsXmlElem(), IsXmlAttribute(), IsXmlNode()

  • IsXmlDoc(): ritorna true se il parametro fornito è un oggetto rappresentante un documento XML;
  • IsXmlRoot(): ritorna true se il parametro fornito è l'elemento radice di un documento XML;
  • IsXmlElem(): ritorna true se il parametro fornito è un elemento XML;
  • IsXmlAttribute(): ritorna true se il parametro fornito è un attributo XML;
  • IsXmlNode():ritorna true se il parametro fornito è un nodo XML.

I file seguenti mostrano come usare le funzioni introdotte poco fa.

Es. 12: XmlParts.cfm

<cfset xmlGeorge=XMLParse(ExpandPath("George.xml"))>
  <html>
  <head>
  <title>XML Parts</title>
  <style type="text/css">
  .YES {background-color:#00cc00; font-weight:bold;}
  .NO {color:#ff0000;}
  </style>
  </head>
  <body>
  <h1>XML Parts</h1>
  <table border="1" cellpadding="2" cellspacing="0">
  <tr>
   <th>#</th>
   <th>XML Part</th>
   <th>IsXmlDoc()</th>
   <th>IsXmlRoot()</th>
   <th>IsXmlElem()</th>
   <th>IsXmlAttribute()</th>
   <th>IsXmlNode()</th>
  </tr>
  <cfoutput>
  <cfset part = xmlGeorge>
  <tr>
   <td>1</td>
   <td>xmlGeorge</td>
   <td class="#IsXmlDoc(part)#">#IsXmlDoc(part)#</td>
   <td class="#IsXmlRoot(part)#">#IsXmlRoot(part)#</td>
   <td class="#IsXmlElem(part)#">#IsXmlElem(part)#</td>
   <td class="#IsXmlAttribute(part)#">#IsXmlAttribute(part)#</td>
   <td class="#IsXmlNode(part)#">#IsXmlNode(part)#</td>
  </tr>
  <cfset part = xmlGeorge.Name>
  <tr>
   <td>2</td>
   <td>xmlGeorge.Name</td>
   <td class="#IsXmlDoc(part)#">#IsXmlDoc(part)#</td>
   <td class="#IsXmlRoot(part)#">#IsXmlRoot(part)#</td>
   <td class="#IsXmlElem(part)#">#IsXmlElem(part)#</td>
   <td class="#IsXmlAttribute(part)#">#IsXmlAttribute(part)#</td>
   <td class="#IsXmlNode(part)#">#IsXmlNode(part)#</td>
  </tr>
  <cfset part = xmlGeorge.Name.XmlAttributes.Title>
  <tr>
   <td>3</td>
   <td>xmlGeorge.Name.XmlAttributes.Title</td>
   <td class="#IsXmlDoc(part)#">#IsXmlDoc(part)#</td>
   <td class="#IsXmlRoot(part)#">#IsXmlRoot(part)#</td>
   <td class="#IsXmlElem(part)#">#IsXmlElem(part)#</td>
   <td class="#IsXmlAttribute(part)#">#IsXmlAttribute(part)#</td>
   <td class="#IsXmlNode(part)#">#IsXmlNode(part)#</td>
  </tr>
  <cfset part = xmlGeorge.Name.FirstName>
  <tr>
   <td>4</td>
   <td>xmlGeorge.Name.FirstName</td>
   <td class="#IsXmlDoc(part)#">#IsXmlDoc(part)#</td>
   <td class="#IsXmlRoot(part)#">#IsXmlRoot(part)#</td>
   <td class="#IsXmlElem(part)#">#IsXmlElem(part)#</td>
   <td class="#IsXmlAttribute(part)#">#IsXmlAttribute(part)#</td>
   <td class="#IsXmlNode(part)#">#IsXmlNode(part)#</td>
  </tr>
  <cfset part = xmlGeorge.Name.XmlChildren[1]>
  <tr>
   <td>5</td>
   <td>xmlGeorge.Name.XmlChildren[1]</td>
   <td class="#IsXmlDoc(part)#">#IsXmlDoc(part)#</td>
   <td class="#IsXmlRoot(part)#">#IsXmlRoot(part)#</td>
   <td class="#IsXmlElem(part)#">#IsXmlElem(part)#</td>
   <td class="#IsXmlAttribute(part)#">#IsXmlAttribute(part)#</td>
   <td class="#IsXmlNode(part)#">#IsXmlNode(part)#</td>
  </tr>
  <cfset part = xmlGeorge.Name.FirstName.XmlText>
  <tr>
   <td>6</td>
   <td>xmlGeorge.Name.FirstName.XmlText</td>
   <td class="#IsXmlDoc(part)#">#IsXmlDoc(part)#</td>
   <td class="#IsXmlRoot(part)#">#IsXmlRoot(part)#</td>
   <td class="#IsXmlElem(part)#">#IsXmlElem(part)#</td>
   <td class="#IsXmlAttribute(part)#">#IsXmlAttribute(part)#</td>
   <td class="#IsXmlNode(part)#">#IsXmlNode(part)#</td>
  </tr>
  </table>
  </cfoutput>
  </body>
  </html>

 

<a href="/img/22/iframe_CF_xml12.html" title= "Vedi esempio">Vedi codice</a>;

 

La pagina mostrerà il seguente risultato:

xmlparts
Fig 8: risultato dell'esempio 12

Quanto visto è piuttosto intuitivo. Le uniche sorprese sono le modalità con cui vengono gestiti nodi ed attributi. Secondo quando mostrato dalla terza riga, l'attributo Title non è né un attributo né un nodo XML. E secondo quanto mostrato nella sesta riga, il testo all'interno dell'elemento FirstElement non rappresenta un nodo XML. L'attributo Title è certamente un attributo XML e tutti gli attributi e i testi in un documento XML sono nodi XML; ad ogni modo ColdFusion tratta gli attributi come proprietà di un elemento, non come nodi, e tratta il testo come puro testo piuttosto che come testo appartenente ad un nodo XML.

XmlNodes Array

Ogni elemento possiede un array XmlNodes, che contiene i nodi degli elementi degli elementi, i nodi testuali, i nodi dei commenti, e le sezioni CDATA. Non contiene nodi degli attributi degli elementi. Per accedere agli attributi, si deve usare la struttura XmlAttributes.

XmlGetNodeType()

La funzione XmlGetNodeType() viene usata per determinare il tipo del nodo passato come parametro. I due esempi seguenti mostrano come agisce la funzione.

Es. 13: GetNodeType.cfm

<cfset xmlGeorge=XMLParse(ExpandPath("George.xml"))>
  <html>
  <head>
  <title>XmlGetNodeType()</title>
  </head>
  <body>
  <h1>XmlGetNodeType()</h1>
  <cfoutput>
  <ol>
   <cfset part = xmlGeorge>
   <li>
    xmlGeorge:
     <cftry>
     #XmlGetNodeType(part)#
     <cfcatch type="any"><span style="">#cfcatch.Message#</span></cfcatch>
    </cftry>
   </li>
      <cfset part = xmlGeorge.Name>
   <li>
    xmlGeorge.Name:
     <cftry>
     #XmlGetNodeType(part)#
     <cfcatch type="any"><span style="">#cfcatch.Message#</span></cfcatch>
    </cftry>
   </li>
      <cfset part = xmlGeorge.Name.XmlAttributes.Title>
   <li>
    xmlGeorge.Name.XmlAttributes.Title:
     <cftry>
     #XmlGetNodeType(part)#
     <cfcatch type="any"><span style="">#cfcatch.Message#</span></cfcatch>
    </cftry>
   </li>
      <cfset part = xmlGeorge.Name.FirstName>
   <li>
    xmlGeorge.Name.FirstName:
     <cftry>
     #XmlGetNodeType(part)#
     <cfcatch type="any"><span style="">#cfcatch.Message#</span></cfcatch>
    </cftry>
   </li>
      <cfset part = xmlGeorge.Name.XmlChildren[1]>
   <li>
    xmlGeorge.Name.XmlChildren[1]:
     <cftry>
     #XmlGetNodeType(part)#
     <cfcatch type="any"><span style="">#cfcatch.Message#</span></cfcatch>
    </cftry>
   </li>
      <cfset part = xmlGeorge.Name.FirstName.XmlText>
   <li>
    xmlGeorge.Name.FirstName.XmlText:
     <cftry>
     #XmlGetNodeType(part)#
     <cfcatch type="any"><span style="">#cfcatch.Message#</span></cfcatch>
    </cftry>
   </li>
  </ol>
  </cfoutput>
  </body>
  </html>

 

<a href="/img/22/iframe_CF_xml13.html" title= "Vedi esempio">Vedi codice</a>;

 

Il risultato degli esempi precedenti viene mostrato nella figura sottostante:

xmlgetnodetype
Fig 9: risultato dell'esempio 13

Es. 14: XmlNodes.cfm

<cfset xmlGeorge=XMLParse(ExpandPath("George2.xml"))>
  <cfset nameNodes = xmlGeorge.Name.XmlNodes>
  <html>
  <head>
  <title>XmlNodes()</title>
  </head>
  <body>
  <h1>XmlNodes()</h1>
  <ol>
  <cfoutput>
  <cfloop index="i" from="1" to="#ArrayLen(nameNodes)#">
   <li>#XmlGetNodeType(nameNodes[i])# - #IsXmlNode(nameNodes[i])#</li>
  </cfloop>
  </cfoutput>
  </ol>
  </body>
  </html>

 

<a href="/img/22/iframe_CF_xml14.html" title= "Vedi esempio">Vedi codice</a>;

 

Il risultato dell'esempio precedente viene mostrato nella figura sottostante:

xmlnodes
Fig 10: risultato dell'esempio 14

Noterete che ha importanza come l'elemento viene richiamato. Quando i nodi testuali vengono richiamati attraverso la notazione a punti (ad esempio xmlGeorge.Name.FirstName.XmlText), non vengono trattati come nodi XML, al contrario di quando vengono richiamati attraverso l'array XmlNodes. La stessa cosa vale per i nodi dei commenti e delle sezioni CDATA. Per andar sul sicuro, dovreste sempre testare un possibile nodo con la funzione IsXmlNode() prima di trattarlo come un nodo XML.


Conclusioni

Con quest'ultima parte, riguardante XML in ColdFusion, termina la guida introduttiva a ColdFusion.



Ti potrebbe interessare anche

commenta la notizia

C'è 1 commento
Redazione
Ti interessano altri articoli su questo argomento?
Chiedi alla nostra Redazione!