Et bibliotek
Løsningene er basert på et lite Pythonbibliotek:
#! /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])
Det er viktig å merke seg at dette biblioteket ikke er hardt testet. Det finnes mange valgmuligheter
både når det gjelder mulig mysql-parametere og når det gjelder varianter av Pythons subprocesser. Det burde
imidlertid være et brukbart utgangspunkt for eksperimentering.
Merk også funksjonen saveJSVariable som lager en Javascript-string av Json-formatet. Denne kan brukes til å
preparere en fil som kan importeres som src i en script-tag på websiden. Denne er ikke benyttet i eksemplene
nedenfor.
Eksemplene nedenfor bruker alle dette biblioteket.
dump to XML
Hvis vi ønsker å dumpe en tabell i en database til XML kan vi gjøre dette
med følgende Python kode, et server script:
#! /usr/bin/python
import cgi,sys
import dbutils
#import cgitb; cgitb.enable()
"""
Dump to xml
using mysqldump in a subprocess as implemented in utils
"""
form=cgi.FieldStorage()
"""
Need connect. | separated string
Sequence is important:
user|password|host|database|table
"""
try:
# always connect
connect=form['connect'].value
# set up parameters
p=dbutils.prepareDumpParameters(connect)
if len(p) >0:
res=dbutils.doProcess(p,'data/dump.xml')
if res.startswith('ok'):
# return the produced file
print "Location: data/dump.xml\n"
else:
print 'Content-type: text/plain; charset=utf-8 \n'
print res
else:
print 'Content-type: text/plain; charset=utf-8 \n'
print 'error bad parameter list in connect'
except:
print 'Content-type: text/plain; charset=utf-8 \n'
res=sys.exc_info()
print 'error '+str(res[1])
I en Ajax-request vil parameterlista være f.eks. slik:
"connect=student|student|frigg.hiof.no|vin|wines"
dump to Json
Hvis vi ønsker å dumpe en tabell i en database til Json kan vi gjøre dette
med følgende Python kode, et server script:
#! /usr/bin/python
import cgi,sys
from lxml import etree
import dbutils
#import cgitb; cgitb.enable()
"""
Dump to json
using mysqldump in a subprocess as implemented in dbutils
"""
#transformation xml -> json
XSLT_FILE='tojson.xsl'
form=cgi.FieldStorage()
"""
Need connect. | separated string
Sequence is important:
user|password|host|database|table
"""
print 'Content-type: text/plain; charset=utf-8 \n'
try:
# always connect
connect=form['connect'].value
# set up parameters
p=dbutils.prepareDumpParameters(connect)
parts=connect.split('|')
if len(p) > 0:
print dbutils.makeJson(p,'data/dump.xml',XSLT_FILE)
else:
print 'error bad parameter list in connect'
except:
res=sys.exc_info()
print 'error '+str(res[1])
I en Ajax-request vil parameterlista være f.eks. slik:
"connect=student|student|frigg.hiof.no|vin|wines"
XSLT-transformasjonen som genererer Json fra XML er slik:
<?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>
<!-- as from
http://stackoverflow.com/questions/9370633/xslt-replacing-double-quotes-with-escape-sequence
-->
<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>
SQL to XML
Hvis vi ønsker å lage XML av en databsseforesørsel kan vi gjøre dette
med følgende Python kode, et server script:
#! /usr/bin/python
import cgi,sys
import dbutils
#import cgitb; cgitb.enable()
"""
Select to XML
using mysql in a subprocess as implemented in dbutils
"""
form=cgi.FieldStorage()
"""
Need connect. | separated string
Sequence is important
user|password|host|database
and sql
"""
try:
# always connect
connect=form['connect'].value
sql=form['sql'].value
# set up parameters
p=dbutils.prepareSelectParameters(connect,sql)
if len(p) > 0:
res=dbutils.doProcess(p,'data/sqlselect.xml')
if res.startswith('ok'):
# return the produced file
print "Location: data/sqlselect.xml\n"
else:
print 'Content-type: text/plain; charset=utf-8 \n'
print res
else:
print 'Content-type: text/plain; charset=utf-8 \n'
print 'error bad parameter list in connect'
except:
print 'Content-type: text/plain; charset=utf-8 \n'
res=sys.exc_info()
print 'error '+str(res[1])
I en Ajax-request vil parameterlista være f.eks. slik:
"connect=student|student|frigg.hiof.no|vin&sql=select * from wines where dice >5 "
SQL to Json
Hvis vi ønsker å lage Json av en databsseforesørsel kan vi gjøre dette
med følgende Python kode, et server script:
#! /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])
I en Ajax-request vil parameterlista være f.eks. slik:
"connect=student|student|frigg.hiof.no|vin&sql=select * from wines where country = 'Chile'"
XSLT-transformasjonen som genererer Json fra XML er den samme som den som brukes
i eksempelet over: dump to Json
Hvorfor det ?
Det flere grunner til at dette kan være en nyttig innfallsvinkel til database access.
Den viktigste er kanskje at vi er uavhegngig av
Python-bibliotek for MysQL. Videre vil en nærmere analyse av mulige parametere vise at vi kan lage mange varianter av
de parameterlistene som er brukt i eksemplene over, og få alternative formater.
Når vi,slik som over, har fått data over på klienten, kan vi velge mange metoder for å
bearbeide dem. Vi kan selvsagt handtere Json-formatet slik vi vil, og vi kan bearbeide XML-treet, enten slik det er eller
vi kan utføre transformasjoner på klienten slik som vist i modulen
XSLT på klienten
.