django parse xml with template
I'm looking to create a dynamic way to parse xml files and convert them into a different format as easy as possible..
Here is my fixture.xml
<Orders>
<Order number="" queue="true" getTax="true">
<Customer>
<Email><![CDATA[mike@domain.com]]></Email>
</Customer&开发者_Python百科gt;
</Order>
</Orders>
I'm using the following code
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
class XMLTree(object):
def __init__(self, node):
self.nodes = {}
self.node = node
for n in node:
if len(n.getchildren()):
xmlnode = XMLTree(n)
else:
xmlnode = XMLNode(n)
if n.tag in self.nodes:
if isinstance(self.nodes[n.tag], (XMLTree, XMLNode)):
self.nodes[n.tag] = [self.nodes[n.tag], xmlnode]
else:
self.nodes[n.tag].append(xmlnode)
else:
self.nodes[n.tag] = xmlnode
def __unicode__(self):
return unicode(dict((k, str(v)) for k, v in self.nodes.iteritems()))
def __str__(self):
return unicode(self).encode('utf-8')
def __getattr__(self, attr):
return self.nodes[attr]
def __getitem__(self, key):
return self.node.attrib.get(key)
def __len__(self):
return len(self.nodes)
def items(self):
return self.nodes
class XMLNode(object):
def __init__(self, node):
self.node = node
def __getitem__(self, key):
return self.node.attrib.get(key)
def __unicode__(self):
return self.node.text or ''
def __str__(self):
return unicode(self).encode('utf-8')
def __repr__(self):
return self.__unicode__()
def __len__(self):
return 1
def order_taxcalc(request):
tree = ET.parse("/tmp/fixture.xml")
xml = XMLTree(tree.getroot())
print "Email: ", xml.Order.Customer.Email
omxXML = render_to_string("endpoints/order.html", {'xml': xml})
return HttpResponse(omxXML)
Now I get the correct email in console.. but here is my order.html stripped down
<Email>{{xml.Order.Customer.Email}}</Email>
Nothing is displayed. I hope it makes since with what I am trying to do.
Thanks!
The problem lies in how Django tries to evaluate context variables:
- dictionary lookup,
- attribute lookup,
- list-index lookup,
- function call.
Firstly a dictionary lookup is tried. Your XMLTree
class implements __getitem__
method, so it can be accessed like a dictionary. The problem is that your class raises no KeyError
if non-existing key is requested. Instead it returns None
.
In the template {{ xml.Order(...) }}
is evaluated to xml['Order']
, which executes __getitem__('Order')
which returns None, which is why there is nothing displayed in your template.
So either:
self.node.attrib.get(key)
is not returning what is should (None instead of 'Order')__getitem__
is not raising theKeyError
.
I've added a simple check and it fixes the issue, so template gets rendered with correct value:
def __getitem__(self, key):
out = self.node.attrib.get(key)
if out is not None:
return out
else:
raise KeyError
精彩评论