List Info

Thread: adding transformContexts to Python




adding transformContexts to Python
user name
2006-08-31 14:50:10
Right now there are some things that you can't do in the
Python layer
because it's not possible to pre-create a TransformContext
and apply a
transformation with one.

So I thought I'd do this and I just want some sanity
checking on the
plan:

- add a function:

    libxslt.newTransformContext(doc, stylesheet)

- add a method to the stylesheet class:

    applyStylesheetUser(self, doc, params, transformContext)


So the method of doing this sort of thing will be:

  stylesheet =
libxslt.parseStylesheetFile("somefilename.xslt")
  src_doc =
libxml2.parseFile("someotherfilename.xml")
  tc = libxslt.newTransformContext(src_doc, stylesheet)
  result = stylesheet.applyStylesheetUser(src_doc, {}, tc)

During the transformation the transform context will be
available to
extension functions and the resolver and so on.


Out of interest, I have 2 reasons for doing this:

1. doing memory recovery of resources created by extension
functions

   Extension functions could register resources to be
collected in a
   map, keyed by the transform context. When the application
is
   finished a clean up routine can be run, collecting
everything in
   the map for the transformContext just finished.


2. doing per-transfrom entity resolution

   When the resolver is called it can get the xpathContext
of the
   call. Which means that it could make a decision on where
to look
   for entitys based on something in the xpathContext.

   This facilitates things like multiple heirarchies of
resolution
   sources.


-- 
Nic Ferrier
http://www.tapsellfer
rier.co.uk   for all your tapsell ferrier needs
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
adding transformContexts to Python
user name
2006-08-31 15:46:42
On Thu, Aug 31, 2006 at 03:50:10PM +0100, Nic James Ferrier
wrote:
> Right now there are some things that you can't do in
the Python layer
> because it's not possible to pre-create a
TransformContext and apply a
> transformation with one.
> 
> So I thought I'd do this and I just want some sanity
checking on the
> plan:
> 
> - add a function:
> 
>     libxslt.newTransformContext(doc, stylesheet)
> 
> - add a method to the stylesheet class:
> 
>     applyStylesheetUser(self, doc, params,
transformContext)
> 
> 
> So the method of doing this sort of thing will be:
> 
>   stylesheet =
libxslt.parseStylesheetFile("somefilename.xslt")
>   src_doc =
libxml2.parseFile("someotherfilename.xml")
>   tc = libxslt.newTransformContext(src_doc, stylesheet)
>   result = stylesheet.applyStylesheetUser(src_doc, {},
tc)
> 
> During the transformation the transform context will be
available to
> extension functions and the resolver and so on.

  Okay,

> 
> Out of interest, I have 2 reasons for doing this:
> 
> 1. doing memory recovery of resources created by
extension functions
> 
>    Extension functions could register resources to be
collected in a
>    map, keyed by the transform context. When the
application is
>    finished a clean up routine can be run, collecting
everything in
>    the map for the transformContext just finished.
> 
> 
> 2. doing per-transfrom entity resolution
> 
>    When the resolver is called it can get the
xpathContext of the
>    call. Which means that it could make a decision on
where to look
>    for entitys based on something in the xpathContext.
> 
>    This facilitates things like multiple heirarchies of
resolution
>    sources.

  I agree not everything is available at the python level,
usually what
got in was driven by user interest, first myself and then
other people.
Patches to fill the gap gratefully accepted (but will be
reviewed of
course 

  thanks !

Daniel

-- 
Red Hat Virtualization group http://redhat.com/v
irtualization/
Daniel Veillard      | virtualization library  http://libvirt.org/
veillardredhat.com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ |
Rpmfind RPM search engine  http://rpmfind.net/
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
adding transformContexts to Python
user name
2006-09-01 02:23:54
Daniel Veillard <veillardredhat.com> writes:

>   I agree not everything is available at the python
level, usually what
> got in was driven by user interest, first myself and
then other people.
> Patches to fill the gap gratefully accepted (but will
be reviewed of
> course 

I've attached a simple diff of the changed bits to
facilitate
transform content accessing.

This works for me... though I've yet to write a
comprehensive test.


Can someone shout if they think I'm on the wrong track
here.

-- 
Nic Ferrier
http://www.tapsellfer
rier.co.uk   for all your tapsell ferrier needs

diff -u libxslt-1.1.17/python/libxslt-python-api.xml
../libxslt-1.1.16/python/libxslt-python-api.xml
--- libxslt-1.1.17/python/libxslt-python-api.xml	2006-09-01
03:14:20.000000000 +0100
+++
../libxslt-1.1.16/python/libxslt-python-api.xml	2006-09-01
02:25:49.000000000 +0100
 -11,6
+11,12 
       <arg name='style' type='xsltStylesheetPtr'
info='a parsed XSLT stylesheet'/>
       <arg name='result' type='xmlDocPtr' info='The
result document'/>
     </function>
+    <function name='xsltNewTransformContext'
file='python'>
+      <info>Create a new XSLT
TransformContext</info>
+      <return type='xsltTransformContextPtr' info='an
xslt TransformContext'/>
+      <arg name='style' type='xsltStylesheetPtr'
info='a parsed XSLT stylesheet'/>
+      <arg name='doc' type='xmlDocPtr' info='the
input document'/>
+    </function>
     <function name='xsltApplyStylesheet'
file='python'>
       <info>Apply the stylesheet to the
document</info>
       <return type='xmlDocPtr' info="the result
document or NULL in case of error"/>
 -18,6
+24,14 
       <arg name='doc' type='xmlDocPtr' info='a
parsed XML document'/>
       <arg name='params' type='pythonObject'
info='the parameters dictionnary'/>
     </function>
+    <function name='xsltApplyStylesheetUser'
file='python'>
+      <info>Apply the stylesheet to the
document</info>
+      <return type='xmlDocPtr' info="the result
document or NULL in case of error"/>
+      <arg name='style' type='xsltStylesheetPtr'
info='a parsed XSLT stylesheet'/>
+      <arg name='doc' type='xmlDocPtr' info='a
parsed XML document'/>
+      <arg name='params' type='pythonObject'
info='the parameters dictionnary'/>
+      <arg name='transformCtxt'
type='xsltTransformContextPtr' info='transformation
context'/>
+    </function>
     <function name='xsltRegisterErrorHandler'
file='python'>
       <info>Register a Python written function to for
error reporting. The function is called back as f(ctx,
error).</info>
       <return type='int' info="1 in case of
success, 0 or -1 in case of error"/>
diff -u libxslt-1.1.17/python/libxslt.c
../libxslt-1.1.16/python/libxslt.c
--- libxslt-1.1.17/python/libxslt.c	2004-07-02
14:49:07.000000000 +0100
+++ ../libxslt-1.1.16/python/libxslt.c	2006-09-01
03:09:16.000000000 +0100
 -502,6
+502,106 
     return(py_retval);
 }
 
+
+PyObject *
+libxslt_xsltNewTransformContext(PyObject *self
ATTRIBUTE_UNUSED, PyObject *args) {
+    PyObject *py_retval;
+    PyObject *pyobj_style;
+    PyObject *pyobj_doc;
+    xsltStylesheetPtr style;
+    xmlDocPtr doc;
+    xsltTransformContextPtr c_retval;
+
+    if (!PyArg_ParseTuple(args, (char *) "OOsltNe
wTransformContext",
+		          &pyobj_style, &pyobj_doc))
+        return(NULL);
+
+    style = (xsltStylesheetPtr)
Pystylesheet_Get(pyobj_style);
+    doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
+    
+    c_retval = xsltNewTransformContext(style, doc);
+    py_retval =
libxslt_xsltTransformContextPtrWrap((xsltTransformContextPtr
) c_retval);
+    return (py_retval);
+}
+
+
+PyObject *
+libxslt_xsltApplyStylesheetUser(PyObject *self
ATTRIBUTE_UNUSED, PyObject *args) {
+    PyObject *py_retval;
+    xmlDocPtr c_retval;
+    xsltStylesheetPtr style;
+    PyObject *pyobj_style;
+    xmlDocPtr doc;
+    xsltTransformContextPtr transformCtxt;
+    PyObject *pyobj_doc;
+    PyObject *pyobj_params;
+    PyObject *pyobj_transformCtxt;
+    const char **params = NULL;
+    int len = 0, i = 0, j;
+    PyObject *name;
+    PyObject *value;
+
+    if (!PyArg_ParseTuple(args, (char *) "OOOOsltAp
plyStylesheetUser",
+		          &pyobj_style, &pyobj_doc,
&pyobj_params, &pyobj_transformCtxt))
+        return(NULL);
+
+    if (pyobj_params != Py_None) {
+	if (PyDict_Check(pyobj_params)) {
+	    len = PyDict_Size(pyobj_params);
+	    if (len > 0) {
+		params = (const char **) xmlMalloc((len + 1) * 2 *
+			                           sizeof(char *));
+		if (params == NULL) {
+		    printf("libxslt_xsltApplyStylesheet: out of
memory\n");
+		    Py_INCREF(Py_None);
+		    return(Py_None);
+		}
+		j = 0;
+		while (PyDict_Next(pyobj_params, &i, &name,
&value)) {
+		    const char *tmp;
+		    int size;
+
+		    tmp = PyString_AS_STRING(name);
+		    size = PyString_GET_SIZE(name);
+		    params[j * 2] = (char *) xmlCharStrndup(tmp, size);
+		    if (PyString_Check(value)) {
+			tmp = PyString_AS_STRING(value);
+			size = PyString_GET_SIZE(value);
+			params[(j * 2) + 1] = (char *)
+			    xmlCharStrndup(tmp, size);
+		    } else {
+			params[(j * 2) + 1] = NULL;
+		    }
+		    j = j + 1;
+		}
+		params[j * 2] = NULL;
+		params[(j * 2) + 1] = NULL;
+	    }
+	} else {
+	    printf("libxslt_xsltApplyStylesheet: parameters
not a dict\n");
+	    Py_INCREF(Py_None);
+	    return(Py_None);
+	}
+    }
+    style = (xsltStylesheetPtr)
Pystylesheet_Get(pyobj_style);
+    doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
+    transformCtxt = (xsltTransformContextPtr)
PytransformCtxt_Get(pyobj_transformCtxt);
+
+    c_retval = xsltApplyStylesheetUser(style, doc, params,
NULL, NULL, transformCtxt);
+    py_retval = libxml_xmlDocPtrWrap((xmlDocPtr) c_retval);
+    if (params != NULL) {
+	if (len > 0) {
+	    for (i = 0;i < 2 * len;i++) {
+		if (params[i] != NULL)
+		    xmlFree((char *)params[i]);
+	    }
+	    xmlFree(params);
+	}
+    }
+    return(py_retval);
+}
+
+
 PyObject *
 libxslt_xsltSaveResultToString(PyObject *self
ATTRIBUTE_UNUSED, PyObject *args) {
     PyObject *py_retval;        /* our final return value,
a python string   */ 
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
adding transformContexts to Python
user name
2006-09-01 10:01:10
On Fri, Sep 01, 2006 at 03:23:54AM +0100, Nic James Ferrier
wrote:
> Daniel Veillard <veillardredhat.com> writes:
> 
> >   I agree not everything is available at the
python level, usually what
> > got in was driven by user interest, first myself
and then other people.
> > Patches to fill the gap gratefully accepted (but
will be reviewed of
> > course 
> 
> I've attached a simple diff of the changed bits to
facilitate
> transform content accessing.
> 
> This works for me... though I've yet to write a
comprehensive test.
> 
> 
> Can someone shout if they think I'm on the wrong track
here.

  Doesn't look crazy to me  Tell me if
you want this to be applied
  as is or if you prefer doing a bit more testing,

Daniel

-- 
Red Hat Virtualization group http://redhat.com/v
irtualization/
Daniel Veillard      | virtualization library  http://libvirt.org/
veillardredhat.com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ |
Rpmfind RPM search engine  http://rpmfind.net/
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
adding transformContexts to Python
user name
2006-09-01 10:34:06
Daniel Veillard <veillardredhat.com> writes:

>   Doesn't look crazy to me  Tell me if
you want this to be applied
>   as is or if you prefer doing a bit more testing,

I wrote a test for the resolver access:

  import libxslt
  import libxml2
  import sys
  import StringIO
  import pdb

  def xslt_resolver(url, id, ctxt):
      pctxt = libxslt.xpathParserContext(_obj=ctxt)
      xpc = pctxt.context()
      doc = xpc.contextDoc()

      if url == "someimport.xslt":
          f =
StringIO.StringIO("""<?xml
version="1.0" encoding="utf-8"?>
  <xsl:stylesheet  version="1.0"
                   xmlnssl=&
quot;http://www.w3.or
g/1999/XSL/Transform">
      <xsl:template match="/xxx">
          <sexy/>
      </xsl:template>
  </xsl:stylesheet>
  """)
          return f
      return None

  def test():
      libxml2.setEntityLoader(xslt_resolver)
      src_doc = libxml2.parseDoc("<a/>")
      style_doc =
libxml2.parseDoc("""<?xml
version="1.0" encoding="utf-8"?>
      <xsl:stylesheet  version="1.0"
                       xmlnssl=&
quot;http://www.w3.or
g/1999/XSL/Transform">
          <xsl:import
href="someimport.xslt"/>
          <xsl:template match="/">
              <goodbye/>
          </xsl:template>
      </xsl:stylesheet>
      """)

      style = libxslt.parseStylesheetDoc(style_doc)
      if style:
          transform_ctxt =
style.newTransformContext(src_doc)
          result = style.applyStylesheetUser(src_doc, {},
transform_ctxt)
          result.dump(sys.stdout)

  pdb.runcall(test)


When I run this on UNPATCHED libxslt (deb 1.1.17-2) it
segfaults at
line 9.

It appears that this function:

  libxsltmod.xsltXPathGetContextDoc

is the immediate cause of the fault... but I'm guessing the
problem is
with the python code putting the values into the C.


I get the same problem with my patched code... can you shed
any light
on this?

-- 
Nic Ferrier
http://www.tapsellfer
rier.co.uk   for all your tapsell ferrier needs
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
varying entity resolution (was Re: adding transformContexts to Python)
user name
2006-09-01 14:58:18
Replying to myself:

> I wrote a test for the resolver access:

<snip/>

>   def xslt_resolver(url, id, ctxt):
>       pctxt = libxslt.xpathParserContext(_obj=ctxt)
>       xpc = pctxt.context()
>
>       if url == "someimport.xslt":
>           f =
StringIO.StringIO("""<?xml
version="1.0" encoding="utf-8"?>
>   <xsl:stylesheet  version="1.0"
>                    xmlnssl=&
quot;http://www.w3.or
g/1999/XSL/Transform">
>       <xsl:template match="/xxx">
>           <sexy/>
>       </xsl:template>
>   </xsl:stylesheet>
>   """)
>           return f
>       return None

This breaks.


I really wanted to be able to access the
xsltTransformContext from
here.

But it appears that I've been wrong about this... the ctxt
delivered
to the resolver is an xmlParserCtxt, not an
xpathParserContext. Moreover the xmlParserCtxt doesn't seem
to have
anyway of getting to an xpathParserContext or an
xsltTransformContext.


The reason I wanted to be able to reach the tranform context
was so
that I could uniquely identify a transformation.

I've got a webapp where users can have personalized copies
of common
xslts. In the resolver I want to be able to say:

- what request is this resolution associated with?

- what is the user's id (from the http request)

- what is the correct directory to search for xslt imports
and other
  entities?


If I can't do this by getting the transformContext can
anyone suggest
how I might do it?

-- 
Nic Ferrier
http://www.tapsellfer
rier.co.uk   for all your tapsell ferrier needs
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
adding transformContexts to Python
user name
2006-09-04 19:29:02
Daniel Veillard <veillardredhat.com> writes:

>   Doesn't look crazy to me  Tell me if
you want this to be applied
>   as is or if you prefer doing a bit more testing,

Don't add it - it doesn't work.


I did some test code and it seems that, even though the
patch
correctly calls xsltApplyStylesheetUser with the correct
transformContext, an extension function examining the
transformContext
via it's xpathContext actually sees a different object.

Not sure why that is yet - clearly something is fubar.


I'm stuck doing the other patch (the one for document
handling) which
is really important to me but once I've done it I'll come
back to this
one which is somewhat important to me.


Harrumph.

-- 
Nic Ferrier
http://www.tapsellfer
rier.co.uk   for all your tapsell ferrier needs
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
[1-7]

about | contact  Other archives ( Real Estate discussion Medical topics )