preliminary support for SVG (used with XQuery in supplied example)
This commit is contained in:
parent
164ba65d48
commit
3ee673c273
|
@ -35,6 +35,9 @@ For Tidy <http://tidy.sourceforge.net/> support, add packages:
|
|||
and install Python library uTidyLib <http://utidylib.berlios.de/>:
|
||||
python setup.py install --prefix /usr/local
|
||||
|
||||
For SVG support, you need package svg2png, add this to /etc/apt/sources.list:
|
||||
deb http://cairographics.org/packages/debian/ unstable/
|
||||
|
||||
|
||||
CVS Checkout
|
||||
------------
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration xmlns="http://www.entrouvert.org/namespaces/expression/0.0">
|
||||
<pidFilePath>expression.pid</pidFilePath>
|
||||
<module name="expression.modules.svg"/>
|
||||
<module name="expression.modules.dbxmldatabases">
|
||||
<environment dbHome="db"/>
|
||||
<container name="test.dbxml"/>
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
_names = {}
|
||||
_uris = {}
|
||||
nsList = []
|
||||
nsFromName = {}
|
||||
nsFromUri = {}
|
||||
|
||||
|
||||
class Namespace(object):
|
||||
|
@ -40,6 +42,8 @@ class Namespace(object):
|
|||
_names[uri] = name
|
||||
_uris[name] = uri
|
||||
nsList.append(self)
|
||||
nsFromName[name] = self
|
||||
nsFromUri[uri] = self
|
||||
|
||||
|
||||
def getName(uri):
|
||||
|
@ -60,9 +64,11 @@ html = Namespace("html", "http://www.w3.org/1999/xhtml")
|
|||
mail = Namespace("mail", "http://www.entrouvert.org/namespaces/email/0.0")
|
||||
md = Namespace("md", "urn:liberty:metadata:2003-08")
|
||||
ooo = Namespace("ooo", "http://openoffice.org/2000/office")
|
||||
svg = Namespace("svg", "http://www.w3.org/2000/svg")
|
||||
xforms = Namespace("xforms", "http://www.w3.org/2002/xforms")
|
||||
xhtml2 = Namespace("xhtml2", "http://www.w3.org/2002/06/xhtml2")
|
||||
xsd = Namespace("xsd", "http://www.w3.org/2001/XMLSchema")
|
||||
xslt = Namespace("xslt", "http://www.w3.org/1999/XSL/Transform")
|
||||
xsi = Namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
||||
yep = Namespace("yep", "http://www.entrouvert.org/namespaces/expression/0.0")
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import libxml2
|
|||
import expression.core.elements as elements
|
||||
import expression.core.environs as environs
|
||||
import expression.core.dataholders as dataholders
|
||||
import expression.core.faults as faults
|
||||
import expression.core.html as html
|
||||
import expression.core.logs as logs
|
||||
import expression.core.namespaces as namespaces
|
||||
|
@ -90,41 +91,73 @@ class DbXmlDatabase(dataholders.DataHolder):
|
|||
class XQuery(things.Thing):
|
||||
""" Element xquery contains an XQuery expression to be evaluated.
|
||||
"""
|
||||
_results = None
|
||||
_errorMessage = None
|
||||
|
||||
def __init__(self, *a, **b):
|
||||
super(XQuery, self).__init__(*a, **b)
|
||||
self._results = None
|
||||
self._errorMessage = None
|
||||
|
||||
def getResults(self):
|
||||
""" Evaluates the content of this element as an XQuery expression
|
||||
and returns results.
|
||||
"""
|
||||
if self._results is None:
|
||||
manager = DbXmlDatabase._manager
|
||||
queryContext = manager.createQueryContext()
|
||||
childNodes = self.evaluateXpath("*")
|
||||
query = childNodes[0].serialize()
|
||||
try:
|
||||
self._results = manager.query(query, queryContext)
|
||||
except RuntimeError, e:
|
||||
logs.error("XQuery failed: %s" % e)
|
||||
logs.error("Query was: %s" % query)
|
||||
self._errorMessage = e
|
||||
return self._results
|
||||
|
||||
def generateXml(self, layout):
|
||||
""" Appends "layout" with the result of this query
|
||||
"""
|
||||
manager = DbXmlDatabase._manager
|
||||
queryContext = manager.createQueryContext()
|
||||
try:
|
||||
results = manager.query(self.node.content, queryContext)
|
||||
except RuntimeError, e:
|
||||
logs.error("Error in query: %s" % e)
|
||||
layout.append(html.p(_("Error in query: %s") % e))
|
||||
# output is not an XML document, let's try it as a list of docs.
|
||||
result = self.getResults()
|
||||
if result is None:
|
||||
return False
|
||||
output = "\n".join([value.asString() for value in results])
|
||||
results.reset()
|
||||
try:
|
||||
doc = libxml2.readDoc(output, None, None, 0)
|
||||
div = html.div()
|
||||
for value in results:
|
||||
doc = libxml2.readDoc(value.asString(), None, None, 0)
|
||||
element = self.newElement(doc.getRootElement())
|
||||
element.generateXml(div)
|
||||
layout.append(div)
|
||||
except libxml2.treeError:
|
||||
# output is not an XML document, let's try it as a list of docs.
|
||||
# values are not whole XML docs. Let's put them in <p>.
|
||||
results.reset()
|
||||
div = html.div()
|
||||
for value in results:
|
||||
div.append(html.p(value.asString()))
|
||||
layout.append(div)
|
||||
|
||||
def styled(self):
|
||||
""" Handles HTTP GET.
|
||||
"""
|
||||
command = environs.getVar("httpCommand")
|
||||
if command == "GET":
|
||||
results = self.getResults()
|
||||
if results is None:
|
||||
raise faults.PathNotFound("") # FIXME: display error message
|
||||
output = "\n".join([value.asString() for value in results]).strip()
|
||||
logs.debug("results: %s" % output)
|
||||
try:
|
||||
div = html.div()
|
||||
for value in results:
|
||||
doc = libxml2.readDoc(value.asString(), None, None, 0)
|
||||
element = self.newElement(doc.getRootElement())
|
||||
element.generateXml(div)
|
||||
layout.append(div)
|
||||
print div.serialize()
|
||||
doc = libxml2.readDoc(output, None, None, 0)
|
||||
except libxml2.treeError:
|
||||
# values are not whole XML docs. Let's put them in <p>.
|
||||
results.reset()
|
||||
div = html.div()
|
||||
for value in results:
|
||||
div.append(html.p(value.asString()))
|
||||
layout.append(div)
|
||||
return super(XQuery, self).styled()
|
||||
element = self.newElement(doc.getRootElement())
|
||||
element.doHttpGet()
|
||||
else:
|
||||
layout.append(doc.getRootElement())
|
||||
return True
|
||||
raise faults.PathNotFound("")
|
||||
|
||||
|
||||
elements.registerElement(namespaces.yep.uri, "xquery", XQuery)
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
|
||||
|
||||
# Expression
|
||||
# By: Frederic Peters <fpeters@entrouvert.com>
|
||||
# Emmanuel Raviart <eraviart@entrouvert.com>
|
||||
# Sébastien Ducoulombier <sebastien.ducoulombier@lesdeveloppementsdurables.com>
|
||||
#
|
||||
# Copyright (C) 2004 Entr'ouvert, Frederic Peters & Emmanuel Raviart
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
"""SVG Module"""
|
||||
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import expression.core.elements as elements
|
||||
import expression.core.environs as environs
|
||||
import expression.core.dataholders as dataholders
|
||||
import expression.core.logs as logs
|
||||
import expression.core.namespaces as namespaces
|
||||
import expression.core.things as things
|
||||
|
||||
|
||||
class SVGHolder(dataholders.StaticDataHolder):
|
||||
""" An Xml document file that gets returned as a PNG file. """
|
||||
|
||||
def getDataFile(self):
|
||||
""" Renders the PNG file, and returns its content.
|
||||
"""
|
||||
filename = self.getAbsolutePathName()
|
||||
cachefile = filename + ".cache"
|
||||
#FIXME : test whether the filename is more recent than the cache file. If so, return the cache file, else regenerate it first.
|
||||
os.system("svg2png %s %s" % (filename, cachefile))
|
||||
return open(cachefile)
|
||||
|
||||
|
||||
class SVG(things.Thing):
|
||||
""" Element svg that contains an SVG document to be rendered.
|
||||
"""
|
||||
def doHttpGet(self):
|
||||
""" Renders the PNG file and HTTP-returns its content.
|
||||
"""
|
||||
file = tempfile.NamedTemporaryFile()
|
||||
file.write("""<?xml version="1.0"?>\n%s""" % self.serialize())
|
||||
file.flush()
|
||||
outfile = file.name + ".temp"
|
||||
os.system("svg2png < %s > %s" % (file.name, outfile))
|
||||
environs.getVar("httpRequestHandler").outputData(open(outfile).read(), mimeType = "image/png")
|
||||
os.unlink(outfile)
|
||||
|
||||
|
||||
elements.registerElement(namespaces.svg.uri, "svg", SVG)
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0"?>
|
||||
<yep:xquery xmlns:yep="http://www.entrouvert.org/namespaces/expression/0.0">
|
||||
<svg width="512pt" height="512pt" xmlns="http://www.w3.org/2000/svg">
|
||||
{
|
||||
for $t at $c in collection("test.dbxml")/*/*/text()
|
||||
return <text
|
||||
xml:space="preserve"
|
||||
style="font-size:64;
|
||||
font-style:normal;
|
||||
font-variant:normal;
|
||||
font-weight:bold;
|
||||
font-stretch:normal;
|
||||
fill:#f7b4bb;
|
||||
fill-opacity:1;
|
||||
fill-rule:nonzero;
|
||||
stroke:#000000;
|
||||
stroke-width:0.3;
|
||||
stroke-linecap:round;
|
||||
stroke-linejoin:round;
|
||||
stroke-miterlimit:4;
|
||||
stroke-opacity:1;
|
||||
font-family:Bitstream Vera Sans;
|
||||
text-anchor:left;
|
||||
writing-mode:lr;"
|
||||
x="0"
|
||||
y="{64 * $c}"
|
||||
>{$t}</text>
|
||||
}
|
||||
</svg>
|
||||
</yep:xquery>
|
Reference in New Issue