Python string,dict,list und Co. <-> XML

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
BlackJack

Donnerstag 16. März 2006, 23:30

jens hat geschrieben: Aber ich kann nicht wirklich glauben, das es nicht schon sowas in der Art, irgendwo fertig rumschwirrt...
Ich habe heute nebenbei mal was gebastelt. Ist nicht wirklich schön, ziemlich unterdokumentiert, aber scheint zu funktionieren:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""XML objects.

The following types can be converted to XML and back:

* None, True and False
* int, long and float
* str
* unicode (as long as it contains only printable characters below U+0020)
* tuple, list, set, frozenset and dict

The container types must not contain cycles and if an object is referenced
more than once it's contend will be expanded for every occurence.

  >>> import xmlobjects
  >>> a = (1, 2, 3)
  >>> b = [a, a]
  >>> xml = xmlobjects.encode(b)
  >>> print xml
  <objects version="0">
    <object type="list">
      <object type="tuple">
        <object type="int">1</object>
        <object type="int">2</object>
        <object type="int">3</object>
      </object>
      <object type="tuple">
        <object type="int">1</object>
        <object type="int">2</object>
        <object type="int">3</object>
      </object>
    </object>
  </objects>

If that XML is decoded, both elements of the list are different objects:

  >>> c = xmlobjects.decode(xml)
  >>> c
  [(1, 2, 3), (1, 2, 3)]
  >>> c[0] is c[1]
  False

"""
from __future__ import division
from itertools import imap
from elementtree.ElementTree import TreeBuilder, XML, tostring

__author__ = "Marc 'BlackJack' Rintsch"
__version__ = '0.0.1'
__date__ = '$Date: 2006-03-16 21:02:28 +0100 (Thu, 16 Mar 2006) $'
__revision__ = '$Rev: 825 $'

OBJECT = 'object'
OBJECTS = 'objects'

encoders = dict()
decoders = dict()


def encode_none(builder, obj):
    builder.start_object('None')
    builder.end_object()


def encode_bool(builder, obj):
    builder.start_object('bool')
    builder.data(str(obj))
    builder.end_object()

def decode_bool(decoder, element):
    try:
        return {'True': True, 'False': False}[element.text]
    except KeyError:
        raise Exception('expected True or False, got %r instead' % element.text)


def encode_complex(builder, obj):
    builder.start_object('complex')
    builder.feed(obj.real)
    builder.feed(obj.imag)
    builder.end_object()

def decode_complex(decoder, element):
    return complex(decoder.dispatch(element[0]), decoder.dispatch(element[1]))


def encode_str(builder, obj):
    try:
        value = obj.decode('ascii')
        typename = 'str'
        small_values = set(char for char in value if char < ' ')
        small_values -= set('\t\r\n')
        if small_values:
            value = obj.encode('base64')
            typename = 'binstr'
    except UnicodeDecodeError:
        value = obj.encode('base64')
        typename = 'binstr'
    builder.start_object(typename)
    builder.data(value)
    builder.end_object()

def decode_str(decoder, element):
    return str(element.text)

def decode_binstr(decoder, element):
    return element.text.decode('base64')


def make_encode_object(typename, encode_func):
    def encode_object(builder, obj):
        builder.start_object(typename)
        builder.data(encode_func(obj))
        builder.end_object()
    return encode_object


def make_decode_object(decode_func):
    def decode_object(decoder, element):
        return decode_func(element.text)
    return decode_object


def make_iterable_encoder(typename):
    def encode_iterable(builder, obj):
        builder.encode_iterable(typename, obj)
    return encode_iterable


def make_iterable_decoder(type_):
    def decode_iterable(decoder, element):
        return type_(imap(decoder.dispatch, element))
    return decode_iterable


def register(type_, encode_func, decode_func, serialized_name=None):
    typename = type_.__name__
    if not serialized_name:
        serialized_name = typename
    encoders[typename] = encode_func
    decoders[serialized_name] = decode_func


def _register_default_types():
    register(type(None), encode_none, lambda d, e: None, 'None')
    
    for type_ in (bool, complex, str):
        typename = type_.__name__
        register(type_,
                 globals()['encode_' + typename],
                 globals()['decode_' + typename])
    decoders['binstr'] = decode_binstr
    
    for type_, encode_func in ((int, str),
                               (float, repr),
                               (unicode, unicode)):
        typename = type_.__name__
        register(type_,
                 make_encode_object(typename, encode_func),
                 make_decode_object(type_))
    
    for type_ in (list, tuple, set, frozenset, dict):
        typename = type_.__name__
        register(type_,
                 make_iterable_encoder(typename),
                 make_iterable_decoder(type_))
    encoders['dict'] = lambda b, o: b.encode_iterable('dict', o.iteritems())
    
    for coders in (encoders, decoders):
        coders['long'] = coders['int']

_register_default_types()


class ObjectTreeBuilder(TreeBuilder):
    def __init__(self):
        TreeBuilder.__init__(self)
        self.start(OBJECTS, {'version': '0'})
        self.encoders = encoders
    
    def feed(self, obj):
        typename = obj.__class__.__name__
        try:
            encode_func = self.encoders[typename]
        except KeyError:
            raise Exception('unknown type %r' % typename)
        encode_func(self, obj)
    
    def close(self):
        self.end(OBJECTS)
        return TreeBuilder.close(self)
    
    def start_object(self, typename):
        self.start(OBJECT, {'type': typename})
    
    def end_object(self):
        self.end(OBJECT)
    
    def encode_iterable(self, typename, iterable):
        self.start_object(typename)
        for item in iterable:
            self.feed(item)
        self.end_object()


class Decoder(object):
    def __init__(self, source):
        self.elements = iter(XML(source))
        self.decoders = decoders
    
    def dispatch(self, element):
        typename = element.attrib['type']
        try:
            decode_func = self.decoders[typename]
        except KeyError:
            raise Exception('unknown type %r' % typename)
        return decode_func(self, element)
    
    def read(self):
        return self.dispatch(self.elements.next())


def indent(element, level=0):
    if not element.tail:
        element.tail = '\n' + ('  ' * level)
    if not element.text and len(element):
        element.text = '\n' + ('  ' * (level + 1))
    for child in element:
        indent(child, level + 1)
    if element:
        element[-1].tail = '\n' + ('  ' * level)


def encode(obj, encoding='utf-8', pretty_print=True):
    otb = ObjectTreeBuilder()
    otb.feed(obj)
    tree = otb.close()
    if pretty_print:
        indent(tree)
    return tostring(tree, encoding)


def decode(text):
    return Decoder(text).read()


def test():
    objects = ([None, True, False, (1, 0.1, (42+23j)), '<test>', u'hällø'],
               {'name': 'Methusalem', 'age': 1000000000000000000000},
               set('Mississippi'),
               frozenset('Mississippi'))

    xml_string = encode(objects)
    print xml_string
    print decode(xml_string)


if __name__ == '__main__':
    test()
Dein Beispiel sieht dann so aus:

Code: Alles auswählen

In [527]:t = [
   .527.:    "beispiel", 123, "noch was",
   .527.:    {'status':'GM', 'rating':2700},
   .527.:    {'status':'Computer', 'rating':2700},
   .527.:    {'status':'Amateur', 'rating':1400},
   .527.:    {
   .527.:        "eins": {"a":1, "b":2},
   .527.:        "zwei": {"c":2, "d":3},
   .527.:    },
   .527.:]

In [528]:print xmlobjects.encode(t)
<objects version="0">
  <object type="list">
    <object type="str">beispiel</object>
    <object type="int">123</object>
    <object type="str">noch was</object>
    <object type="dict">
      <object type="tuple">
        <object type="str">status</object>
        <object type="str">GM</object>
      </object>
      <object type="tuple">
        <object type="str">rating</object>
        <object type="int">2700</object>
      </object>
    </object>
    <object type="dict">
      <object type="tuple">
        <object type="str">status</object>
        <object type="str">Computer</object>
      </object>
      <object type="tuple">
        <object type="str">rating</object>
        <object type="int">2700</object>
      </object>
    </object>
    <object type="dict">
      <object type="tuple">
        <object type="str">status</object>
        <object type="str">Amateur</object>
      </object>
      <object type="tuple">
        <object type="str">rating</object>
        <object type="int">1400</object>
      </object>
    </object>
    <object type="dict">
      <object type="tuple">
        <object type="str">eins</object>
        <object type="dict">
          <object type="tuple">
            <object type="str">a</object>
            <object type="int">1</object>
          </object>
          <object type="tuple">
            <object type="str">b</object>
            <object type="int">2</object>
          </object>
        </object>
      </object>
      <object type="tuple">
        <object type="str">zwei</object>
        <object type="dict">
          <object type="tuple">
            <object type="str">c</object>
            <object type="int">2</object>
          </object>
          <object type="tuple">
            <object type="str">d</object>
            <object type="int">3</object>
          </object>
        </object>
      </object>
    </object>
  </object>
</objects>
Man kann natürlich sagen, dass es auch ein wenig aufgebläht ist, weil ich nur ein Tag verwende, aber ich wollte es erstmal einfach halten und erweiterbar, so dass man auch Typnamen verwenden kann die keine gültigen Tagnamen sind.

Man kann auch (De)Kodierfunktionen für andere Datentypen registrieren.

Wenn Zeichenketten "binäre" Daten enthalten, dann werden sie in Base64 kodiert gespeichert.

Und das ganze kommt nicht mit zyklischen Datenstrukturen klar und Referenzen auf das gleiche Objekt werden jedesmal neu kodiert und beim wiedereinlesen hat man dann zwei gleiche Objekte, die aber nicht die selben sind.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 17. März 2006, 07:43

Wow... Nette arbeit, die du dir gemacht hat... Leider kann ich aber nur mekern :lol:

Du hast das externe Modul ElementTree genutzt, das ist nicht nur schlecht, weil ich es nicht installiert hab, sondern generell blöd weil man es installieren muß ;)
Laut http://effbot.org/zone/element-index.htm wird zwar wohl in Python 2.5 mit an Board sein, aber solange auf Shared-Hosting-Server ein uralt Python installiert ist, bringt das erstmal auch nix...

Wie du schon richtig festgestellt hat, ist deine gewählte Datenstruktur leider auch sehr aufgebläht. Aber immerhin wesendlich besser als XMLRPC das macht, weil es viel lesbarer ist...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 17. März 2006, 08:56

Frisch aus der Maillingliste, gibt es was:

Code: Alles auswählen

import sys

t = [
    "beispiel", 123, "noch was",
    {'status':'GM', 'rating':2700},
    {'status':'Computer', 'rating':2700},
    {'status':'Amateur', 'rating':1400},
    {
        "eins": {"a":1, "b":2},
        "zwei": {"c":2, "d":3},
    },
]

def to_xml(data, out, deep=0, **attributes):
    typ = data.__class__.__name__

    attr = [typ]
    for a in attributes.iteritems():
        attr.append('%s="%s"' % a)
    attr = " ".join(attr)

    out.write(
        "%s<%s>" % ("\t"*deep, attr)
    )

    if isinstance(data, dict):
        out.write("\n")
        for k,v in data.iteritems():
            to_xml(v, out, deep+1, key=k)
        out.write("\t"*deep)

    elif isinstance(data, list) or \
        isinstance(data, tuple):
        out.write("\n")
        for e in data:
            to_xml(e, out, deep+1)
        out.write("\t"*deep)

    else:
        out.write(repr(data))

    out.write("</%s>\n" % typ)

to_xml(t, out=sys.stdout)

print "-"*79
t = {'foo': {"bar":("jup","jap","schnupp")}}
to_xml(t, out=sys.stdout)
Erzeugt:

Code: Alles auswählen

<list>
	<str>'beispiel'</str>
	<int>123</int>
	<str>'noch was'</str>
	<dict>
		<str key="status">'GM'</str>
		<int key="rating">2700</int>
	</dict>
	<dict>
		<str key="status">'Computer'</str>
		<int key="rating">2700</int>
	</dict>
	<dict>
		<str key="status">'Amateur'</str>
		<int key="rating">1400</int>
	</dict>
	<dict>
		<dict key="eins">
			<int key="a">1</int>
			<int key="b">2</int>
		</dict>
		<dict key="zwei">
			<int key="c">2</int>
			<int key="d">3</int>
		</dict>
	</dict>
</list>
-------------------------------------------------------------------------------
<dict>
	<dict key="foo">
		<tuple key="bar">
			<str>'jup'</str>
			<str>'jap'</str>
			<str>'schnupp'</str>
		</tuple>
	</dict>
</dict>
EDIT: So, nun hab ich auch die TABs besser erzeugt....

EDIT2: man sieht allerdings das es mit komplizierten Kombinationen probleme gibt, bei <tuple key="bar">

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Freitag 17. März 2006, 10:39

jens hat geschrieben:Wow... Nette arbeit, die du dir gemacht hat... Leider kann ich aber nur mekern :lol:
Ich werd's überleben. :-)
Du hast das externe Modul ElementTree genutzt, das ist nicht nur schlecht, weil ich es nicht installiert hab, sondern generell blöd weil man es installieren muß ;)
Laut http://effbot.org/zone/element-index.htm wird zwar wohl in Python 2.5 mit an Board sein, aber solange auf Shared-Hosting-Server ein uralt Python installiert ist, bringt das erstmal auch nix...
ElementTree ist aber so schön einfach zu benutzen. Und es ist in Python geschrieben, sollte sich also auch als Benutzer installieren lassen.
Wie du schon richtig festgestellt hat, ist deine gewählte Datenstruktur leider auch sehr aufgebläht. Aber immerhin wesendlich besser als XMLRPC das macht, weil es viel lesbarer ist...
Wie gesagt ich wollt's erstmal möglichst generell halten. Aber ich habe in der ToDo stehen, dass ich es mal mit eigenen Tags für die Grundtypen probieren will. Und zyklische Datenstrukturen wären auch ganz nett, damit man auch "Graphen" speichern kann.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 17. März 2006, 11:11

Ein kleines Update... Nun kümmere ich mich nicht mehr um die Formatierung, denn die kann man anschließend von minidom machen lassen:

Code: Alles auswählen

import sys

t = [
    "beispiel", 123, "noch was",
    {'status':'GM', 'rating':2700},
    {
        "eins": {"a":1, "b":2},
        "zwei": {"c":2, "d":3},
    },
    {'foo': {"bar":("jup","jap","schnupp")}}
]

def to_xml(data, out, **attributes):
    typ = data.__class__.__name__

    attr = [typ]
    for a in attributes.iteritems():
        attr.append('%s="%s"' % a)
    attr = " ".join(attr)

    out.write("<%s>" % attr)

    if isinstance(data, dict):
        for k,v in data.iteritems():
            to_xml(v, out, key=k)

    elif isinstance(data, list) or \
        isinstance(data, tuple):
        for e in data:
            to_xml(e, out)

    else:
        out.write(str(data))

    out.write("</%s>" % typ)

class buffer:
    def __init__(self):
        self.data = ""
    def write(self, s):
        self.data += s


b = buffer()

to_xml(t, out=b)
data = b.data
print data


from xml.dom import minidom
# Formatieren und ausgeben
dom = minidom.parseString(data)
print dom.toprettyxml("    ")

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 17. März 2006, 13:11

Ich hab mal meines weiter gebaut, aber nun häng ich an einem Fehler und komm nicht weiter:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys, time

t = [
    "beispiel", 123, 23j, #u'hällø',
    {"1": None, "2": True, "3": False},
    {'status':'GM', 'rating':2700},
    {
        "eins": {"a":1, "b":2},
        "zwei": {"c":2, "d":3},
    },
    {'foo': {"bar":("jup","jap","schnupp")}}
]


class XMLPickle:
    def __init__(self):

        self.encodingMap = {
            dict: self.encode_dict,
            list: self.encode_iter,
            tuple: self.encode_iter,
            unicode: self.encode_unicode,

            str: str,

            int: str,
            long: str,
            complex: str,
        }

    def encode_dict(self, data):
        result = ""
        for k,v in data.iteritems():
            result += self.to_xml(v, key=k)
        return result

    def encode_iter(self, data):
        result = ""
        for e in iter(data):
            result += self.to_xml(e)
        return result

    def encode_unicode(self, data):
        try:
            return data.decode('ascii')
        except UnicodeError:
            return data.encode(
                sys.stdout.encoding or sys.getfilesystemencoding()
            )

    def encodeData(self, data):
        # Quick: type()-Mapping
        try:
            return self.encodingMap[type(data)](data)
        except KeyError:
            # slow Fallback: isinstance()-Mapping
            for encodeType, method in self.encodingMap.iteritems():
                if isinstance(data, encodeType):
                    return method(data)

            try:
                return encode_iter(e)
            except:
                return str(data)


    def to_xml(self, data, **attributes):
        result = ""
        typ = data.__class__.__name__

        if type(data) in (None,True,False,):
            return "<%s></%s>" % (data,data)

        if attributes:
            startTag = [typ]
            for a in attributes.iteritems():
                startTag.append('%s="%s"' % a)
            startTag = " ".join(startTag)
        else:
            startTag = typ

        return "<%s>%s</%s>" % (
            startTag, self.encodeData(data), typ
        )

    def dumps(self, dataString):
        return self.to_xml(dataString)



def durationTest():
    start_time = time.time()
    xml = XMLPickle()
    for i in xrange(10000):
        xml.dumps(t)
    print "duration: %.2fsec" % (time.time()- start_time)

#~ durationTest()

xml = XMLPickle()
xmlData = xml.dumps(t)
xmlData = "<data>%s</data>" % xmlData

#~ xmlData = xmlData.replace(">",">\n")
#~ xmlData = xmlData.strip()
#~ for e in enumerate(xmlData.split("\n")):
    #~ print "%3s - %s" % e

#~ print xmlData

from xml.dom import minidom

# Formatieren und ausgeben
dom = minidom.parseString(xmlData)
print dom.toprettyxml("    ")
Ausgabe:

Code: Alles auswählen

<?xml version="1.0" ?>
<data>
    <list>
        <str>
            beispiel
        </str>
        <int>
            123
        </int>
        <complex>
            23j
        </complex>
        <dict>
            <NoneType key="1">
                None
            </NoneType>
            <bool key="3">
                False
            </bool>
            <bool key="2">
                True
            </bool>
        </dict>
        <dict>
            <str key="status">
                GM
            </str>
            <int key="rating">
                2700
            </int>
        </dict>
        <dict>
            <dict key="eins">
                <int key="a">
                    1
                </int>
                <int key="b">
                    2
                </int>
            </dict>
            <dict key="zwei">
                <int key="c">
                    2
                </int>
                <int key="d">
                    3
                </int>
            </dict>
        </dict>
        <dict>
            <dict key="foo">
                <tuple key="bar">
                    <str>
                        jup
                    </str>
                    <str>
                        jap
                    </str>
                    <str>
                        schnupp
                    </str>
                </tuple>
            </dict>
        </dict>
    </list>
</data>
EDIT: Fehler gefunden... (Ich dummie hab alle Tags nicht geschlossen ;)

Außerdem wüßte ich gern, wie man am besten mit unicode umgehen könnte... Aber das kommt wahrscheinlich auf die Art der Verwendung an, was?

Nun müßte ich mir mal überlegen, wie man das wieder zurück wandeln kann... *schau auf BlackJack's Lösung* :lol:

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Freitag 17. März 2006, 17:01

Leonidas hat geschrieben:Ich werf jetzt noch neben YAML auch noch JSON rein, zusammen mit JSON-RPC ;)
Wollte ich auch gerade vorschlagen. Nutzt pocoo für den AJAX transport :)
TUFKAB – the user formerly known as blackbird
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 17. März 2006, 17:23

Hab mir gerade simplejson angeschaut... Sieht nett aus:

Code: Alles auswählen

import simplejson

t = [
    "beispiel", 123, 23, #u'hällø',
    {"1": None, "2": True, "3": False},
    {'status':'GM', 'rating':2700},
    {
        "eins": {"a":1, "b":2},
        "zwei": {"c":2, "d":3},
    },
    {'foo': {"bar":("jup","jap","schnupp")}}
]

data = simplejson.dumps(t)
print data
print type(data)


data = simplejson.loads(data)
print data
print type(data)
Ist kaum ein unterschied zur Python-Version auszumachen:

Code: Alles auswählen

["beispiel", 123, 23, {"1":null, "3":false, "2":true}, {"status":"GM", "rating":2700}, {"eins":{"a":1, "b":2}, "zwei":{"c":2, "d":3}}, {"foo":{"bar":["jup", "jap", "schnupp"]}}]
<type 'str'>
[u'beispiel', 123, 23, {u'1': None, u'3': False, u'2': True}, {u'status': u'GM', u'rating': 2700}, {u'eins': {u'a': 1, u'b': 2}, u'zwei': {u'c': 2, u'd': 3}}, {u'foo': {u'bar': [u'jup', u'jap', u'schnupp']}}]
<type 'list'>
IMHO hätten die sich dann auch gleich alle Leerzeichen sparen können...


Aber ich weiß nicht, es ist nicht so super gut lesbar, weil die Formatierung, in einer Zeile, recht unübersichtlich ist. Da kann ich gleich pickle nehmen...

Die Sourcen sind mit 26KB vertretbar klein...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
XT@ngel
User
Beiträge: 256
Registriert: Dienstag 6. August 2002, 14:36
Kontaktdaten:

Freitag 17. März 2006, 18:16

HI, ich hab jetzt nicht alles gelesen aber schau dir dochmal Dookies PyXO an.
http://www.boa3d.de/python/modules/PyXO.php die Seite ist noch online.

MfG
Andreas
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 17. März 2006, 18:29

Dookies PyXO hatte ich mir heute schon öfters mal angesehen. Aber IMHO kann man damit nicht wirklich ein verschachteltes dict/liste/tuple zu XML konvertieren... oder ich hab es noch nicht richtig verstanden :oops:

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
XT@ngel
User
Beiträge: 256
Registriert: Dienstag 6. August 2002, 14:36
Kontaktdaten:

Freitag 17. März 2006, 21:35

Logisch gehts das ;)

Am Beispiel t = []

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import PyXO

xmlfile = "PyXO_demo.xml"

t = [
    "beispiel", 123, 23, #u'hällø',
    {"1": None, "2": True, "3": False},
    {'status':'GM', 'rating':2700},
    {
        "eins": {"a":1, "b":2},
        "zwei": {"c":2, "d":3},
    },
    {'foo': {"bar":("jup","jap","schnupp")}}
] 

PyXO.Object.save(xmlfile, t)
Ergebnis

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8"?>
<PyXO del_root="true" id="Root_001" name="PyXO_demo.xml" python_module="PyXO">
  <list>
    <str>beispiel</str>
    <int>123</int>
    <int>23</int>
    <dict>
      <str>1</str>
        <NoneType>None</NoneType>
      <str>3</str>
        <bool>False</bool>
      <str>2</str>
        <bool>True</bool>
    </dict>
    <dict>
      <str>status</str>
        <str>GM</str>
      <str>rating</str>
        <int>2700</int>
    </dict>
    <dict>
      <str>eins</str>
        <dict>
          <str>a</str>
            <int>1</int>
          <str>b</str>
            <int>2</int>
        </dict>
      <str>zwei</str>
        <dict>
          <str>c</str>
            <int>2</int>
          <str>d</str>
            <int>3</int>
        </dict>
    </dict>
    <dict>
      <str>foo</str>
        <dict>
          <str>bar</str>
            <tuple>
              <str>jup</str>
              <str>jap</str>
              <str>schnupp</str>
            </tuple>
        </dict>
    </dict>
  </list>
</PyXO>
Es gibt nichts besseres als PyXO

MfG
Andreas :wink:
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Samstag 18. März 2006, 08:35

XT@ngel hat geschrieben:Es gibt nichts besseres als PyXO
Wow, das geht ja doch... Ich hatte auf die schnelle kein Beispiel gefunden...

Ich würde allerdings gern eine dumpString() und loadString() Methode einbauen... Aber ich check einfach nicht, wie PyXO funktioniert... Kannst du mir helfen?

EDIT: Ich hab PyXO mal in meinem SVN aufgenommen: http://www.python-forum.de/viewtopic.php?p=33275#33275

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Samstag 18. März 2006, 12:37

Bah, PyXO ist nicht mal auf irgendeine geartete Weise transparent wie das pickle ist. Eines der schlimmsten Hacks die ich bisher gesehen habe. Wenn Du wirklich xml-Pickling willst, dann guck Dir mal gnosis.xml.* an, die haben ein pickle(-ähnliches) Serialisierungsprotokoll (sprich __savestate__ und __loadstate__ und Verwandte), und geben auch brauchbares XML aus (was ohne XML-Tags in Text wie bei PyXO auskommt, *brrrrr*^5, siehe Beispiel auf der Webseite zu Base64). Alles andere wie der __init__(**kwargs)-Hack bei PyXO ist Scheiße.

Edit: natürlich gehts bei meiner Kritik um Serialisierung von eigenen Objekten. Dass PyXO normale Standard-Python-Objektbäume transparent serialisiert, davon bin ich einfach mal so ausgegangen...
--- Heiko.
XT@ngel
User
Beiträge: 256
Registriert: Dienstag 6. August 2002, 14:36
Kontaktdaten:

Samstag 18. März 2006, 14:03

Hie Jens,
jens hat geschrieben: Ich würde allerdings gern eine dumpString() und loadString() Methode einbauen... Aber ich check einfach nicht, wie PyXO funktioniert... Kannst du mir helfen?
Kannst du mir erklären was du darunter verstehst? Ich schau dann mal ob ich dir helfen kann.

@modeline
Alles eine Frage des Blickwinkels, mich interessiert nicht wie ein Modul funktioniert. Wichtig ist, dass es funktioniert und seinen Zweck erfüllt.
Immer diese Kritiker.........


MfG
Andreas
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Samstag 18. März 2006, 14:26

Immer diese Kritiker.........
Das iss nicht böse gemeint, und ich weiß dass der Entwickler von PyXO auch hier im Forum ist. Nur find ich das Design von PyXO absolut unsauber und unpythonisch, deswegen würde ich einen riesengroßen Bogen drum machen. Da ist gnosis.xml.pickle erheblich besser, weil's eben pickle vom Interface her nachbaut (und was eben ein ziemlich pythonisches Interface hat, für allgemeine Inhalte von "pythonisch"), bloß eine XML-Ausgabe produziert, ähnlich wie PyXO auch.

Aber: hört nicht auf mich, vielleicht bin ich auch einfach zu sehr Perfektionist... ;-)
--- Heiko.
Antworten