it-swarm.dev

Převod XML na JSON pomocí Pythonu?

Viděl jsem na webu spravedlivý podíl neochvějného kódu XML-> JSON a poté, co jsem na chvíli pracoval s uživateli Stack, jsem přesvědčen, že tento dav může pomoci více než prvních pár stránek výsledků Google.

Takže analyzujeme krmivo pro počasí a potřebujeme naplnit widgety počasí na mnoha webových stránkách. Hledáme nyní řešení založená na Pythonu.

Tento veřejný weather.com RSS zdroj je dobrým příkladem toho, co bychom měli rozebrat (naše aktuální weather.com krmivo obsahuje další informace kvůli partnerství w/them).

Stručně řečeno, jak bychom měli převést XML na JSON pomocí Pythonu?

137
Pete Karl II

xmltodict (úplné zveřejnění: napsal jsem to) vám může pomoci převést XML na strukturu dict + list + řetězec, podle tohoto "standardu" . Je Expat - založené, takže je to velmi rychlé a nemusí načítat celý strom XML v paměti.

Jakmile tuto datovou strukturu máte, můžete ji serializovat do JSON:

import xmltodict, json

o = xmltodict.parse('<e> <a>text</a> <a>text</a> </e>')
json.dumps(o) # '{"e": {"a": ["text", "text"]}}'
246
Martin Blech

Knihovnu xmljson můžete použít k převodu pomocí různých konvencí XML ​​JSON .

Například tento XML:

<p id="1">text</p>

překládá pomocí BadgerFish konvence do tohoto:

{
  'p': {
    '@id': 1,
    '$': 'text'
  }
}

a prostřednictvím konvence GData do tohoto (atributy nejsou podporovány):

{
  'p': {
    '$t': 'text'
  }
}

... a prostřednictvím konvence Parker do tohoto (atributy nejsou podporovány):

{
  'p': 'text'
}

Je možné konvertovat z XML do JSON az JSON do XML pomocí stejných konvencí :

>>> import json, xmljson
>>> from lxml.etree import fromstring, tostring
>>> xml = fromstring('<p id="1">text</p>')
>>> json.dumps(xmljson.badgerfish.data(xml))
'{"p": {"@id": 1, "$": "text"}}'
>>> xmljson.parker.etree({'ul': {'li': [1, 2]}})
# Creates [<ul><li>1</li><li>2</li></ul>]

Zveřejnění: Tuto knihovnu jsem napsal. Doufám, že to pomůže budoucím hledačům.

16
S Anand

Tady je kód, který jsem pro to postavil. Neexistuje žádný rozbor obsahu, prostá konverze.

from xml.dom import minidom
import simplejson as json
def parse_element(element):
    dict_data = dict()
    if element.nodeType == element.TEXT_NODE:
        dict_data['data'] = element.data
    if element.nodeType not in [element.TEXT_NODE, element.DOCUMENT_NODE, 
                                element.DOCUMENT_TYPE_NODE]:
        for item in element.attributes.items():
            dict_data[item[0]] = item[1]
    if element.nodeType not in [element.TEXT_NODE, element.DOCUMENT_TYPE_NODE]:
        for child in element.childNodes:
            child_name, child_dict = parse_element(child)
            if child_name in dict_data:
                try:
                    dict_data[child_name].append(child_dict)
                except AttributeError:
                    dict_data[child_name] = [dict_data[child_name], child_dict]
            else:
                dict_data[child_name] = child_dict 
    return element.nodeName, dict_data

if __== '__main__':
    dom = minidom.parse('data.xml')
    f = open('data.json', 'w')
    f.write(json.dumps(parse_element(dom), sort_keys=True, indent=4))
    f.close()
7
Paulo Vj

Existuje metoda přenosu značek založených na XML jako JSON, která umožňuje bezeztrátovou konverzi zpět do původní podoby. Viz http://jsonml.org/

Je to jakýsi XSLT JSON. Doufám, že vám to pomůže 

6
themihai

Pokud nějaký čas dostanete pouze kód odpovědi namísto všech dat pak chyba jako json parse bude tam, takže u je třeba převést jako text

import xmltodict

data = requests.get(url)
xpars = xmltodict.parse(data.text)
json = json.dumps(xpars)
print json 
6
Akshay Kumbhar

Možná se budete chtít podívat na http://designtheory.org/library/extrep/designdb-1.0.pdf . Tento projekt začíná převodem XML na JSON rozsáhlé knihovny souborů XML. V konverzi bylo provedeno mnoho výzkumů a bylo vytvořeno nejjednodušší intuitivní mapování XML -> JSON (je popsáno na začátku dokumentu). V souhrnu vše převeďte na objekt JSON a opakované bloky vložte jako seznam objektů.

objekty, které znamenají dvojice klíč/hodnota (slovník v jazyce Python, hashmap v jazyce Java, objekt v jazyce JavaScript)

Neexistuje žádné mapování zpět do XML získat identický dokument, důvodem je, že není známo, zda pár klíč/hodnota byl atribut nebo <key>value</key>, proto tyto informace jsou ztraceny. 

Pokud se mě ptáte, atributy jsou hack na start; pak zase dobře pracovali na HTML.

5
pykler

Pravděpodobně nejjednodušší způsob je pouze analyzovat XML do slovníků a pak to serializovat pomocí simplejsonu. 

4
dguaraglia

Navrhl bych, že nechceme přímou konverzi. Převeďte XML na objekt a poté z objektu na JSON.

Podle mého názoru to dává čistší definici, jak XML a JSON odpovídají.

Chvíli trvá, než se dostanete správně, a můžete dokonce napsat nástroje, které vám pomohou s generováním některých z nich, ale vypadalo by to zhruba takto:

class Channel:
  def __init__(self)
    self.items = []
    self.title = ""

  def from_xml( self, xml_node ):
    self.title = xml_node.xpath("title/text()")[0]
    for x in xml_node.xpath("item"):
      item = Item()
      item.from_xml( x )
      self.items.append( item )

  def to_json( self ):
    retval = {}
    retval['title'] = title
    retval['items'] = []
    for x in items:
      retval.append( x.to_json() )
    return retval

class Item:
  def __init__(self):
    ...

  def from_xml( self, xml_node ):
    ...

  def to_json( self ):
    ...
3
Michael Anderson

Zatímco vestavěné libs pro XML parsování jsou docela dobré, jsem částečný lxml .

Ale pro analýzu RSS kanálů bych doporučil Universal Feed Parser , který může také analyzovat Atom. Jeho hlavní výhodou je, že dokáže strávit i většinu zformovaných kanálů.

Python 2.6 již obsahuje analyzátor JSON, ale novější verze se zlepšenou rychlostí je k dispozici jako simplejson .

S těmito nástroji budování aplikace by nemělo být tak těžké.

2
Luka Marinko

Když dělám něco s XML v pythonu, téměř vždy používám balíček lxml. Mám podezření, že většina lidí používá lxml. Můžete použít xmltodict, ale budete muset zaplatit pokutu za analýzu XML znovu.

Chcete-li převést XML na soubor json pomocí lxml, postupujte takto:

  1. Analyzujte XML dokument pomocí lxml
  2. Převést lxml na dict
  3. Převést seznam na json

Ve svých projektech používám následující třídu. Použijte metodu toJson.

from lxml import etree 
import json


class Element:
    '''
    Wrapper on the etree.Element class.  Extends functionality to output element
    as a dictionary.
    '''

    def __init__(self, element):
        '''
        :param: element a normal etree.Element instance
        '''
        self.element = element

    def toDict(self):
        '''
        Returns the element as a dictionary.  This includes all child elements.
        '''
        rval = {
            self.element.tag: {
                'attributes': dict(self.element.items()),
            },
        }
        for child in self.element:
            rval[self.element.tag].update(Element(child).toDict())
        return rval


class XmlDocument:
    '''
    Wraps lxml to provide:
        - cleaner access to some common lxml.etree functions
        - converter from XML to dict
        - converter from XML to json
    '''
    def __init__(self, xml = '<empty/>', filename=None):
        '''
        There are two ways to initialize the XmlDocument contents:
            - String
            - File

        You don't have to initialize the XmlDocument during instantiation
        though.  You can do it later with the 'set' method.  If you choose to
        initialize later XmlDocument will be initialized with "<empty/>".

        :param: xml Set this argument if you want to parse from a string.
        :param: filename Set this argument if you want to parse from a file.
        '''
        self.set(xml, filename) 

    def set(self, xml=None, filename=None):
        '''
        Use this to set or reset the contents of the XmlDocument.

        :param: xml Set this argument if you want to parse from a string.
        :param: filename Set this argument if you want to parse from a file.
        '''
        if filename is not None:
            self.tree = etree.parse(filename)
            self.root = self.tree.getroot()
        else:
            self.root = etree.fromstring(xml)
            self.tree = etree.ElementTree(self.root)


    def dump(self):
        etree.dump(self.root)

    def getXml(self):
        '''
        return document as a string
        '''
        return etree.tostring(self.root)

    def xpath(self, xpath):
        '''
        Return elements that match the given xpath.

        :param: xpath
        '''
        return self.tree.xpath(xpath);

    def nodes(self):
        '''
        Return all elements
        '''
        return self.root.iter('*')

    def toDict(self):
        '''
        Convert to a python dictionary
        '''
        return Element(self.root).toDict()

    def toJson(self, indent=None):
        '''
        Convert to JSON
        '''
        return json.dumps(self.toDict(), indent=indent)


if __== "__main__":
    xml='''<system>
    <product>
        <demod>
            <frequency value='2.215' units='MHz'>
                <blah value='1'/>
            </frequency>
        </demod>
    </product>
</system>
'''
    doc = XmlDocument(xml)
    print doc.toJson(indent=4)

Výstup z vestavěného hlavního je:

{
    "system": {
        "attributes": {}, 
        "product": {
            "attributes": {}, 
            "demod": {
                "attributes": {}, 
                "frequency": {
                    "attributes": {
                        "units": "MHz", 
                        "value": "2.215"
                    }, 
                    "blah": {
                        "attributes": {
                            "value": "1"
                        }
                    }
                }
            }
        }
    }
}

Která je transformace tohoto XML:

<system>
    <product>
        <demod>
            <frequency value='2.215' units='MHz'>
                <blah value='1'/>
            </frequency>
        </demod>
    </product>
</system>
2
shrewmouse

Tento materiál je zde aktivně udržován a zatím je to můj oblíbený: xml2json in python

1
typelogic

Pro každého, kdo to může ještě potřebovat. Zde je novější, jednoduchý kód pro provedení této konverze.

from xml.etree import ElementTree as ET

xml    = ET.parse('FILE_NAME.xml')
parsed = parseXmlToJson(xml)


def parseXmlToJson(xml):
  response = {}

  for child in list(xml):
    if len(list(child)) > 0:
      response[child.tag] = parseXmlToJson(child)
    else:
      response[child.tag] = child.text or ''

    # one-liner equivalent
    # response[child.tag] = parseXmlToJson(child) if len(list(child)) > 0 else child.text or ''

  return response
1
jnhustin

Můžete použít declxml. Má pokročilé funkce, jako je více atributů a komplexní vnořenou podporu. Stačí k tomu napsat jednoduchý procesor. Také se stejným kódem můžete také převést zpět na JSON. Je to poměrně jednoduché a dokumentace je úžasná.

Odkaz: https://declxml.readthedocs.io/en/latest/index.html

1
srth12

Našel jsem pro jednoduché výstřižky XML, použití regulárního výrazu by ušetřilo potíže. Například:

# <user><name>Happy Man</name>...</user>
import re
names = re.findall(r'<name>(\w+)<\/name>', xml_string)
# do some thing to names

Chcete-li to pomocí XML analýzy, jak řekl @Dan, není jedno-pro-všechny řešení, protože data jsou odlišná. Můj návrh je použít lxml. I když není dokončeno na json, lxml.objectify dávají tiché dobré výsledky:

>>> from lxml import objectify
>>> root = objectify.fromstring("""
... <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...   <a attr1="foo" attr2="bar">1</a>
...   <a>1.2</a>
...   <b>1</b>
...   <b>true</b>
...   <c>what?</c>
...   <d xsi:nil="true"/>
... </root>
... """)

>>> print(str(root))
root = None [ObjectifiedElement]
    a = 1 [IntElement]
      * attr1 = 'foo'
      * attr2 = 'bar'
    a = 1.2 [FloatElement]
    b = 1 [IntElement]
    b = True [BoolElement]
    c = 'what?' [StringElement]
    d = None [NoneElement]
      * xsi:nil = 'true'
1
Andrew_1510

podívejte se na lxml2json (zveřejnění: napsal jsem to) 

https://github.com/rparelius/lxml2json

je to velmi rychlé, lehké (vyžaduje pouze lxml) a jednou výhodou je, že máte kontrolu nad tím, zda jsou určité prvky převedeny na seznamy nebo diktáty

1
Robert Parelius

jsonpickle nebo pokud používáte feedparser, můžete vyzkoušet feed_parser_to_json.py

1
choonkeat

Připravte si data v Python : Pro vytvoření JSON nejprve musíte připravit data v pythonu. K přípravě dat můžeme použít seznam a slovník v Pythonu.

Python List <==> JSON Array

Python Slovník <==> JSON Objekt (Formát klíčové hodnoty) Zaškrtnutím tohoto políčka zobrazíte další podrobnosti

https://devstudioonline.com/article/create-json-and-xml-in-python

0
Anushree Anisha