0

I have model with several fields that look like this:

class XMLData(models.Model):
   name = models.CharField()
   description = models.CharField()
   price = models.CharField()

and xml data that wrapped in string, xml data look like this:

<Root>
   <Header>
      <information>info</information>
   </Header>
   <Main>
      <Product>
         <Name>name1</Name>
         <Description>description1</Description>
         <Price>1</Price>
      </Product>
      <Product>
         <Name>name2</Name>
         <Description>description2</Description>
         <Price>2</Price>
      </Product>
   </Main>
</Root>

My question is: should i replace children nodes Product to the parent node and should i rename tags Name, Description, Price to name, description, price?

I tried to deserialize using this code:

for product in serializers.deserialize("xml", xmldata):
   savedata = XMLData(product)
   savedata.save()

so I hoped that will rise some errors and i would understand what to do next, but there was no errors and xml data didn't save to database.

Hope you understand my problem and thank you for your answer.

Zagorodniy Olexiy
  • 2,132
  • 3
  • 22
  • 47
  • 1
    There is no magic here. Django can't deserialize whatever XML you want. It is able to deserialize only format described in the [documentation](https://docs.djangoproject.com/en/1.9/topics/serialization/#xml). And your XML doesn't fit expected format. You have to look into generic XML parsing tools (like [`lxml`](http://lxml.de/)) and manually create you models from parsed data. – Yaroslav Admin Dec 19 '15 at 15:41
  • Thank you for your answer, please set your comment to answer. To close this question – Zagorodniy Olexiy Dec 19 '15 at 16:03
  • There is a better answer by @abu-ashraf-masnun. Feel free to accept it instead. – Yaroslav Admin Dec 19 '15 at 16:08

1 Answers1

3

It seems you are only interested in storing the product information. In that case Product would be a better model name than XMLData.

Django serializers won't help since your data is not in the correct format. However you can deserialize with lxml. Code taken from: Converting xml to dictionary using ElementTree

from xml.etree import cElementTree as ET
from collections import defaultdict

def etree_to_dict(t):
    d = {t.tag: {} if t.attrib else None}
    children = list(t)
    if children:
        dd = defaultdict(list)
        for dc in map(etree_to_dict, children):
            for k, v in dc.iteritems():
                dd[k].append(v)
        d = {t.tag: {k:v[0] if len(v) == 1 else v for k, v in dd.iteritems()}}
    if t.attrib:
        d[t.tag].update(('@' + k, v) for k, v in t.attrib.iteritems())
    if t.text:
        text = t.text.strip()
        if children or t.attrib:
            if text:
              d[t.tag]['#text'] = text
        else:
            d[t.tag] = text
    return d

e = ET.XML('''
<Root>
   <Header>
      <information>info</information>
   </Header>
   <Main>
      <Product>
         <Name>name1</Name>
         <Description>description1</Description>
         <Price>1</Price>
      </Product>
      <Product>
         <Name>name2</Name>
         <Description>description2</Description>
         <Price>2</Price>
      </Product>
   </Main>
</Root>
''')

from pprint import pprint

d = etree_to_dict(e)

pprint(d)

Now, instead of pretty printing, we can directly store the products:

d = etree_to_dict(e)

products = d['Root']['Main']['Product']

for p in products:
    product = Product()
    p.name = p['Name']
    p.description = p['Description']
    p.price = p['Price']

    p.save()

That should store the products to the database.

Community
  • 1
  • 1
masnun
  • 11,635
  • 4
  • 39
  • 50