سؤال

لقد شاهدت حصة عادلة من صعب المراس XML->سلمان مدونة على شبكة الإنترنت ، وبعد أن تفاعلت مع كومة المستخدمين قليلا, أنا مقتنع أن هذا الحشد يمكن أن تساعد أكثر من الصفحات القليلة الأولى من جوجل النتائج.

لذلك نحن في تحليل الطقس تغذية ، ونحن بحاجة إلى ملء الطقس الحاجيات على العديد من المواقع على شبكة الإنترنت.نحن نبحث الآن في بيثون القائم على الحلول.

هذا العام weather.com تغذية RSS هو مثال جيد على ما سيكون إعراب (لدينا الفعلية weather.com تغذية يحتوي على معلومات إضافية بسبب شراكة w/لهم).

باختصار كيف يمكننا تحويل XML إلى JSON باستخدام الثعبان ؟

هل كانت مفيدة؟

المحلول

وليس هناك "واحد مقابل واحد" تعيين بين XML و JSON، لذلك تحويل واحدة إلى أخرى بالضرورة يتطلب بعض فهم ما تريد قيام مع النتائج.

وأن يقال، مكتبة القياسية بيثون لديه عدة وحدات لتحليل XML ( بما في ذلك DOM، SAX، وElementTree). اعتبارا من بيثون 2.6، يتم تضمين الدعم لتحويل هياكل البيانات بيثون من وإلى JSON في json حدة .

وحتى البنية التحتية هناك.

نصائح أخرى

xmltodict (والكشف الكامل: أنا كتبت ذلك) يمكن أن تساعدك على تحويل XML الخاصة بك إلى ديكت + قائمة + هيكل سلسلة، تتبع هذا href="http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html" " معيار ". ومن الوافدة المستندة، حتى انها سريعة جدا ولا تحتاج إلى تحميل كله شجرة XML في الذاكرة.

وبمجرد الانتهاء من ذلك بنية بيانات، يمكنك إجراء تسلسل لJSON:

import xmltodict, json

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

ويمكنك استخدام xmljson مكتبة لتحويل باستخدام مختلف <أ href = على "HTTP: //wiki.open311. غزاله / JSON_and_XML_Conversion / "> الاتفاقيات JSON XML .

وعلى سبيل المثال، وهذا XML:

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

ويترجم عبر اتفاقية BadgerFish إلى هذا:

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

ووعبر GData في هذا (غير معتمدة سمات):

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

... وعبر باركر في هذا (غير معتمدة سمات):

{
  'p': 'text'
}

ومن الممكن تحويل من XML إلى JSON ومن JSON إلى XML باستخدام نفس الاتفاقيات:

>>> 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>]

والإفصاح: كتبت هذه المكتبة. نأمل أن يساعد الباحثين في المستقبل.

وهنا هو رمز أنا بنيت لذلك. ليس هناك توزيع للمحتويات، مجرد تحويل عادي.

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 __name__ == '__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()

اذا كان بعض الوقت تحصل فقط رمز الاستجابة بدلا من أن جميع البيانات ثم خطأ مثل سلمان تحليل سوف يكون هناك حتى u تحتاج إلى تحويل كما النص

import xmltodict

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

وهناك طريقة لنقل العلامات على أساس XML كما JSON الذي يسمح لها ليتم تحويلها losslessly العودة إلى شكلها الأصلي. انظر http://jsonml.org/ .

وانها نوع من XSLT من JSON. وآمل أن تجد أنه من المفيد

وقد تحتاج إلى إلقاء نظرة على http://designtheory.org/library/ extrep / designdb-1.0.pdf . يبدأ هذا المشروع قبالة مع XML لتحويل JSON مكتبة كبيرة من ملفات XML. كان هناك الكثير من الأبحاث التي أجريت في التحويل، وXML بديهية أبسط -> تم إنتاج الخرائط JSON (هو وصفها في وقت مبكر في الوثيقة). وخلاصة القول، وتحويل كل شيء إلى كائن JSON، ووضع كتل تكرار كقائمة من الكائنات.

والأشياء يعني مفتاح / قيمة أزواج (القاموس في بيثون، hashmap في جاوة، الكائن في جافا سكريبت)

وليس هناك رسم الخرائط إلى XML للحصول على وثيقة مماثلة، والسبب هو، ومن غير المعروف ما إذا كان الزوج مفتاح / قيمة سمة أو <key>value</key>، وبالتالي يتم فقدان تلك المعلومات.

إذا سألتني، الصفات هي الإختراق لبدء؛ ثم مرة أخرى أنها عملت بشكل جيد لHTML.

حسنا، ربما كان أبسط طريقة هي مجرد تحليل XML في القواميس وثم تسلسل أنه مع simplejson.

وأنا أقترح عدم الذهاب للتحويل المباشر. تحويل XML إلى كائن، ثم من كائن إلى JSON.

في رأيي، وهذا يعطي تعريفا أكثر نظافة لكيفية XML و JSON تتوافق.

ويستغرق وقتا طويلا للحصول على حق بل ويمكنك كتابة أدوات لمساعدتك في توليد بعض من ذلك، ولكن أنها تبدو تقريبا مثل هذا:

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 ):
    ...

ولقد وجدت لالقصاصات XML بسيطة، استخدام تعبير عادي من شأنه أن ينقذ المتاعب. على سبيل المثال:

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

لتفعل ذلك عن طريق تحليل XML، كما قالDan، وليس هناك واحد للجميع حل لأن البيانات هو مختلف. اقتراحي هو استخدام lxml. على الرغم من عدم الانتهاء إلى سلمان، lxml.objectify تعطي نتائج جيدة هادئة:

>>> 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'

وعلى الرغم من أن يبس المدمج في للتحليل XML هي جيدة جدا أنا جزئي ل lxml .

ولكن بالنسبة لتحليل آر إس إس، أود أن أوصى العالمي تغذية محلل ، والتي يمكن أيضا تحليل الذرة. ميزته الرئيسية هي أنه يمكن هضم الأعلاف حتى أكثر تالف.

وبيثون 2.6 تضم بالفعل محلل JSON، ولكن الإصدار الأحدث مع تحسن سرعة متاح كما simplejson .

ومع هذه الأدوات بناء التطبيق الخاص بك لا ينبغي أن يكون ذلك صعبا.

عندما أفعل أي شيء مع XML في بيثون أنا دائما تقريبا استخدام lxml الحزمة.وأظن أن معظم الناس استخدام lxml.هل يمكن استخدام xmltodict ولكن سيكون لديك لدفع عقوبة تحليل XML مرة أخرى.

تحويل XML إلى json مع lxml لك:

  1. تحليل مستند XML مع lxml
  2. تحويل lxml إلى ديكت
  3. تحويل القائمة إلى json

يمكنني استخدام الطبقة التالية في المشاريع.استخدام 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 __name__ == "__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)

الإخراج من المدمج في الرئيسية هو:

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

وهو التحول من هذا xml:

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

jsonpickle أو إذا كنت تستخدم feedparser، يمكنك محاولة <لأ href = "HTTP: // www.silassewell.com/blog/2008/05/05/universal-feed-parser-json/ "يختلط =" نوفولو "> feed_parser_to_json.py

جوابي عناوين محددة (و شائع إلى حد ما) حالة حيث كنت حقا لا تحتاج إلى تحويل كامل xml إلى json, ولكن ما تحتاجه لاجتياز/الوصول إلى أجزاء معينة من xml, و يجب أن يكون سريع, ، بسيطة (باستخدام سلمان/dict-مثل عمليات).

النهج

لهذا من المهم أن نلاحظ أن إعراب xml إلى etree باستخدام lxml بسرعة فائقة.بطيئة في معظم إجابات أخرى هي ثاني تمرير:تعبر etree هيكل (عادة في بيثون-أرض) ، وتحويلها إلى json.

الذي يقودني إلى نهج وجدت أفضل لهذه الحالة:تحليل xml باستخدام lxml, ثم يلف etree العقد (تكاسل) ، التي توفر لهم ديكت مثل واجهة.

رمز

هنا كود:

from collections import Mapping
import lxml.etree

class ETreeDictWrapper(Mapping):

    def __init__(self, elem, attr_prefix = '@', list_tags = ()):
        self.elem = elem
        self.attr_prefix = attr_prefix
        self.list_tags = list_tags

    def _wrap(self, e):
        if isinstance(e, basestring):
            return e
        if len(e) == 0 and len(e.attrib) == 0:
            return e.text
        return type(self)(
            e,
            attr_prefix = self.attr_prefix,
            list_tags = self.list_tags,
        )

    def __getitem__(self, key):
        if key.startswith(self.attr_prefix):
            return self.elem.attrib[key[len(self.attr_prefix):]]
        else:
            subelems = [ e for e in self.elem.iterchildren() if e.tag == key ]
            if len(subelems) > 1 or key in self.list_tags:
                return [ self._wrap(x) for x in subelems ]
            elif len(subelems) == 1:
                return self._wrap(subelems[0])
            else:
                raise KeyError(key)

    def __iter__(self):
        return iter(set( k.tag for k in self.elem) |
                    set( self.attr_prefix + k for k in self.elem.attrib ))

    def __len__(self):
        return len(self.elem) + len(self.elem.attrib)

    # defining __contains__ is not necessary, but improves speed
    def __contains__(self, key):
        if key.startswith(self.attr_prefix):
            return key[len(self.attr_prefix):] in self.elem.attrib
        else:
            return any( e.tag == key for e in self.elem.iterchildren() )


def xml_to_dictlike(xmlstr, attr_prefix = '@', list_tags = ()):
    t = lxml.etree.fromstring(xmlstr)
    return ETreeDictWrapper(
        t,
        attr_prefix = '@',
        list_tags = set(list_tags),
    )

هذا التطبيق ليست كاملة ، على سبيل المثال ، لا نظيفة دعم الحالات التي يكون فيها عنصر لديه كل من النص الصفات ، أو كل من النص و الأطفال (فقط لأنني لم أكن في حاجة إليها عندما كتبت ذلك...) ينبغي أن يكون من السهل على تحسين ذلك.

السرعة

في استخدام محدد الحالة ، حيث كنت بحاجة فقط عملية محددة عناصر xml هذا النهج أعطى مفاجئا ، ضرب تسريع بمقدار 70 (!) مقارنة باستخدام @مارتن Blech هو xmltodict ثم تعبر ديكت مباشرة.

مكافأة

كمكافأة منذ هيكل بالفعل dict-مثل الحصول على بديل آخر تنفيذ xml2json مجانا.نحن فقط بحاجة إلى اجتياز dict-مثل هيكل json.dumps.شيء من هذا القبيل:

def xml_to_json(xmlstr, **kwargs):
    x = xml_to_dictlike(xmlstr, **kwargs)
    return json.dumps(x)

إذا xml يتضمن سمات, كنت بحاجة إلى استخدام بعض أبجدية attr_prefix (مثلا ، "ATTR_") ، لضمان مفاتيح صالحة سلمان المفاتيح.

لم قياسها هذا الجزء.

ويتم الاحتفاظ بهذه الأشياء هنا بنشاط وحتى الآن هو المفضل لدي: xml2json في بيثون

لشخص قد لا تزال بحاجة هذا. وفيما يلي أحدث ورمز بسيط للقيام بذلك التحويل.

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

وتحقق من lxml2json (الكشف: أنا كتبت ذلك)

https://github.com/rparelius/lxml2json

وانها سريعة جدا وخفيفة الوزن (يتطلب فقط lxml)، وميزة واحدة هو أن لديك السيطرة على ما إذا كان يتم تحويل بعض العناصر على قوائم أو dicts

ويمكنك استخدام declxml. لديها ميزات متقدمة مثل سمات متعددة ودعم متداخلة معقدة. كل ما تحتاجه لكتابة معالج بسيط لذلك. أيضا مع نفس الرمز، يمكنك تحويل إلى JSON كذلك. فمن اضحة إلى حد ما والوثائق رهيبة.

الرابط: https://declxml.readthedocs.io/en/latest/index هتمل

وإعداد البيانات في بيثون : لإنشاء JSON تحتاج أولا إلى إعداد البيانات في بيثون. يمكننا استخدام قائمة وقاموس في بيثون لإعداد البيانات.

بيثون قائمة <==> <أ href ل = "https://devstudioonline.com/article/create-json-and-xml-in-python" يختلط = "نوفولو noreferrer"> JSON صفيف

بيثون قاموس <==> <أ href ل = "https://devstudioonline.com/article/create-json-and-xml-in-python" يختلط = "نوفولو noreferrer"> كائن JSON (وتنسيق قيمة المفتاح) التحقق من ذلك لمزيد من التفاصيل

https://devstudioonline.com/article/create-json -و-أكس-في-الثعبان

لتمثيل البيانات في JSON شكل

name=John
age=20
gender=male
address=Sector 12 Greater Kailash, New Delhi
Jobs=Noida,Developer | Gurugram,Tester |Faridabad,Designer

في سلمان نحن repesent بيانات في مفتاح و شكل قيمة

{
    "name":"john",
    "age":20,
    "gender":"male",
    "address":["New kP college","Greater Kailash","New Delhi"],
    "jobs":[
               {"Place":"Noida","Title":"Developer "},
               {"Place":"Gurugram","Title":"Tester "},
               {"Place":"Faridabad","Title":"Designer"}
           ]
}

لتمثيل البيانات في XML شكل

<!-- In xml we write a code under a key you can take any key -->
<info> <!-- key open -->

<name> john </name> 
<age> 20 </age>
<gender> male </gender>

<address> 
<item> New kP college </item>
<item> Greater Kailash </item>
<item> New Delhi </item>
</address>

<jobs>
 <item>
  <title>Developer </title>
  <place>Noida</place>
 </item>

 <item>
  <title>Designer</title>
  <place>Gurugram</place>
 </item>
 
 <item>
  <title>Developer </title>
  <place>Faridabad</place>
 </item>
</jobs>

</info> <!-- key close-->

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top