Форматирование данных из массива Python - PullRequest
0 голосов
/ 17 февраля 2010

Я изучаю питон впервые.У меня есть цель, которая состоит в том, чтобы взять данные из API и вывести их в формате xml.

Вывод сохраняется в массиве ("projectData"), вот пример вывода:

[{'code': 'demo',
 'created_at': datetime.datetime(2008, 6, 11, 7, 35, 19, tzinfo=<api.LocalTimezone object at 0x10072ab10>),
 'created_by': None,
 'id': 4,
 'image': 'https://website.com/files/0000/0000/blah.jpg',
 'name': 'Demo Project',
 'description': 'This is for demonstration purposes',
 'due': '2009-05-30',
 'start': '2009-05-06',
 'status': 'Active',
 'stype': 'Demo',
 'tag_list': [],
 'type': 'Project',
 'updated_at': datetime.datetime(2009, 5, 27, 1, 41, 55, tzinfo=<api.LocalTimezone object at 0x10072ab10>),
 'updated_by': {'id': 24, 'name': 'Test', 'type': 'HumanUser'},
 'users': [{'id': 19, 'name': 'User 1', 'type': 'HumanUser'},
           {'id': 18, 'name': 'User 2', 'type': 'HumanUser'},
           {'id': 17, 'name': 'User 3', 'type': 'HumanUser'},
           {'id': 16, 'name': 'User 4', 'type': 'HumanUser'},
           {'id': 15, 'name': 'User 5', 'type': 'HumanUser'},
           {'id': 14, 'name': 'User 6', 'type': 'HumanUser'},
           {'id': 13, 'name': 'User 7', 'type': 'HumanUser'},
           {'id': 12, 'name': 'User 8', 'type': 'HumanUser'},
           {'id': 20, 'name': 'Client 1', 'type': 'HumanUser'}]},

(и т. Д.)

Я написал некоторый код, который будет выводить его в формате xml следующим образом:

for _project in projectData:
  print "<Project>"
  for key in _project:
    value = _project[key]
    print "\t<" + str(key) + ">" + str(value) + "</" + str(key) + ">"
  print("</Project>\n")

, который фактически дает мне результат, который работает для меня.

Однако, поскольку я новичок в этом, я подозреваю, что это не очень эффективный подход и может быть подвержен всевозможным ошибкам, я надеялся, что кто-то более знающий может иметь некоторые указатели для меня,Следующее, что я хочу попробовать, это сделать его рекурсивным, чтобы, например, элемент updated_by возвращал свой собственный xml

Спасибо.

Ответы [ 3 ]

2 голосов
/ 17 февраля 2010

Вот пример использования lxml.etree, неполный .. и, вероятно, немного наивный. На самом деле вы должны определить схему и убедиться, что ваш вывод соответствует ей.

Редактировать, сказал, что он был неполным, добавил тип None и предположил, что созданный_был похож на updated_by при заполнении

import datetime

projects = [{'code': 'demo',
 'created_at': datetime.datetime(2008, 6, 11, 7, 35, 19),
 'created_by': None,
 'id': 4,
 'image': 'https://website.com/files/0000/0000/blah.jpg',
 'name': 'Demo Project',
 'description': 'This is for demonstration purposes',
 'due': '2009-05-30',
 'start': '2009-05-06',
 'status': 'Active',
 'stype': 'Demo',
 'tag_list': [],
 'type': 'Project',
 'updated_at': datetime.datetime(2009, 5, 27, 1, 41, 55),
 'updated_by': {'id': 24, 'name': 'Test', 'type': 'HumanUser'},
 'users': [{'id': 19, 'name': 'User 1', 'type': 'HumanUser'},
           {'id': 18, 'name': 'User 2', 'type': 'HumanUser'},
           {'id': 17, 'name': 'User 3', 'type': 'HumanUser'},
           {'id': 16, 'name': 'User 4', 'type': 'HumanUser'},
           {'id': 15, 'name': 'User 5', 'type': 'HumanUser'},
           {'id': 14, 'name': 'User 6', 'type': 'HumanUser'},
           {'id': 13, 'name': 'User 7', 'type': 'HumanUser'},
           {'id': 12, 'name': 'User 8', 'type': 'HumanUser'},
           {'id': 20, 'name': 'Client 1', 'type': 'HumanUser'}]},
 ]

from lxml import etree

def E(tag, parent=None, content=None, children=None, **kw):
  e = etree.Element(tag)
  if not content is None:
    e.text = str(content)
  for k,v in kw.items():
    e.set(k, str(v))
  if not parent is None:
    parent.append(e)
  if not children is None:
    for c in children:
      e.append(c)
  return e

def processProject(data):
  attrs = ('name','type','id')
  p = E('Project')
  for item in attrs:
    p.set(item,str(data[item]))
  for k,v in [ x for x in data.items() if x[0] not in attrs ]:
    if v is None:
      E(k,parent=p)
    elif isinstance(v,basestring):
      E(k,content=v,parent=p)
    elif isinstance(v,(float,long,int)):
      E(k,content=str(v),parent=p)
    elif isinstance(v,datetime.datetime):
      E(k,content=v.strftime('%Y-%m-%d %H%M'),parent=p)
    elif k == 'users':
      users = E(k,parent=p)
      for u in v:
        E('user',parent=users,**dict([ (x,str(y)) for (x,y) in u.items()]))
    elif k in ('updated_by','created_by'):
      E(k,parent=p,**dict([ (x,str(y)) for (x,y) in v.items()]))
    elif k == 'tag_list':
      taglist = E(k,parent=p)
      for t in v:
        E('tag',parent=taglist,content=t)
  return p

>>> projxml = processProject(projects[0])
>>> etree.dump(projxml)
<Project name="Demo Project" type="Project" id="4">
  <status>Active</status>
  <code>demo</code>
  <created_at>2008-06-11 0735</created_at>
  <due>2009-05-30</due>
  <created_by/>
  <updated_at>2009-05-27 0141</updated_at>
  <start>2009-05-06</start>
  <image>https://website.com/files/0000/0000/blah.jpg</image>
  <updated_by type="HumanUser" id="24" name="Test"/>
  <users>
    <user type="HumanUser" id="19" name="User 1"/>
    <user type="HumanUser" id="18" name="User 2"/>
    <user type="HumanUser" id="17" name="User 3"/>
    <user type="HumanUser" id="16" name="User 4"/>
    <user type="HumanUser" id="15" name="User 5"/>
    <user type="HumanUser" id="14" name="User 6"/>
    <user type="HumanUser" id="13" name="User 7"/>
    <user type="HumanUser" id="12" name="User 8"/>
    <user type="HumanUser" id="20" name="Client 1"/>
  </users>
  <tag_list/>
  <stype>Demo</stype>
  <description>This is for demonstration purposes</description>
</Project>
2 голосов
/ 17 февраля 2010

Попробуйте использовать что-то вроде genshi или etree вместо создания XML вручную.

0 голосов
/ 17 февраля 2010

Подумайте об использовании какого-либо инструмента шаблона (даже string.Template) вместо большого количества манипуляций со строками.

Например, универсальный словарь для тега довольно прост с глупым небольшим встроенным шаблоном.class.

import string
tag= string.Template( "<$tag>$value</$tag>" )
for k,v in someProjectDictionary:
    print tag.substitute( key=k, value=v )

Однако переход к Jinja или Mako делает это намного проще, поскольку весь ваш XML-документ становится простой итерацией на языке шаблонов.

{% for p in project_data %}
<project>
    {% for k in p %}
    <{{k}}>{{p[k]}}</{{k}}>
    {% endfor %}
</project>
{% endfor %}        

Вы можете создать для этого отдельный файл и использовать Jinja для обработки подстановки в ваш XML-шаблон из ваших данных.

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
template = env.get_template('mytemplate.html')
print template.render(project_data=the_project_data_list)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...