Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Possible Duplicate:
Converting XML to JSON using Python?

I'm doing some work on App Engine and I need to convert an XML document being retrieved from a remote server into an equivalent JSON object.

I'm using xml.dom.minidom to parse the XML data being returned by urlfetch. I'm also trying to use django.utils.simplejson to convert the parsed XML document into JSON. I'm completely at a loss as to how to hook the two together. Below is the code I'm tinkering with:

from xml.dom import minidom
from django.utils import simplejson as json

#pseudo code that returns actual xml data as a string from remote server. 
result = urlfetch.fetch(url,'','get');

dom = minidom.parseString(result.content)
json = simplejson.load(dom)

self.response.out.write(json)
share|improve this question
Previously: stackoverflow.com/questions/191536/… – RexE Jan 23 '09 at 7:44

marked as duplicate by Piotr Dobrogost, David Basarab, Bo Persson, Abizern, flem Oct 15 '12 at 18:28

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

7 Answers

up vote 9 down vote accepted

Soviut's advice for lxml objectify is good. With a specially subclassed simplejson, you can turn an lxml objectify result into json.

import simplejson as json
import lxml

class objectJSONEncoder(json.JSONEncoder):
"""A specialized JSON encoder that can handle simple lxml objectify types
   >>> from lxml import objectify
   >>> obj = objectify.fromstring("<Book><price>1.50</price><author>W. Shakespeare</author></Book>")       
   >>> objectJSONEncoder().encode(obj)
   '{"price": 1.5, "author": "W. Shakespeare"}'       
"""
 def default(self,o):
    if isinstance(o, lxml.objectify.IntElement):
        return int(o)
    if isinstance(o, lxml.objectify.NumberElement) or isinstance(o, lxml.objectify.FloatElement):
        return float(o)
    if isinstance(o, lxml.objectify.ObjectifiedDataElement):
        return str(o)
    if hasattr(o, '__dict__'):
        #For objects with a __dict__, return the encoding of the __dict__
        return o.__dict__
    return json.JSONEncoder.default(self, o)

See the docstring for usage, essentially you pass the result of lxml objectify to the encode method of an instance of objectJSONEncoder

Note that Koen's point is very valid here, the solution above only works for simply nested xml and doesn't include the name of root elements. This could be fixed.

I've included this class in a gist here: http://gist.github.com/345559

share|improve this answer

I think the XML format can be so diverse that it's impossible to write a code that could do this without a very strict defined XML format. Here is what I mean:

<persons>
	<person>
		<name>Koen Bok</name>
		<age>26</age>
	</person>
	<person>
		<name>Plutor Heidepeen</name>
		<age>33</age>
	</person>
</persons>

Would become

{'persons': [
	{'name': 'Koen Bok', 'age': 26},
	{'name': 'Plutor Heidepeen', 'age': 33}]
}

But what would this be:

<persons>
	<person name="Koen Bok">
		<locations name="defaults">
			<location long=123 lat=384 />
		</locations>
	</person>
</persons>

See what I mean?

Edit: just found this article: http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html

share|improve this answer
1  
the article you found is for javascript – George Jan 19 '10 at 20:33
3  
@George The article is about the general issues of roundtripping XML and JSON. It's very germane to this topic. Don't let the JavaScript code at the end throw you off. – zigg May 2 '12 at 19:29

xmltodict (full disclosure: I wrote it) can help you convert your XML to a dict+list+string structure, following this "standard". It is Expat-based, so it's very fast and doesn't need to load the whole XML tree in memory.

Once you have that data structure, you can serialize it to JSON:

import xmltodict, json

o = xmltodict.parse('<e> <a>text</a> <a>text</a> </e>')
json.dumps(o) # '{"e": {"a": ["text", "text"]}}'
share|improve this answer
Have you written the inverse? I'd be interested in such an animal, I think. – zigg May 2 '12 at 19:26
I haven't, but it doesn't sound too hard to do. I woudn't know what to do with "semi structured" xml, though. Stuff like <a>text <b>c</b> moretext</a> -> {'a': {'#text': 'text moretext', 'b': 'c'}} -> now what? – Martin Blech May 9 '12 at 0:19
1  
If you go strictly by Goessner's article, you actually should have had {'a': 'text <b>c</b> moretext'}, which then roundtrips to <a>text &lt;b&gt;c&lt;/b&gt; moretext</a>... the mismatch between JSON and XML makes situations like this very awkward. I took a stab at the whole thing using ElementTree anyway, though, for API work I'm doing. github.com/zigg/xon – zigg May 9 '12 at 1:03
1  
@MartinBlech xmltodict works perfectly for my ebay rss reader project, thank you! – Haqa Sep 16 '12 at 23:31

Jacob Smullyan wrote a utility called pesterfish which uses effbot's ElementTree to convert XML to JSON.

share|improve this answer

One possibility would be to use Objectify or ElementTree from the lxml module. An older version ElementTree is also available in the python xml.etree module as well. Either of these will get your xml converted to Python objects which you can then use simplejson to serialize the object to JSON.

While this may seem like a painful intermediate step, it starts making more sense when you're dealing with both XML and normal Python objects.

share|improve this answer

I wrote a small command-line based Python script based on pesterfesh that does exactly this:

https://github.com/hay/xml2json

share|improve this answer
This link is broken. It would be nice if it were updated (if the script still exists). – Alison R. Apr 6 '11 at 19:18
Woops, i moved the script into its own repository. Thanks for noticing the 404! – Husky Apr 6 '11 at 22:25
Thanks, this is perfect. One thing to note is that it needs simplejson to be installed: sudo easy_install simplejson – Suman Apr 12 '12 at 21:30
@srs2012 I haven't tried this specific script, but I noticed that pesterfish imports simplejson specifically when it appears it would do just fine with the standard library json. See stackoverflow.com/a/712799/722332 for more on this. – zigg May 2 '12 at 19:24

In general, you want to go from XML to regular objects of your language (since there are usually reasonable tools to do this, and it's the harder conversion). And then from Plain Old Object produce JSON -- there are tools for this, too, and it's a quite simple serialization (since JSON is "Object Notation", natural fit for serializing objects). I assume Python has its set of tools.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.