UEFA2
Databasen (MySQL) er bygget opp med to tabeller som (re)settes slik:
_Ligaer
DROP TABLE IF EXISTS `ligas`; CREATE TABLE `ligas` ( `ligaid` CHAR(10) NOT NULL, `name` VARCHAR(45) NOT NULL, `nationid` CHAR(2) NOT NULL, `level` SMALLINT NOT NULL, PRIMARY KEY (`ligaid`) )ENGINE=InnoDB DEFAULT CHARSET=utf8;
_Klubber
DROP TABLE IF EXISTS `clubs`; CREATE TABLE `clubs` ( `id` CHAR(20) NOT NULL, `name` VARCHAR(45) NOT NULL, `level` SMALLINT NOT NULL, `aliases` MEDIUMTEXT DEFAULT NULL, `homepage` VARCHAR(95) DEFAULT NULL, `wiki` VARCHAR(95) DEFAULT NULL, `logo` VARCHAR(95) DEFAULT NULL, `arenaname` VARCHAR(45) NOT NULL, `arenawiki` VARCHAR(95) DEFAULT NULL, `capasity` INT DEFAULT NULL, `lng` VARCHAR(30) DEFAULT NULL, `lat` VARCHAR(30) DEFAULT NULL, `data` MEDIUMTEXT DEFAULT NULL, `comments` MEDIUMTEXT DEFAULT NULL, `nationid` CHAR(2) NOT NULL, PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=utf8;
Liga tabellen er ikke i bruk i dette eksempelet. Vi kunne brukt den til å bygge menyen på eksempelsiden. Vi bruker følgende SQL-setning for å hente data og produsere JSON:
select name,logo,arenaname from clubs where level='"+level+"' and nationid='"+nation+"' order by name;"
der nation er det landet vi er interesserte i (f.eks. NO for Norge), og level er det nivået vi skal ha (f.eks 1 for tippeligaen).
Starten på XML-fila vi får tilbake fra tjeneren starter f.eks. slik:
<?xml version="1.0"?> <resultset statement="select name,logo,arenaname from clubs where level='1' and nationid='DE' order by name" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"> <row> <field name="name">Augsburg</field> <field name="logo">https://borres.hiof.no/resources/fotballogos/DE0017.png</field> <field name="arenaname">SGL arena</field> </row> <row> ... </row> </resultset>
Python
Den involverte Python-koden som leverer Json er slik:
_select2XML.py
#! /usr/bin/python import cgi,sys from lxml import etree import dbutils import cgitb; cgitb.enable() """ select from database to json using mysql in a subprocess as implemented in utils """ # transform xml -> json XSLT_FILE='tojson.xsl' form=cgi.FieldStorage() """ Need connect. | separated string Sequence is important: user|password|host|database|table sql """ print 'Content-type: text/plain; charset=utf-8 \n' try: # always connect connect=form['connect'].value sql=form['sql'].value # set up parameters p=dbutils.prepareSelectParameters(connect,sql) if len(p) > 0: print dbutils.makeJson(p,'data/select.xml',XSLT_FILE) else: print 'error bad parameter list in connect' except: res=sys.exc_info() print 'error '+str(res[1])
som benytter samme biblioteket som løsningen i modulen uefa1 :
_dbutils.py
#! /usr/bin/python import cgi,sys import subprocess from lxml import etree """ Run a subprocess, used to perform: extract from database with mysqldump or mysql return ok or error.... """ def doProcess(params,targetfile): try: f=open(targetfile,'wb') p=subprocess.check_call(params,stdout=f,stderr=f,shell=False) f.flush() f.close() if p==0: return 'ok' else: return 'error in subprocess: '+str(p) except: res=sys.exc_info() return 'error '+ str(res[1]) """ extract from database and make an xslt transform to legal JSON return the JSON string or error.... """ def makeJson(params,xmlfile,xslfile): res=doProcess(params,xmlfile) if res.startswith('error'): return res try: tree=etree.parse(xmlfile) xsltree=etree.parse(xslfile) transform=etree.XSLT(xsltree) resulttree=transform(tree) return str(resulttree) except: res=sys.exc_info() return 'error '+ str(res[1]) """ extract from database, make an xslt transform to legal JSON and save the string as a compact Javascript string variable var obj='....' """ def saveJSVariable(params,xslfile,targetfile): S=makeJson(params,"data/tmp",xslfile) if S.startswith('error'): S='{"message":"S"}' else: S=S.replace('\r','').replace('\n','') T="var obj='"+S+"'" res=storeTextFile(targetfile,T) return res[0] """ Set up parameters for a use of mysqldump user|password|host|database|table """ def prepareDumpParameters(connect): p=[] parts=connect.split('|') if len(parts) == 5: p.append('mysqldump') p.append('--xml') p.append('--lock-tables=false')#when limited user rights p.append('--user='+parts[0]) p.append('--password='+parts[1]) p.append('--default-character-set=utf8') p.append('--host='+parts[2]) p.append(parts[3]) #database p.append(parts[4]) #table return p """ Set up parameters for a use of mysql user|password|host|database """ def prepareSelectParameters(connect,sql): p=[] parts=connect.split('|') if len(parts) == 4: p.append('mysql') p.append('-X') p.append('--execute='+sql) p.append('--user='+parts[0]) p.append('--password='+parts[1]) p.append('--default-character-set=utf8') p.append('--host='+parts[2]) p.append(parts[3]) #database return p """ Read / write text files """ def getTextFile(filename): try: file=open(filename,'r') res=file.read() file.close() return ('ok',res) except: res=sys.exc_info() return('error',res[1]) def storeTextFile(filename,txt): try: file=open(filename,'w') file.write(txt) file.close() return('ok','') except: res=sys.exc_info() return('error',res[1])
XSLT
Transformasjone som lager Json fra XML er den samme som i modulen uefa1 :
_Fra XML til Json
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="utf-8"/> <!-- Producing strait json either from a mysqldump of one table to xml or from mysql extract to xmlfile with sql Limitation: Replace " with /" in values, as from: http://stackoverflow.com/questions/9370633/xslt-replacing-double-quotes-with-escape-sequence no other cleaning or escaping alternativ stylesheet at: http://code.google.com/p/xml2json-xslt/ --> <xsl:template match="/"> {"list":[<xsl:apply-templates select="//row"/>]} </xsl:template> <xsl:template match="row"> {<xsl:apply-templates select="field"/> } <xsl:if test="position() < last()">,</xsl:if> </xsl:template> <xsl:template match="//row/field"> "<xsl:value-of select="@name"/>":"<xsl:call-template name="escapeQuote"/>"<xsl:if test="position() < last()">,</xsl:if> </xsl:template> <!-- replace quotes--> <xsl:template name="escapeQuote"> <xsl:param name="pText" select="."/> <xsl:if test="string-length($pText) >0"> <xsl:value-of select="substring-before(concat($pText, '"'), '"')"/> <xsl:if test="contains($pText, '"')"> <xsl:text>\"</xsl:text> <xsl:call-template name="escapeQuote"> <xsl:with-param name="pText" select="substring-after($pText, '"')"/> </xsl:call-template> </xsl:if> </xsl:if> </xsl:template> </xsl:stylesheet>
Javascript
Javascriptet er slik:
_index2.js
// images var logoPath="https://borres.hiof.no/resources/fotballogos/"; // the XSL-dom we will use to make json var TransDOM; // fast load of xsldom function getXSLDOM(address){ xhttp=new XMLHttpRequest(); xhttp.open("GET",address,false); xhttp.send(""); // report load elt=document.getElementById("dump"); elt.innerHTML=elt.innerHTML+"\n"+address+" : "+xhttp.statusText; if(xhttp.status!=200) return null; return xhttp.responseXML; } // make json-string from an XMLDom with a transfomation (transDOM) function getJsonStringFrom(XMLDom){ if (window.ActiveXObject){// code for IE T=XML_DOM.transformNode(transDOM); return T; //document.getElementById(eltID).innerHTML=ex; } // Mozilla, Firefox, Opera, etc. else if (document.implementation && document.implementation.createDocument){ xsltProcessor=new XSLTProcessor(); try{ xsltProcessor.importStylesheet(transDOM); resultDocument = xsltProcessor.transformToFragment(XML_DOM,document); ser=new XMLSerializer(); // ok since we have "rooted"-doc T=ser.serializeToString(resultDocument); return T; } catch(e){ document.getElementById("dump").innerHTML=e; return e; } } } // load xml from a database extract (sql) // transform it to json and disoplay the result function goGetIt(serie){ var index=serie.selectedIndex; var value=serie.value;//DE1 var nation=value.substring(0,2); var level=value.substring(2); var liganame= document.querySelector('select option:nth-child('+(index+1)+')').innerHTML; var sql="select name,logo,arenaname from clubs where level='"+ level+"' and nationid='"+nation+"' order by name;"; var T=null; $.ajax({ // the python job url:"pykode/select2XML.py", data:"connect=student|student| itstud.hiof.no|bsdiverse&sql="+sql, async:false, success:function(data, textStatus, jqXHR) { temp=jqXHR.responseText; // while debugging:console.log(temp); if(temp.indexOf('error')!=0){ XML_DOM=jqXHR.responseXML; T=getJsonStringFrom(XML_DOM); obj=JSON.parse(T); liste=obj.list; S=""+ liste.length+' lag\n\n'; S+='<ul>'; for(var ix=0;ix < liste.length;ix++){ S+='<li class="lstNormal" onclick="hilite('+ix+')">'+liste[ix].name+'</li>'; } S+='</ul>'; $('#result').html(S); hilite(0); $('#header').html(liganame); } else $('#result').html(T); }, error:function(data) { $('#dump').html(data); } }); } // hilite a selected team function hilite(ix){ //alert(""+ix); S='<img class="logo" src="'+liste[ix].logo+'" alt="'+liste[ix].logo+'" />'; S+='<div class="name">'+liste[ix].name+'</div>'; S+='<div class="aname">'+liste[ix].arenaname+'</div';; $('#hilited').html(S); var elt=document.getElementsByClassName('lstHilited'); if(elt[0]){ elt[0].className='lstNormal'; } elt=document.querySelector('ul li:nth-child('+(ix+1)+')'); if(elt){ elt.className='lstHilited'; } } // when we start, load xslDOM, get selected serie //and make an initial selection function init(){ transDOM=getXSLDOM('pykode/tojson.xsl'); goGetIt(document.forms["form1"].serie); hilite(0); }