summaryrefslogtreecommitdiff
path: root/lib/thandy/encodeToXML.py
blob: c563d77bd8c0f4cbcc7010c9fa3fc1103be0d9a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.

import re
import thandy

def xml_str_encoder(s):
    s = s.replace("&", "&")
    s = s.replace("<", "&lt;")
    s = s.replace(">", "&gt;")
    return s

def isAsciiName(s):
    """
       Return true iff s is pure-ascii, and a syntactically valid XML name.

       >>> isAsciiName("a")
       True
       >>> isAsciiName("ab.-dc")
       True
       >>> isAsciiName("")
       False
       >>> isAsciiName(".foo")
       False
    """
    return re.match(r'^[A-Za-z\_\:][A-Za-z0-9\_\:\-\.]*$', s) != None

def _encodeToXML(obj, outf):
    if isinstance(obj, basestring):
        outf(xml_str_encoder(obj))
    elif obj is True:
        outf("true")
    elif obj is False:
        outf("false")
    elif obj is None:
        outf("null")
    elif isinstance(obj, (int,long)):
        outf(str(obj))
    elif isinstance(obj, (tuple, list)):
        outf("<list>\n")
        for item in obj:
            outf("<item>")
            _encodeToXML(item, outf)
            outf("</item> ")
        outf("</list>\n")
    elif isinstance(obj, dict):
        outf("<dict>\n")
        for k,v in sorted(obj.items()):
            isAscii = isAsciiName(k)
            if isAscii:
                outf("<%s>"%k)
                _encodeToXML(v, outf)
                outf("</%s>\n"%k)
            else:
                outf("<dict-entry><key>%s</key><val>"%xml_str_encoder(k))
                _encodeToXML(v, outf)
                outf("</val></dict-entry>\n")
        outf("</dict>\n")
    else:
        raise thandy.FormatException("I can't encode %r"%obj)

def encodeToXML(obj, outf=None):
    """Convert a json-encodable object to a quick-and-dirty XML equivalent."""
    result = None
    if outf == None:
        result = []
        outf = result.append

    _encodeToXML(obj, outf)
    if result is not None:
        return "".join(result)