Possible Duplicate:
Converting XML to JSON using Python?
Я работаю над App Engine, и мне нужно преобразовать XML-документ, полученный с удаленного сервера, в эквивалентный объект JSON.
Я использую xml.dom.minidom для анализа XML-данных, возвращаемых urlfetch. Я также пытаюсь использовать django.utils.simplejson для преобразования проанализированного XML-документа в JSON. Я совершенно не понимаю, как связать их вместе. Ниже приведен код, над которым я работаю:
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)
взгляните на это: github.com/aausch/filteringxmljsonifier






Джейкоб Смуллян написал утилиту под названием ядовитая рыба, которая использует ЭлементДерево effbot для преобразования XML в JSON.
Установка с помощью pip кажется неработающей: UnicodeDecodeError: 'utf8' codec can't decode byte 0x8b in position 1: invalid start byte
Я думаю, что формат XML может быть настолько разнообразным, что невозможно написать код, который мог бы это сделать, без очень строго определенного формата XML. Вот что я имею в виду:
<persons>
<person>
<name>Koen Bok</name>
<age>26</age>
</person>
<person>
<name>Plutor Heidepeen</name>
<age>33</age>
</person>
</persons>
Станет
{'persons': [
{'name': 'Koen Bok', 'age': 26},
{'name': 'Plutor Heidepeen', 'age': 33}]
}
Но что бы это было:
<persons>
<person name = "Koen Bok">
<locations name = "defaults">
<location long=123 lat=384 />
</locations>
</person>
</persons>
Понимаете, что я имею в виду?
Обновлено: только что нашел эту статью: http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html
найденная вами статья предназначена для javascript
@George Статья посвящена общим вопросам двусторонней передачи XML и JSON. Это очень уместно по этой теме. Не позволяйте коду JavaScript в конце сбить вас с толку.
@ Коэн, будет так. {"people": {"person": {"-name": "Koen Bok", "locations": {"-name": "defaults", "location": {"-long": "123", " -lat ":" 384 "}}}}}
Одна из возможностей - использовать Objectify или ElementTree из lxml модуль. Более старая версия ElementTree также доступна в модуле python xml.etree. Любой из них преобразует ваш xml в объекты Python, которые затем можно использовать simplejson для сериализации объекта в JSON.
Хотя это может показаться болезненным промежуточным этапом, он становится более понятным, когда вы имеете дело с обоими обычными объектами Python XML а также.
В общем, вы хотите перейти от XML к обычным объектам вашего языка (поскольку для этого обычно есть разумные инструменты, а это более сложное преобразование). А затем из Plain Old Object создайте JSON - для этого тоже есть инструменты, и это довольно простая сериализация (поскольку JSON - это «нотация объектов», естественно, подходит для сериализации объектов). Я предполагаю, что у Python есть свой набор инструментов.
Совет Совьюта по объективации lxml хорош. С помощью специального подкласса simplejson вы можете превратить результат lxml objectify в 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)
См. Пример использования в строке документации, по сути, вы передаете результат lxml objectify методу кодирования экземпляра objectJSONEncoder.
Обратите внимание, что здесь очень актуальна точка зрения Коэна, приведенное выше решение работает только для простого вложенного xml и не включает имя корневых элементов. Это можно исправить.
Я включил этот класс в суть здесь: http://gist.github.com/345559
Что делать, если у меня есть тег, у которого есть несколько дочерних элементов с одинаковым именем тега?
@vittore: вы можете заменить return o.__dict__ на return [i.__dict__ for i in o] выше, чтобы обрабатывать несколько дочерних элементов.
@weaver, это почти именно то, что я сделал.
Я написал небольшой скрипт Python на основе командной строки, основанный на pesterfesh, который делает именно это:
https://github.com/hay/xml2json
Эта ссылка не работает. Было бы неплохо, если бы его обновили (если скрипт еще существует).
Woops, я переместил скрипт в его собственный репозиторий. Спасибо, что обратили внимание на 404!
Спасибо, это прекрасно. Следует отметить, что для установки требуется simplejson: sudo easy_install simplejson
@ srs2012 Я не пробовал этот конкретный сценарий, но заметил, что pesterfish импортирует именно simplejson, когда кажется, что он отлично справится со стандартной библиотекой json. Подробнее об этом см. stackoverflow.com/a/712799/722332.
-1 Ваш код не работает. а) Он игнорирует атрибуты тегов: xml2json.xml2json('<a href = "111"> <b href = "222" /> </a>', no_options) отбрасывает атрибуты href и выдает только '{"a": {"b": null}}'
б) Как ни странно, требуется обязательный второй аргумент, который должен быть объектом Python и иметь атрибут pretty, даже если это False: options = type("anonobj", (object,), dict(pretty=False)). Вместо использования options = {} по умолчанию и использования options.getkey('pretty',default=False)
c) И он возвращает строку из json.dumps, а не фактический объект json. Вместо этого нам может понадобиться объект json. Вы можете добавить необязательный аргумент to_string=False.
xmltodict (полное раскрытие: это я написал) может помочь вам преобразовать ваш XML в структуру dict + list + string, следуя этому "стандарт". Он основан на Эмигрант, поэтому работает очень быстро и не требует загрузки всего XML-дерева в память.
Получив эту структуру данных, вы можете сериализовать ее в JSON:
import xmltodict, json
o = xmltodict.parse('<e> <a>text</a> <a>text</a> </e>')
json.dumps(o) # '{"e": {"a": ["text", "text"]}}'
Вы написали обратное? Думаю, мне было бы интересно такое животное.
Нет, но это не так уж сложно сделать. Однако я не знаю, что делать с «полуструктурированным» xml. Такие вещи, как <a>text <b>c</b> moretext</a> -> {'a': {'#text': 'text moretext', 'b': 'c'}} -> что теперь?
Если строго следовать статье Гесснера, на самом деле у вас должен был быть {'a': 'text <b>c</b> moretext'}, который затем возвращается к <a>text <b>c</b> moretext</a> ... несоответствие между JSON и XML делает подобные ситуации очень неудобными. Я все равно попытался использовать ElementTree для работы с API, которую я выполняю. github.com/zigg/xon
@MartinBlech xmltodict отлично работает для моего проекта чтения RSS-каналов ebay, спасибо!
xmltodict, похоже, имеет "неразборчивый" метод, который теперь будет делать обратное
есть проблема с библиотекой libexpat, она не может обрабатывать скобки полной ширины в имени элемента.
Ранее: stackoverflow.com/questions/191536/…