Avoid XML Schema restrictions

I am back on XML Schema design and I do really like it !

One of the challenge that I am facing now is including or not the UBL metalanguage in my schemas (see some video on the oasis website), an Oasis standard, as you can deduce.

As you can see from this file:


UBL metalanguage has elements which are based on the UN/CEFACT elements, see:


So as you can see UN/CEFACT has ComplexType which are extended by adding optional attributes, while the UBL elements are sometime restrictions  on the attributes (by making them required) and sometimes the elements are just extended giving a freedom in a later moment to choose what to add.

Independently from  the current problem, it happens that we might not need all the attributes or simply all the elements for our schema.

So either we add restrictions or we copy the elements that we need in our schema but simplified.

Adding restrictions can be possible in two ways:

1) Restrict on the patterns, like the max length of an element, they are so called facets, see: http://www.w3.org/TR/xmlschema-0/#SimpleTypeFacets

2) Restrict on the number of elements or attributes, in the case of the attributes  we need to make them prohibited

Conceptually both are restrictions based on an another type and this creates a problem in Object Oriented languages, like Java (hence the tittle of this post) which supports extensions (at the end a restriction is a sort of extension of a base object with some changes).

Jaxb is the official standard used for databinding XML elements to Java objects which relies on XJC for the conversion. Such standard adds Java annotations to associate XML elements to Java objects. Further, Jaxb relies on the validator of the marshaller by using the setSchema() method, see for example the post of Blaise Doughan, so in any moment you can validated your object against the schema to be sure before sending out your xml message.

For the facets, Jaxb doesn’t create annotations, there is still an open issue where 2 subgroups are working to solve it but still none of them are officially approved:

Other data bindings work on simple restrictions like enumerations (see Jibx) or numeric type and enumerations (see Xmlbeans, now archived).

You need also to consider that facets can change in the future (the max length could be extended from 100 characters to 200), so which impact has changing the xml schema? Since Jaxb doesn’t generate annotations for facets you don’t need to change the java objects but other databindings might be.

For the restriction on the the number of elements/attributes this CANNOT be reflected in a Object Oriented language because it is not possible to restrict an extended class on inherited properties. Therefore I suggest to copy simplified elements (by keep only those mandatory and removing the optionals), in this way:

  1. you have less dependency
  2. the developer has less method generated (just those needed)
  3. you keep compatibility at the minimum if you want to convert the copied object into the original objects

Therefore I would recommend to avoid restrictions if possible, you can keep them for the sake of validation but you need to think about the impact on the objects generated with the databinding libraries. Such recommandation is also expressed by the HP XML schema best practices (search for “restrictions for complex types”) and in Microsoft xml schema design pattern.





Selenium: testing PDF with Calibre

During my test activities I have arrived at the point that I need to test generated PDFs containing the same text that I have in a html page.

So I searched different PDF utilities that can be used through a command line to extract text out of a PDF, among these I found: pdftotext (a command line tool coming with xpdf), Calibre (an ebook manager/converter), Tika (used by Solr to index pdf content), pdfbox (a java application library that extract pdf).

Giving a better look Calibre is using poppler as library and pdftotext is using poppler as well while Tika is based on pdfbox library to extract text.

At the end I chose Calibre for different reasons:

  1. Calibre allows to extract hyperlinks from the pdf (main reason) when using a wiki syntax like textile (I didn’t find this possibility in pdftotext, tika or pdfbox) on the other side the generated text is with wiki syntax
  2. The development life cycle of Calibre is quite fast (compared with xpdf)
  3. Calibre points to release the application for Windows, Mac and Linux (with xpdf you can have different versions but the one for Mac is released on 2007)

Note that I don’t care the possibility to extract text from images, I know that with pdfimages command it is possible to extract them or other formats that tika can support.

I have to say that in terms of performance on the pdf I tested pdftotext is the fastest (0.01 sec), followed by pdfbox (1.7 sec), Calibre (2.3 sec) and then Tika (2.8 sec) on page , so if you don’t care about hyperlinks but just PDF text I would suggest to go to pdftotext.

After choosing Calibre I created a simple php application that:

  1. receives as parameter the URL of a PDF
  2. calls Calibre with different options on the PDF downloaded
  3. removes  some text (like empty lines, etc.)
  4. gives back an xml file with all the text generated.

I created then a selenium command that calls the php file (through an xmlhttp request) and search for a particular text (specified as input together with the url of the pdf file).

Php application (convert.php):

$content = file_get_contents($_GET['url']);
$filefrom = 'extract.pdf';
$fileto = preg_replace("/\.pdf$/","",$filefrom).".txt";
//$t_start = microtime(true);
//system("java -jar tika.jar -t ".escapeshellcmd($filefrom)." > ".escapeshellcmd($fileto),$ret);
system("ebook-convert ".escapeshellcmd($filefrom)." ".escapeshellcmd($fileto)."  >nul 2>&1",$ret);
//system("pdftotext -nopgbrk -raw ".escapeshellcmd($filefrom)." ".escapeshellcmd($fileto),$ret);
//system("java -jar pdfbox.jar ExtractText  ".escapeshellcmd($filefrom)." ".escapeshellcmd($fileto),$ret);
//$t_end = microtime(true);
  $value_empty_line=preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $value);
  header('Content-type: text/xml');
  echo "<result>".htmlspecialchars($text)."</result>";
  header('Content-type: text/xml');
  echo "<result>Convertion failed</result>";

Selenium command (assertSearhInPDF):

Selenium.prototype.assertSearchInPDF = function(uri,names){
  var baseurl = globalStoredVars['host'];
  var params = [{"param" : "url","value" : storedVars[uri],}];
  var lista = "";
  for(var i=0; i<params.length; i++){
    lista +="&" + params[i].param + "=" + encodeURIComponent(params[i].value);
  var indirizzo = baseurl+"/test/convert.php?"+lista;
  LOG.info( 'indirizzo = ' + indirizzo);
  var responseXML = chiamaWebService(indirizzo);
  LOG.info( 'response = ' + responseXML);
  var text = responseXML.getElementsByTagName('result')[0].firstChild.nodeValue;
  text = text.replace(/(\n)/g, " ");
  var array = names.split('|');
  var result=0;
  var length=array.length;
  LOG.info( 'text = ' + text);
  for (var i = 0; i < length; i++){
    if(text.indexOf(array[i]) !==-1){
      LOG.info( 'Found = ' + array[i]);
      LOG.info( 'Element ' + array[i]+' not found');
    Assert.fail("Not all the elements have been found");

In particular the selenium command can accept a list of elements (separated by “|”) to searched in the respective order, if they are not found the command fails.

Estendere Selenium per validare pagine web, parte 2

Nel precedente articolo abbiamo visto come sia semplice fare delle chiamate XmlhttpRequest da Selenium testando il tutto sul css validator.

In un’ottica di automatizzare i test di selenium con Hudson (vedi plugin), potremmo pensare anche di salvare o di inviare per email il report generato da guardare in un secondo momento.

Per fare ciò invece di chiamare direttamente il validator potremmo chiamare un proxy scritto in PHP (o in un altro linguaggio) che:

  1. prende in input l’indirizzo della pagina da validare, l’indirizzo email e il tipo di validazione (CSS21, CSS3 ecc)
  2. chiama il validator e ottiene il report in xml
  3. salva il report in html e invia l’html per email (usando un file xslt per fare la trasformazione da xml a html)
  4. restituisca il report xml.

Andiamo a vedere dunque il comando da selenium:

storeLocation entry
checkCss ${entry} validity, email=emidiostani@gmail.com, profile=CSS21
verifyExpression ${validity} true

Come potete vedere una volta memorizzato l’indirizzo della pagina corrente nella variable entry, passiamo tale indirizzo al comando checkCss che restituisce il valore della variabile validity e prende come opzioni l’email e il profile (magari è meglio spostarli nella colonna di centro in futuro). Verifichiamo alla fine che il valore della variabile validity sia true.

Andiamo a vedere il codice (vi risparmio la funzione chiama WebService che abbiamo già visto nel precedente articolo):

Selenium.prototype.doCheckCss = function( uri, names ){

 var email = "";
 var profile = "";
 var array = names.split(',');
 for (var i = 0; i < array.length; i++){
 var name = array[i].trim();
 LOG.info( 'email = ' + name);
 var email_array = name.split('=');
 email = email_array[1];
 else if(name.substr(0,7)=="profile"){
 LOG.info( 'profile = ' + name);
 var profile_array = name.split('=');
 profile = profile_array[1];

 var params = [
 "param" : "uri",
 "value" : uri,
 "param" : "email",
 "value" : email,
 "param" : "profile",
 "value" : profile,

 var lista = "";
 for(var i=0; i<params.length; i++){
 lista +="&" + params[i].param + "=" + encodeURIComponent(params[i].value);

 var proxycss ="";
 var indirizzo = proxycss+lista;
 LOG.info( 'indirizzo = ' + indirizzo);

 var responseXML = chiamaWebService(indirizzo);
 LOG.info( 'response = ' + responseXML);

 for (var i = 0; i < array.length; i++){
 var name = array[i].trim();
 if(name.substr(0,5)!="email" && name.substr(0,7)!="profile"){
 var name2 = "m:"+name;
 LOG.info( 'name2 = ' + name2);
 storedVars[name] = responseXML.getElementsByTagName(name2)[0].firstChild.nodeValue;
 LOG.info( 'callWebService: returned [' + storedVars[name] + ']' );

Nella prima parte estraiamo le opzioni email e profile da inserire insieme all’indirizzo (uri) nell’array params.

Concateniamo poi i parametri all’inidirizzo del proxy che contattiamo con la chiamaWebService (notate l’indirizzo ip che ovviamente dovete cambiare).

Estraiamo infine dalla risposta xml i parametri che abbiamo passato (ad eccezione di email e profile) da memorizzare nell’array associativo storedVars (predefinito per Selenium).

Ci resta da vedere il proxy php che dunque deve ricevere uri, email e profile e intrinsecamente:

  1. l’indirizzo della css validator (più altri parametri impliciti)
  2. il path del file xslt da applicare
  3. il path del report da salvare

Ed ecco il codice:


$uri = trim($_REQUEST['uri']);
$profile = trim(strtolower($_REQUEST['profile']));
$email = trim(strtolower($_REQUEST['email']));
$css = "";
$usermedium = "all";
$warning = "1";
$lang = "en";
$output = "soap12";

if($profile =='')
$address = $css."uri=".$uri."&profile=".$profile."&usermedium=".$usermedium."&warning=".$warning."&lang=".$lang."&output=".$output;
$result = file_get_contents($address);

$XSL = new DOMDocument();
$XSL->load( '/var/www/rest_style_css.xslt', LIBXML_NOCDATA);
$xslt = new XSLTProcessor();
$xslt->importStylesheet( $XSL );
$XML = new DOMDocument();
$XML->loadXML( $result );
$html = $xslt->transformToXML( $XML );

$dir = "reports/css/";
$report = "css-report-". date("H:i:s").".html";
$pathmyFile = "/var/www/".$dir.$report;
$fh = fopen($pathmyFile, 'w') or die("can't open file");
fwrite($fh, $html);

if($email !=''){
 $to = $email;
 $subject = 'CSS validation';
 $addresstomyfile = "<a href=http://".$_SERVER['SERVER_ADDR']."/".$dir.$report.">".$report."</a>";
 $message = "Report generated: ".$addresstomyfile." on ".date("j F, Y, g:i a")."\n".$html;
 $headers  = "From: Selenium Server<selenium.server@gmail.com>\r\n";
 $headers .= 'MIME-Version: 1.0' . "\r\n";
 $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
 mail($to, $subject, $message, $headers);

header('Content-type: text/xml');
echo $result;

Si suppone dunque che:

  1. avete  la libreria xml e xsl per php (riavviate apache dopo averla installata)
  2. avete creato la cartella reports/css sotto la var/www
  3. avete creato un file xslt (che trovate alla fine dell’articolo) nella var/www
  4. abbiate una applicazione come sendmail che è in ascolto per mandare email

Il codice è facile da leggere:

  • una volta estratti i parametri li concateniamo per chiamare il validator con il metodo file_get_content(),
  • convertiamo il file xml ottenuto in html tramite il file xslt
  • salviamo tale file nella cartella reports/css
  • se l’email era stata passata come opzione allora mandiamo email l’html ottenuto
  • restituiamo (possiamo vedere anche tramite browser) il risultato xml

Potremmo in futuro passare solo una parte del risultato xml per risparmiare banda usata.

Ora potete fare lo stesso con w3c validator (su Ubuntu installate w3c-markup-validator), rss validator (ho testato in remoto ma non installato), l’achecker per l’accessibilità (che potete traquillamente installare (vi consiglio da svn).

File xslt da usare:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:m="http://www.w3.org/2005/07/css-validator" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="html" encoding="UTF-8"/>
 <xsl:template match="m:cssvalidationresponse">
 <title>CSS report</title>
 <table width="100%">
 <TR bgcolor="#f7f3fd">
 <TD colspan="6">Analyzed web page address:
 <a href="{m:uri}" onclick="popup('{m:uri}; return false;')" title="{m:uri}" target="_new">
 <xsl:value-of select="m:uri" />
 <TR bgcolor="#f7f3fd">
 <TD colspan="3"><B>Errors</B></TD>
 <TR bgcolor="#f7f3fd">
 <TD><B>Error Type</B></TD>
 <TD><B>Error Subtype</B></TD>
 <TD><B>Skipped String</B></TD>
 <xsl:for-each select="m:result/m:errors/m:errorlist/m:error">
 <xsl:if test="(position() mod 2 = 1)">
 <xsl:attribute name="bgcolor">#EEEEFF</xsl:attribute>
 <TD><xsl:value-of select="m:line" /></TD>
 <TD><xsl:value-of select="m:errortype" /></TD>
 <TD><xsl:value-of select="m:context" /></TD>
 <TD><xsl:value-of select="m:errorsubtype" /></TD>
 <TD><xsl:value-of select="m:skippedstring" /></TD>
 <TD><xsl:value-of select="m:message" /></TD>
 <table width="100%">
 <TR rowspan="4" bgcolor="#f7f3fd">
 <TD width="10%"><B>Warnings</B></TD>
 <TR bgcolor="#f7f3fd">
 <TD width="10%"><B>Line</B></TD>
 <TD width="10%"><B>Level</B></TD>
 <TD width="70%"><B>Message</B></TD>
 <TD width="10%"><B>Context</B></TD>
 <xsl:for-each select="m:result/m:warnings/m:warninglist/m:warning">
 <xsl:if test="(position() mod 2 = 1)">
 <xsl:attribute name="bgcolor">#EEEEFF</xsl:attribute>
 <TD width="10%"><xsl:value-of select="m:line" /></TD>
 <TD width="10%"><xsl:value-of select="m:level" /></TD>
 <TD width="70%"><xsl:value-of select="m:message" /></TD>
 <TD width="10%"><xsl:value-of select="m:context" /></TD>

Estendere Selenium per validare pagine web

Come webmaster potreste trovarvi a coordinare un team composto da webdesigner, sviluppatore ed editore. Dovreste quindi verificare per esempio:

  • che il webdesigner abbia aggiustato il css del sito web,
  • che lo sviluppatore abbia realizzato la funzionalità di cercare nel sito o semplicemente quella di ingrandire il testo non appena si prema su un pulsante
  • che l’editore abbia effettivamente inserito un determinato testo nella pagina web.

Tutto ciò è già possibile testarlo con Selenium.

Sempre come webmaster potreste trovarvi nella situazione di validare le vostre pagine web verificando che esse rispettano standard w3c, css o ancora standard di accessibilità. Per fare tutto ciò esistono validatori online per cui indicando l’indirizzo della pagina web vi restituiscono un report di validità (in html o in xml).

Perchè dunque non aggiungere ai vari test fatti da Selenium la possibilità di chiamare i validatori sulla pagina che si sta analizzando ?

Dovete sapere che, poichè i comandi di Selenium sono scritti in javascript, è possibile dunque fare delle chiamate XmlHttpRequest dove indicate l’indirizzo del vostro validatore e farvi restituire il risultato XML da cui per esempio estraete il numero di errori trovato.

Per poter estendere Selenium dovete crearvi un file chiamato user-extensions.js da far caricare al Selenium IDE o da passare come parametro al selenium server. Ricordatevi che dovete caricare tale file nel Selenium IDE ogni qual volta lo modificate (almeno così noto che funziona).

Andiamo ora a vedere un file che definisce il comando ControllaCss che riceve come input l’indirizzo della pagina web da verificare e da come output  uno dei valori presenti nella risposta XML dal css validator:

function chiamaWebService(indirizzo){

 var req  = null;
 if (window.XMLHttpRequest){
 req = new XMLHttpRequest();
 else if (window.ActiveXObject){// per Internet Explorer
 req = new ActiveXObject("Microsoft.XMLHTTP");

 if (req){
 req.open( "GET", indirizzo, false );
 if ( req.status != 200 ){
 throw { status_code: req.status, status_text: req.statusText, response_text: req.responseText };
 return req.responseXML;
 catch  (e){
 return "errore:"+e.description;
 return "";

Selenium.prototype.doControllaCss = function( indirizzo_pagina, risultati ){

 var lista = "uri=" + encodeURIComponent(indirizzo_pagina);    

 var params = [
 "param" : "profile",
 "value" : "css21",
 "param" : "usermedium",
 "value" : "all",
 "param" : "warning",
 "value" : "1",
 "param" : "lang",
 "value" : "en",
 "param" : "output",
 "value" : "soap12",

 for(var i=0; i<params.length; i++){
 lista +="&" + params[i].param + "=" + encodeURIComponent(params[i].value);

 var url = "http://jigsaw.w3.org/css-validator/validator?";
 var indirizzo = url+lista;

 var rispostaXML = chiamaWebService(indirizzo);

 var array = risultati.split(',');
 for (var i = 0; i < array.length; i++){
 var variabile = array[i].trim();
 var variabile2 = "m:"+variabile;
 storedVars[variabile] = rispostaXML.getElementsByTagName(variabile2)[0].firstChild.nodeValue;
 LOG.info( 'valore ottenuto: ' + storedVars[variabile] );

In breve abbiamo una funzione ChiamaWebService che riceve l’indirizzo del web service da chiamare (completo di parametri), effettua l’operazione di GET e restituisce la risposta XML.

La seconda parte definisce il comando ControllaCss (notare il prefisso “do”) e riceve l’indirizzo della pagina da validare e un array di variabili separate da virgola dove memorizzare valori estrapolati dalla rispota XML.

Notate che per i vari parametri chiamo la funzione encodeURIComponent per codificare particolari caratteri.

La parte più importante è l’ultima:

 var array = risultati.split(',');
 for (var i = 0; i < array.length; i++){
 var variabile = array[i].trim();
 var variabile2 = "m:"+variabile;
 storedVars[variabile] = rispostaXML.getElementsByTagName(variabile2)[0].firstChild.nodeValue;
 LOG.info( 'valore ottenuto: ' + storedVars[variabile] );

In pratica dividiamo i vari valori che sono separati dalla virgola, eliminiamo spazi bianchi, aggiungiamo il prefisso “m:” (questo perchè nella risposta xml del validatore css i tag hanno il prefisso “m:”), memorizziamo nell’array storedVars (array usato da Selenium) il valore della variabile estratta con quel particolare tag e poi stampiamo il valore della variabile con il comando di log.

Ora con Selenium IDE carichiamo il file user-extensions.js (vedere tra le opzioni) e creiamo un test case del tipo:

open /
storeLocation page
controllaCss ${page} validity
verifyExpression ${validity} true

In pratica memorizziamo nella variabile “validity” il valore estratto dalla risposta XML e verifichiamo che tale valore sia “true”. Potremmo anche verificare il valore di “errorcount” per vedere il numero degli errori sia 0.

Come errore dovreste avere qualcosa come:

[error] Actual value 'false' did not match 'true.'

Ora siete pronti a chiamare altri servizi come il w3c validator e Achecker (di cui vi avevo già parlato).

Nota: magari volete installarvi il css validator in locale, potete scaricare il war e farne il deploy su Tomcat o Glassfish (io l’ho fatto su Glassfish 3.0.1, attenzione che dentro il file web-inf.xml dovete invertire le righe mime types con welcome file list).

Achecker, validare le vostre pagine web

Come webmaster vi troverete a migliorare le vostre pagine web sotto diversi punti di vista, uno di questi è di sicuro la validazione delle vostre pagine web per l’accessibilità secondo diversi standard:

  • WCAG 1.0/2.0 A/AA/AAA
  • legge Stanca
  • BITV (standard tedesco)
  • Sezione 508 (standard americano)
  • JIS (standard giapponese)

Probabilmente avrete già la Web Developer Toolbar in Firefox che si aggancia a diversi siti per la validazione WAI e 508.

Tra gli strumenti elencati dal W3C troverete di certo Achecker un software libero sviluppato dall’Advanced Technology Resource Centre dell’Università di Toronto e supportato dalla provincia dell’Ontario (in cui Toronto si trova).

Achecker 1.0 supporta gli standard sopra elencati eccetto JIS, è scritto in PHP (e richiede MySQL) ed è rilasciato con licenza GPL.

Mi sono deciso di installarlo su Xampp la cui ultima versione dispone PHP 5.3 ma a quanto pare Achecker è scritto in PHP 5.2 ho dunque corretto 7 files (fino ad ora) di codice deprecato, principalmente dovrete:

  • Rimuovere il carattere & perchè l’assegnamento in PHP 5.3 avviene già per rifererimento
  • Rimpiazzare la funzione eregi(regularexpression) con preg_match(/regularexpression/i), vedi qui
  • Rimpiazzare la funzione split con explode

Inutile che vi dico i file, vedrete i warning con i vostri occhi durante la fase di installazione. L’installazione è semplice, vi crea in automatico il database e vi chiede di creare una cartella temporanea e i soliti username e password per accedere come amminstratore all’interfaccia.

L’interfaccia è semplice, potete gestire gli utenti/gruppi, le linee guida (quali rendere pubbliche o no), tutti i tipi di controlli da effettuare, in che lingua visualizzare l’interfaccia e il profilo utente.

Nel profilo utente noterete il Web Service ID che è una sorta di chiave per poter usare Achecker in modalità web-service.

Infatti potete passare da url tutti i parametri che volete per la validazione e farvi restituire i risultati in HTML o XML (modalità REST), per esempio:

http://localhost/AChecker/checkacc.php?uri=http%3A%2F%2Fatutor.ca&amp; id=888ca9e3f856baa0120755ecd8ffae6be3142029&output=html&guide=STANCA,WCAG2-AA

dove si passa l’url, il web service id, il tipo di output, le guide da consultare.

Inoltre Achecker viene suggerito come strumento dall’IPG Europeo per testare l’accessibilità dei siti web europei.

Buona validazione !

Soa Design Pattern: progettare web services

Al di là dell’implementazione di un web service occorre pensare a come progettarli; normalmente l’implementazione è fatta su misura dei messaggi scambiati ma a livello architetturale dovete pensare a come nel tempo i vostri web services potrebbero mutare.
Un esempio banale è quello che il vostro xml schema cambi o semplicemente il contratto (file wsdl) possa cambiare per una qualunque ragione e da qui il concetto di versioning che si puo’ applicare anche alle semplici policy di accesso.

Per affrontare questi problemi occorre avere una buona panoramica e in questo Thomas Erl riesce bene con il suo libro Soa Design Pattern da cui è stato realizzato un sito web:  http://www.soapatterns.org/ che ho scoperto oggi

Sulla destra potete notare il lungo elenco di design pattern che sono descritti nel libro. Tra l’altro sul sito potete notare 2 poster interessanti da stampare:


Per quello che ho potuto notare Thomas è autore di un sacco di libri sull’argomento SOA (vedete: http://www.soapatterns.com/ ) tra cui il libro sugli Enterprise Service Bus che sarà lanciato al SOA Symposium il 22-23 Ottobre  a Rotterdam (l’ingresso costicchia).