Database
MySql
mysqldump
Python
JSON
XSLT
Børre Stenseth
Olympiade >DB2JSON

Behandling av XML-dump fra database

Hva

Her skal vi lese en XML-dump fra en databse og vise hvordan vi kan transformere den til et annet format. Vi skal bruke JSON som endelig format.

I stedet for å bruke Pythons MySQL bibliotek til å hente data, skal vi bruke en annen innfallsvinkel. Vi skal bruke mysql som en kommando, og vi skal bruke kommandoen mysqldump [1] . Vi skal se hvordan vi kan bruke denne kommandoen til å levere XML, og, ved hjelp av en transformasjon, også JSON.

Et bibliotek

Løsningene er basert på et lite Pythonbibliotek:

_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])+ ': '+targetfile
 
"""
 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

olxmldump
Database og XMLdump med eller uten SQL

Hvis vi ønsker å dumpe en tabell i en database til XML kan vi gjøre dette med følgende Python kode, et server script:

_dump2XML.py

I en Ajax-request vil parameterlista være f.eks. slik:

connect=student|student| itstud.hiof.no|bsdiverse|olresults
dumpxml.html https://borres.hiof.no/wep/xslt/ol/db2xml/dumpxml.html

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:

_select2XML.py

I en Ajax-request vil parameterlista være f.eks. slik:

connect=student|student| itstud.hiof.no|bsdiverse&sql=select * from olresults where place='Barcelona'
selectxml.html https://borres.hiof.no/wep/xslt/ol/db2xml/selectxml.html

Dump to Json

oljsondump
Database og JSON med eller uten SQL

Hvis vi ønsker å dumpe en tabell i en database til Json kan vi gjøre dette med følgende Python kode, et server script:

_dump2Json.py

I en Ajax-request vil parameterlista være f.eks. slik:

connect=student|student| itstud.hiof.no|bsdiverse|olresults

XSLT-transformasjonen som genererer JSON fra XML er slik:

_tojson.xsl
<?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() &lt; last()">,</xsl:if>
</xsl:template>
<xsl:template match="//row/field">
"<xsl:value-of select="@name"/>":"<xsl:call-template name="escapeQuote"/>"<xsl:if test="position() &lt; last()">,</xsl:if>
</xsl:template>
<xsl:template name="escapeQuote">
  <xsl:param name="pText" select="."/>
  <xsl:if test="string-length($pText) >0">
   <xsl:value-of select="substring-before(concat($pText, '&quot;'), '&quot;')"/>
   <xsl:if test="contains($pText, '&quot;')">
    <xsl:text>\"</xsl:text>
    <xsl:call-template name="escapeQuote">
      <xsl:with-param name="pText" select="substring-after($pText, '&quot;')"/>
    </xsl:call-template>
   </xsl:if>
  </xsl:if>
</xsl:template>
</xsl:stylesheet>
dumpjson.html https://borres.hiof.no/wep/xslt/ol/db2xml/dumpjson.html

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:

_select2Json.py

I en Ajax-request vil parameterlista være f.eks. slik:

connect=student|student| itstud.hiof.no|bsdiverse&sql=select * from olresults where place='Barcelona'

XSLT-transformasjonen som genererer Json fra XML er den samme som den som brukes i eksempelet over: dump to Json

selectjson.html https://borres.hiof.no/wep/xslt/ol/db2xml/selectjson.html

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 På klienten .

Referanser
  1. mysqldump mysql.com dev.mysql.com/doc/refman/5.1/en/mysqldump.html 14-02-2014
Olympiade >DB2JSON