[lxml-dev] Call for Contribution: lxml 0.9

Hello, everyone! Martijn and I realised that there has not been a release of lxml for quite a while - despite a lot of important changes to the code base. We therefore agreed to prepare the release of lxml 0.9 for *Monday, March 20*. The remaining time will be used to get the trunk ready for a release. It will include the current feature set of the trunk plus the support for extension functions that is currently implemented in the scoder2 branch. The latter still needs a bit of discussion and merging. Any comments on this are appreciated. For you, this announcement means the following. - If you want any features included, make sure you send requests and patches to the list within the next days or try to fix a date when a patch will be available. Remember that we may have to discuss patches before applying them. - If you feel that you especially like or dislike anything about the new features and the way they are made available through APIs, feel free to tell us over the list. - If you feel that anything from past discussions has been left out that should be worth remembering for a new release, speak up now. - We know that there are still a few places where documentation would help users to understand new features. A good way to contribute would therefore be to look through the documentation in the "doc" directory and see if it is understandable or if there is anything you might want to add. - In the same line, usage examples in the form of doctests would be nice to have for more API functions. They also belong into the files in the "doc" directory, which are (or must be) called from the related test cases in src/lxml/tests. Happy coding, Stefan

The main feature I'd like to see would be an easy installer that include lxml's dependencies, maybe using easy_install. It's a complex project and the installation is easy to get wrong. Thanks for the work on this. Looking forward to 0.9. --Dethe "the city carries such a cargo of pathos and longing that daily life there vaccinates us against revelation" -- Pain Not Bread, The Rise and Fall of Human Breath

Dethe Elza wrote:
Hmm, I'm not quite sure what could be done better here. What you'd have to do for 0.9 is: * install libxml2 and libxslt (which lxml can't do for you) * tar zxf lxml-0.9.tar.gz * cd lxml-0.9 * run "python setup.py install" (or bdist_egg or whatever you run normally) That doesn't sound very error prone to me... But then, that's mainly how it works on Linux. You seem to be on Apple, so I imagine what you're looking for is a readily installable darwin port? Maybe even without compilation? I guess then we'd have to find someone who uses MacOS-X and can provide a port... Stefan

Why not? Other python extensions install their dependencies.
OS X is my main platform, but I actually encountered trouble installing on Windows, where the steps were: 1. Read install instructions for lxml 2. Follow these to libxml site 3. Find download link on crowded page 4. Find download link to Windows binaries 5. Read install instructions and figure out *which* libraries are needed out of: libxml2, libxslt, openssl, iconv, zlib, xmlsec, and xsldbg) and in what order. Appear to need four libraries: openssl, iconv, libxml2, and libxslt in that order. 6. Download and unzip each set of binaries. 7. Get the exes in my %PATH% 8. Collect the headers in ~/include/ and the DLLs in ~/lib/ and point the config file at them 9. run python setup.py install 10. have it fail 11. Run out of time to futz with it and give up
I guess then we'd have to find someone who uses MacOS-X and can provide a port...
On OS X it isn't nearly such a problem, more of an inconvenience. If necessary I can make an egg at some point for OS X.
Stefan
--Dethe Choosing software is not a neutral act. It must be done consciously; the debate over free and proprietary software can’t be limited to the differences in the applications’ features and ergonomics. To choose an operating system, or software, or network architecture is to choose a kind of society. --Lemaire and Decroocq (trans. by Tim Bray)

Dethe Elza wrote:
It's not a problem as long as it's only about Python dependencies. EasyInstall can do that. It's not a problem if it's only self-contained C extensions for Python. EasyInstall can do that, too. However, libxml2 and libxslt are written in plain C, with their own further dependencies and their installation very much depends on the operating system, its version, the processor architecture, the availability of a C compiler, ... It would be hard work for us to handle all of that in Python. And it's not up to the developers of /lxml/ to provide better ways of installing its dependencies under the various types of systems. If installing libxml2 is a problem, it's a problem with libxml2, not lxml.
I understand that this is a problem and that it keeps people from using libxml2/libxslt under certain proprietary systems. But you could argue that this is due to the lack of package management in these systems. I actually think I remember having seen that Cygwin comes with a resonable installer that allows you to install various libraries by simply selecting them. If I'm not mistaken, libxml2/xslt should have been amongst them. http://cygwin.com/
9. run python setup.py install 10. have it fail
Well, most 'bug' reports about 'having it fail' that we get on the list are actually because of Pyrex rather than lxml. That will change. However, we can't really help you with the way you set up your system before trying to compile lxml. There just isn't much we can do about that. We could only bundle the libraries in a Windows installer. But then, what good is it to have libraries if you include them statically? That would mean having to respond to every security announcement to provide a new installer ourselves - also for every version of Python and so on... That's really a problem with the way installations on Microsoft systems work, not with lxml. Having to provide all dependencies yourself in the single installer binary of your software and overwriting the libraries that were provided by other installers simply isn't the right way to do it.
That would be helpful. MacOS *has* package management. Also, MacOS-X libraries tend to be a lot more - hum - static? outdated? - so that installers make more sense there. Stefan

Dethe Elza wrote:
Stephan already answered this, but I'll jump in -- I actually looked for a bit at setuptools last year in the hope it could tackle this problem, but there wasn't much that could help there... So, yeah, we're aware that this can be a problem, but it's not easy to fix unfortunately. Contributions in that department are of course very welcome. Regards, Martijn

Hi Stefan. Thanks for the work on this and sending the heads-up note. Before writing and checking in a test, I want to find out if something is known behavior. I have an XSLT that uses XML data in the stylesheet itself. Essentially: ---- xslt preamble stuff ---- <localstuff> <localitem>klkdk</localitem> </localstuff> .....later.... <xsl:apply-templates select="document('')/localstuff"/> It works with xsltproc but doesn't work with lxml. I wonder if there's something about the resolver that is the issue. Should I file a case for this, or is this known behavior? Also, I'd file a case about not wiring in libxml2's HTMLParser, but I suppose that's not a bug, it's just a missing feature. :^) I *really* need that wired in at some point, but for now, I can just ship some other tool that converts HTML -> well-formed XML. --Paul Stefan Behnel wrote:

Paul Everitt wrote:
Hmmm, I can reproduce that. This results in an empty root tag 'test': --------------- from lxml import etree xslt = etree.XSLT(etree.XML('''\ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <test> <xsl:copy-of select="document('')"/> </test> </xsl:template> </xsl:stylesheet> ''')) print xslt(etree.XML('<a/>')), --------------- Looks like libxslt doesn't know how to access document('') without an XSLT specific entity loader. You can run xsltproc with the '--load-trace' option to see that the entity solver handles that access, too. According to strace, it even reads in the file twice, so we'd either have to provide the XSLT processor with access to the original XSL file (which is impossible if it is generated in memory) or write a replacement to the entity resolver that handles that special case. I personally consider that a bug in libxslt, though. document('') should be a special case /in the library/.
Would be nice to have - but it's a little too close to 0.9 to implement the interface code, which also has to be ElementTree compatible to a certain extent. Stefan

Stefan Behnel wrote:
Ok, point made. :^) I'm currently working around this by putting the nodes I want into the input document. However, that makes me pay a penalty on every request, instead of just once when the stylesheet is generated. I can live with it, though. It's already lots faster than other templating approaches. :^) --Paul

On 2 Mar 2006 at 16:37, Paul Everitt wrote:
<xsl:apply-templates select="document('')/localstuff"/>
Sorry to barge in here.. I've been watching lxml for a while, waiting for it to support a custom resolver so I can use it in Paste and Zope, etc. Currently I'm using libxslt with Paste in my "tal2xslt" project. I rely on document('') as a way to inject "system-wide" constants into the .xsl files that are generated from the input TAL. I register a global resolver with libxslt and tag the URI associated with a given document so it can be tied back to the originating request. I use libxml2.readDoc() to associate a custom URI with each document. Each URI I load uses a custom scheme so I know it's "mine". Anyway, in the resolver if the scheme doesn't match my fake scheme, I just hand it back to libxslt and let it resolve itself. Can you do the same in lxml? I poked around http://codespeak.net/svn/lxml/trunk/src/lxml/ but couldn't find the module where you set the resolver.
Yeah, I love it. Edge side includes done via xml/xsl in the client. It's great. -- Brad Clements, bkc@murkworks.com (315)268-1000 http://www.murkworks.com AOL-IM or SKYPE: BKClements

Brad Clements wrote:
You're very welcome.
That's because we don't. :) We currently do not care about resolving at all. Everything that works does so because libxml2/xslt handles it itself. Everything that doesn't work - uhm, well, doesn't work. I would absolutely like to see a resolver API in lxml. So, if you're interested in getting it there, you could provide some example code showing how you set it up. Then we could see what would be a good way of extending the current API to support resolvers - especially custom ones. We would especially need to see at what granularity you can set them: at a function-local level, at an object level or at a global level? Stefan

On 2 Mar 2006 at 22:16, Stefan Behnel wrote:
Great, at least I know I'm not blind now.
In that case, I wonder about the original poster's claim that document('') doesn't work. I use xsltproc and xml starlet all the time, I don't think xsltproc sets a resolver at all, but I haven't looked at the source to be certain. Anyway, document('') works in both xsltproc and xml starlet.
The last I knew, libxslt only allowed setting the resolver on a per-process level. Also, I am using the Python level interface, not the C level interface. I'll paste below the current hacky code I use. One note, I'm not using the most recent libxslt. In the version of libxslt I'm using now, if a resolver raises an exception, libxslt treats that to mean "continue with default resolution". apparently the semantics have changed in more recent libxslt versions.. Since I don't want default resolution to occur when an exception happens, I return an empty string in that case. I want to point out that this code isn't really correct in that respect. This code is still in development. _resolver_context = {} _scheme = "memory" _resolver_lock = RLock() def _Resolver(URL,ID,ctxt): try: context, new_uri = extract_uri_and_context(URL) if not context: prefix = URL.split(':')[0] if prefix == _scheme: print "no context for %r" % URL return None resolver = get_resolver(context) if not resolver: print "Could not find resolver for context %r, url %r" % (context, URL) return '' return StringIO.StringIO(resolver(new_uri)) except: print "unexpected exception in resolver" traceback.print_exc() return '' def add_context_to_uri(uri, context): """Mangle the uri, adding a fake scheme and context""" return urlparse.urlunsplit((_scheme, context, uri, '', '')) def extract_uri_and_context(uri): """Un-mangle uri, returns (context, uri) or (None, None) if not our scheme""" parts = urlparse.urlsplit(unquote(uri)) context, new_uri = (None, uri) if parts[0] == _scheme: if parts[1]: context = parts[1] new_uri = parts[2] elif parts[2][:2] == '//': # buggy urlsplit sticks netloc in path context, new_uri = parts[2][2:].split('/',1) new_uri = "/" + new_uri return (context, new_uri) def register_resolver(context, resolver): """add this context to list of resolvers""" _resolver_lock.acquire() try: obj = get_resolver(context) if not obj: _resolver_context[context] = (resolver, 1) else: old_resolver, use_count = obj _resolver_context[context] = (resolver, use_count+1) finally: _resolver_lock.release() def unregister_resolver(context): """remove this context from the list of resolvers""" _resolver_lock.acquire() try: obj = get_resolver(context) if not obj: raise ValueError("resolver context %r not currently registered" % context) old_resolver, use_count = obj use_count -= 1 if use_count > 0: _resolver_context[context] = (old_resolver, use_count) else: del _resolver_context[context] finally: _resolver_lock.release() def get_resolver(context): """Return a resolver for the specified context""" _resolver_lock.acquire() try: obj = _resolver_context.get(context) if not obj: return obj resolver, use_count = obj return resolver finally: _resolver_lock.release() libxml2.setEntityLoader(_Resolver) # this is a process-wide change, -- Brad Clements, bkc@murkworks.com (315)268-1000 http://www.murkworks.com AOL-IM or SKYPE: BKClements

Brad Clements wrote:
xsltproc does set an own resolver, I checked the source. But the main handling is still done by the libxslt default resolver. I also looked through the libxslt resolver and AFAICT it does not special case document(''). That case is handled by the normal file lookup based on the document base URL (which essentially results in using the base URL unchanged). Hence the double read of the XSL file. There were some places where the code seemed to check a list of in-memory documents, so maybe that would be the place to hook in: provide a parsed representation of the document referenced by its original name or something. But, as usual, the documentation is not very telling.
Ok, but that doesn't necessarily keep us from setting it when entering a function and resetting it at the end. Applying an XSLT is basically one function call, so that is a nicely enclosed code block without unpredictable concurrency problems.
Also, I am using the Python level interface, not the C level interface.
Both are mostly identical in terms of function calls, so that still helps. Actually, it's even better since lxml is written in Pyrex, so Python code can be copied more or less as is.
Thanks for posting it. I'll look through it as soon as I find the time. It's always better to have working code to read and discuss than fancy ideas and no one to implement them. Stefan

Paul Everitt wrote:
Ok, I played with it a bit and found that we can work around this in the case where the XSLT is read in from a file (which should be the majority of cases, I'd say). All we have to do is use the file parser functions from libxml2 in that case, which store the file URL in the document structure. This breaks the case where the document is modified in between (since the changes are not reflected by the file when it is re-read by libxslt), but that is a) a rare case and b) a bug in libxslt, which should recognise the case where the stylesheet itself is referenced. So, I committed the change to the trunk (revision 23950). Please try it to see if it fixes the cases you needed. Stefan

The main feature I'd like to see would be an easy installer that include lxml's dependencies, maybe using easy_install. It's a complex project and the installation is easy to get wrong. Thanks for the work on this. Looking forward to 0.9. --Dethe "the city carries such a cargo of pathos and longing that daily life there vaccinates us against revelation" -- Pain Not Bread, The Rise and Fall of Human Breath

Dethe Elza wrote:
Hmm, I'm not quite sure what could be done better here. What you'd have to do for 0.9 is: * install libxml2 and libxslt (which lxml can't do for you) * tar zxf lxml-0.9.tar.gz * cd lxml-0.9 * run "python setup.py install" (or bdist_egg or whatever you run normally) That doesn't sound very error prone to me... But then, that's mainly how it works on Linux. You seem to be on Apple, so I imagine what you're looking for is a readily installable darwin port? Maybe even without compilation? I guess then we'd have to find someone who uses MacOS-X and can provide a port... Stefan

Why not? Other python extensions install their dependencies.
OS X is my main platform, but I actually encountered trouble installing on Windows, where the steps were: 1. Read install instructions for lxml 2. Follow these to libxml site 3. Find download link on crowded page 4. Find download link to Windows binaries 5. Read install instructions and figure out *which* libraries are needed out of: libxml2, libxslt, openssl, iconv, zlib, xmlsec, and xsldbg) and in what order. Appear to need four libraries: openssl, iconv, libxml2, and libxslt in that order. 6. Download and unzip each set of binaries. 7. Get the exes in my %PATH% 8. Collect the headers in ~/include/ and the DLLs in ~/lib/ and point the config file at them 9. run python setup.py install 10. have it fail 11. Run out of time to futz with it and give up
I guess then we'd have to find someone who uses MacOS-X and can provide a port...
On OS X it isn't nearly such a problem, more of an inconvenience. If necessary I can make an egg at some point for OS X.
Stefan
--Dethe Choosing software is not a neutral act. It must be done consciously; the debate over free and proprietary software can’t be limited to the differences in the applications’ features and ergonomics. To choose an operating system, or software, or network architecture is to choose a kind of society. --Lemaire and Decroocq (trans. by Tim Bray)

Dethe Elza wrote:
It's not a problem as long as it's only about Python dependencies. EasyInstall can do that. It's not a problem if it's only self-contained C extensions for Python. EasyInstall can do that, too. However, libxml2 and libxslt are written in plain C, with their own further dependencies and their installation very much depends on the operating system, its version, the processor architecture, the availability of a C compiler, ... It would be hard work for us to handle all of that in Python. And it's not up to the developers of /lxml/ to provide better ways of installing its dependencies under the various types of systems. If installing libxml2 is a problem, it's a problem with libxml2, not lxml.
I understand that this is a problem and that it keeps people from using libxml2/libxslt under certain proprietary systems. But you could argue that this is due to the lack of package management in these systems. I actually think I remember having seen that Cygwin comes with a resonable installer that allows you to install various libraries by simply selecting them. If I'm not mistaken, libxml2/xslt should have been amongst them. http://cygwin.com/
9. run python setup.py install 10. have it fail
Well, most 'bug' reports about 'having it fail' that we get on the list are actually because of Pyrex rather than lxml. That will change. However, we can't really help you with the way you set up your system before trying to compile lxml. There just isn't much we can do about that. We could only bundle the libraries in a Windows installer. But then, what good is it to have libraries if you include them statically? That would mean having to respond to every security announcement to provide a new installer ourselves - also for every version of Python and so on... That's really a problem with the way installations on Microsoft systems work, not with lxml. Having to provide all dependencies yourself in the single installer binary of your software and overwriting the libraries that were provided by other installers simply isn't the right way to do it.
That would be helpful. MacOS *has* package management. Also, MacOS-X libraries tend to be a lot more - hum - static? outdated? - so that installers make more sense there. Stefan

Dethe Elza wrote:
Stephan already answered this, but I'll jump in -- I actually looked for a bit at setuptools last year in the hope it could tackle this problem, but there wasn't much that could help there... So, yeah, we're aware that this can be a problem, but it's not easy to fix unfortunately. Contributions in that department are of course very welcome. Regards, Martijn

Hi Stefan. Thanks for the work on this and sending the heads-up note. Before writing and checking in a test, I want to find out if something is known behavior. I have an XSLT that uses XML data in the stylesheet itself. Essentially: ---- xslt preamble stuff ---- <localstuff> <localitem>klkdk</localitem> </localstuff> .....later.... <xsl:apply-templates select="document('')/localstuff"/> It works with xsltproc but doesn't work with lxml. I wonder if there's something about the resolver that is the issue. Should I file a case for this, or is this known behavior? Also, I'd file a case about not wiring in libxml2's HTMLParser, but I suppose that's not a bug, it's just a missing feature. :^) I *really* need that wired in at some point, but for now, I can just ship some other tool that converts HTML -> well-formed XML. --Paul Stefan Behnel wrote:

Paul Everitt wrote:
Hmmm, I can reproduce that. This results in an empty root tag 'test': --------------- from lxml import etree xslt = etree.XSLT(etree.XML('''\ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <test> <xsl:copy-of select="document('')"/> </test> </xsl:template> </xsl:stylesheet> ''')) print xslt(etree.XML('<a/>')), --------------- Looks like libxslt doesn't know how to access document('') without an XSLT specific entity loader. You can run xsltproc with the '--load-trace' option to see that the entity solver handles that access, too. According to strace, it even reads in the file twice, so we'd either have to provide the XSLT processor with access to the original XSL file (which is impossible if it is generated in memory) or write a replacement to the entity resolver that handles that special case. I personally consider that a bug in libxslt, though. document('') should be a special case /in the library/.
Would be nice to have - but it's a little too close to 0.9 to implement the interface code, which also has to be ElementTree compatible to a certain extent. Stefan

Stefan Behnel wrote:
Ok, point made. :^) I'm currently working around this by putting the nodes I want into the input document. However, that makes me pay a penalty on every request, instead of just once when the stylesheet is generated. I can live with it, though. It's already lots faster than other templating approaches. :^) --Paul

On 2 Mar 2006 at 16:37, Paul Everitt wrote:
<xsl:apply-templates select="document('')/localstuff"/>
Sorry to barge in here.. I've been watching lxml for a while, waiting for it to support a custom resolver so I can use it in Paste and Zope, etc. Currently I'm using libxslt with Paste in my "tal2xslt" project. I rely on document('') as a way to inject "system-wide" constants into the .xsl files that are generated from the input TAL. I register a global resolver with libxslt and tag the URI associated with a given document so it can be tied back to the originating request. I use libxml2.readDoc() to associate a custom URI with each document. Each URI I load uses a custom scheme so I know it's "mine". Anyway, in the resolver if the scheme doesn't match my fake scheme, I just hand it back to libxslt and let it resolve itself. Can you do the same in lxml? I poked around http://codespeak.net/svn/lxml/trunk/src/lxml/ but couldn't find the module where you set the resolver.
Yeah, I love it. Edge side includes done via xml/xsl in the client. It's great. -- Brad Clements, bkc@murkworks.com (315)268-1000 http://www.murkworks.com AOL-IM or SKYPE: BKClements

Brad Clements wrote:
You're very welcome.
That's because we don't. :) We currently do not care about resolving at all. Everything that works does so because libxml2/xslt handles it itself. Everything that doesn't work - uhm, well, doesn't work. I would absolutely like to see a resolver API in lxml. So, if you're interested in getting it there, you could provide some example code showing how you set it up. Then we could see what would be a good way of extending the current API to support resolvers - especially custom ones. We would especially need to see at what granularity you can set them: at a function-local level, at an object level or at a global level? Stefan

On 2 Mar 2006 at 22:16, Stefan Behnel wrote:
Great, at least I know I'm not blind now.
In that case, I wonder about the original poster's claim that document('') doesn't work. I use xsltproc and xml starlet all the time, I don't think xsltproc sets a resolver at all, but I haven't looked at the source to be certain. Anyway, document('') works in both xsltproc and xml starlet.
The last I knew, libxslt only allowed setting the resolver on a per-process level. Also, I am using the Python level interface, not the C level interface. I'll paste below the current hacky code I use. One note, I'm not using the most recent libxslt. In the version of libxslt I'm using now, if a resolver raises an exception, libxslt treats that to mean "continue with default resolution". apparently the semantics have changed in more recent libxslt versions.. Since I don't want default resolution to occur when an exception happens, I return an empty string in that case. I want to point out that this code isn't really correct in that respect. This code is still in development. _resolver_context = {} _scheme = "memory" _resolver_lock = RLock() def _Resolver(URL,ID,ctxt): try: context, new_uri = extract_uri_and_context(URL) if not context: prefix = URL.split(':')[0] if prefix == _scheme: print "no context for %r" % URL return None resolver = get_resolver(context) if not resolver: print "Could not find resolver for context %r, url %r" % (context, URL) return '' return StringIO.StringIO(resolver(new_uri)) except: print "unexpected exception in resolver" traceback.print_exc() return '' def add_context_to_uri(uri, context): """Mangle the uri, adding a fake scheme and context""" return urlparse.urlunsplit((_scheme, context, uri, '', '')) def extract_uri_and_context(uri): """Un-mangle uri, returns (context, uri) or (None, None) if not our scheme""" parts = urlparse.urlsplit(unquote(uri)) context, new_uri = (None, uri) if parts[0] == _scheme: if parts[1]: context = parts[1] new_uri = parts[2] elif parts[2][:2] == '//': # buggy urlsplit sticks netloc in path context, new_uri = parts[2][2:].split('/',1) new_uri = "/" + new_uri return (context, new_uri) def register_resolver(context, resolver): """add this context to list of resolvers""" _resolver_lock.acquire() try: obj = get_resolver(context) if not obj: _resolver_context[context] = (resolver, 1) else: old_resolver, use_count = obj _resolver_context[context] = (resolver, use_count+1) finally: _resolver_lock.release() def unregister_resolver(context): """remove this context from the list of resolvers""" _resolver_lock.acquire() try: obj = get_resolver(context) if not obj: raise ValueError("resolver context %r not currently registered" % context) old_resolver, use_count = obj use_count -= 1 if use_count > 0: _resolver_context[context] = (old_resolver, use_count) else: del _resolver_context[context] finally: _resolver_lock.release() def get_resolver(context): """Return a resolver for the specified context""" _resolver_lock.acquire() try: obj = _resolver_context.get(context) if not obj: return obj resolver, use_count = obj return resolver finally: _resolver_lock.release() libxml2.setEntityLoader(_Resolver) # this is a process-wide change, -- Brad Clements, bkc@murkworks.com (315)268-1000 http://www.murkworks.com AOL-IM or SKYPE: BKClements

Brad Clements wrote:
xsltproc does set an own resolver, I checked the source. But the main handling is still done by the libxslt default resolver. I also looked through the libxslt resolver and AFAICT it does not special case document(''). That case is handled by the normal file lookup based on the document base URL (which essentially results in using the base URL unchanged). Hence the double read of the XSL file. There were some places where the code seemed to check a list of in-memory documents, so maybe that would be the place to hook in: provide a parsed representation of the document referenced by its original name or something. But, as usual, the documentation is not very telling.
Ok, but that doesn't necessarily keep us from setting it when entering a function and resetting it at the end. Applying an XSLT is basically one function call, so that is a nicely enclosed code block without unpredictable concurrency problems.
Also, I am using the Python level interface, not the C level interface.
Both are mostly identical in terms of function calls, so that still helps. Actually, it's even better since lxml is written in Pyrex, so Python code can be copied more or less as is.
Thanks for posting it. I'll look through it as soon as I find the time. It's always better to have working code to read and discuss than fancy ideas and no one to implement them. Stefan

Paul Everitt wrote:
Ok, I played with it a bit and found that we can work around this in the case where the XSLT is read in from a file (which should be the majority of cases, I'd say). All we have to do is use the file parser functions from libxml2 in that case, which store the file URL in the document structure. This breaks the case where the document is modified in between (since the changes are not reflected by the file when it is re-read by libxslt), but that is a) a rare case and b) a bug in libxslt, which should recognise the case where the stylesheet itself is referenced. So, I committed the change to the trunk (revision 23950). Please try it to see if it fixes the cases you needed. Stefan
participants (5)
-
Brad Clements
-
Dethe Elza
-
Martijn Faassen
-
Paul Everitt
-
Stefan Behnel