Jython and PyXML

Sunday, June 15, 2008

This is the tech paper I published in PyCON 2005, since its not available in web, here we go.

Jython and PyXML

S.Prasanna,
sprasanna199@gmail.com

Here I will discuss my experience with PyXML and Jython. I tried to make the best use of Jython with the latest PyXML module. While working with PyXML is a fairly easy task in Python, making things things to work with the latest PyXML in Jython is bit tricky.

Below is a simple code, which gets the servlets and their mappings from the Web.xml file in Tomcat.

For more details on servlets programming in Jython, visit here.

Listing 1: XMLParse.py

1 #XMLParse.py
2 from xml.dom import minidom
3
4
#Open the parser
5 doc = minidom.parse(open("Web.xml" , "r"))
6
7 mapping = doc.getElementsByTagName('servlet-mapping')
8 servlet = doc.getElementsByTagName('servlet')
9
10 #Get the tag
11 dictservlet = {}
12 dictmapping = {}
13
#Get all servlet names and associated class
14 for a in servlet:
15 b = a.getElementsByTagName ('servlet-name')
16 c = a.getElementsByTagName ('servlet-class')
17 for k in b:
18 for h in c:
19 dictservlet [k.firstChild.data] = h.firstChild.data
20
21 #Get all servlet names and associated URL patterns
22 for a in mapping:
23 b = a.getElementsByTagName('servlet-name')
24 c = a.getElementsByTagName ('url-pattern')
25 for k in b:
26 for h in c:
27 dictmapping [h.firstChild.data] = k.firstChild.data
28
29 print "\n\n The dynamic servlet mappings are "
30 print "\n\nServlets are "
31 for i in dictservlet.keys(): print i ," = ", dictservlet[i]
32 print "\n\nServlet mappings are "
33 for i in dictmapping.keys(): print i ," = ", dictmapping[i]

When executing this code in jython (without PyXML), an exception was reported as shown below.

C:\>Jython XMLParse.py

Traceback (innermost last):
File "XMLParse.py", line 4, in ?
File "C:\jython-2.1\Lib\xml\dom\minidom.py", line 908, in parse
File "C:\jython-2.1\Lib\xml\dom\minidom.py", line 900, in _doparse
File "C:\jython-2.1\Lib\xml\dom\pulldom.py", line 251, in getEvent
AttributeError: feed

The exception thrown is due to the module pulldom.py. In this case the pulldom.py module from the latest stable Python version (2.3) is replaced in the Jython library module and then executed. (i.e replace the < PYTHON_HOME>/lib/xml/dom/pulldom.py in <JYTHON_HOME>/lib/xml/dom/pulldom.py) . This solved the problem and the above code worked.

The other thing which I experimented is to make the latest PyXML module to work with Jython in executing the above code. To do this, download the PyXML source and from the PyXML source copy the contents of the xml directory and replace it with that of the Jython 2.1 xml module.

C:\>jython xmlparse.py

Traceback (innermost last):
File "xmlparse.py", line 4, in ?
File "C:\jython-2.1\Lib\xml\dom\minidom.py", line 1907, in parse
ImportError: cannot import name expatbuilder

Since expat parser is not available in jython, the line, which throws the exception in minidom.py, the code in that line in minidom.py should be changed.

def parse(file, parser=None, bufsize=None):
"""Parse a file into a DOM by filename or file object."""
if parser is None and not bufsize:
from xml.dom import expatbuilder
return expatbuilder.parse(file)
else:
from xml.dom import pulldom
return _do_pulldom_parse(pulldom.parse, (file,),
{'parser': parser, 'bufsize': bufsize})

def parseString(string,parser=None):
"""Parse a file into a DOM from a string."""
if parser is None:
from xml.dom import expatbuilder
return expatbuilder.parseString(string)
else:
from xml.dom import pulldom
return _do_pulldom_parse(pulldom.parseString, (string,),
{'parser': parser})

Change it to

def parse(file, parser=None, bufsize=None):
"""Parse a file into a DOM by filename or file object."""
if parser is None and not bufsize:
from xml.dom import pulldom
return _do_pulldom_parse(pulldom.parse, (file,),
{'parser': parser, 'bufsize': bufsize})

def parseString(string, parser=None):
"""Parse a file into a DOM from a string."""
if parser is None:
from xml.dom import pulldom
return _do_pulldom_parse(pulldom.parseString, (string,),
{'parser': parser})

After making this modification, the subsequent exception thrown was

C:\>jython xmlparse.py

Traceback (innermost last):
File "xmlparse.py", line 4, in ?
File "C:\jython-2.1\Lib\xml\dom\minidom.py", line 1908, in parse
File "C:\jython-2.1\Lib\xml\dom\minidom.py", line 1898, in _do_pulldom_parse
File "C:\jython-2.1\Lib\xml\dom\pulldom.py", line 338, in parse
File "C:\jython-2.1\Lib\xml\sax\sax2exts.py", line 37, in make_parser
File "C:\jython-2.1\Lib\xml\sax\saxexts.py", line 69, in make_parser
File "C:\jython-2.1\Lib\xml\sax\saxexts.py", line 37, in _create_parser
File "C:\jython-2.1\Lib\xml\sax\drivers2\drv_xmlproc.py", line 9, in ?
ImportError: cannot import name xmlproc

After a careful analysis of the PyXML module and the python module it uses, it was found that the cause of the exception was due to the absence of some python (2.3) modules in jython.

Now I used the python 2.3 modules

Urlib2.py
Dis.py
Inspect.py
Opcode.py

In the Jython library and finally the code executed in Jython!

Note: While replacing the inspect.py module from Python 2.3 to Jython, make sure that you replace the // operator in inspect.py module since jython 2.1 does not support // operator. Instead modify that operator in inspect.py as follows.

start = lineno - 1 - context//2

to

start = line - 1 - int(math.floor(context/2))

In short, many python libraries can be made to work with Jython with little tweaking, to take the full advantage of Java Implementation of python.

4 comments:

Alan said...

Thanks for sharing that with us; we need more XML and jython examples on the net.

One small thing though; please can you try to figure out how to make your blog software show the whitespace in your jython code properly? The way that your code is shown makes it very hard to read and hard to use (e.g. with copy and paste).

srid said...

Why don't you syntax highlight your code? BTW, that banner ad on top-left of the post is very obtrusive. Ah, I forgot to install Adblock...

Prasanna Seshadri said...

Hi Alan,

Thanks for your suggestions, since this is the first time I am posting some code in blogger, I will make it copy paste friendly in near future for sure, also I am planning to find ways to attach the source code in a link so that you can download it easily, will do it soon.

Prasanna Seshadri said...

Hi Sridhar,

This is just an experimental version of the blog layout, I will syntax highlight code for sure, also the layout of my blog is not complete yet, will design it again to ensure good user experience.


Copyright © 2008 Prasanna Seshadri, www.prasannatech.net, All Rights Reserved.
No part of the content or this site may be reproduced without prior written permission of the author.