Projet

Général

Profil

0002-add-an-XmlBuilder-class-to-help-in-generating-XML-do.patch

Benjamin Dauvergne, 02 décembre 2015 16:45

Télécharger (3,57 ko)

Voir les différences:

Subject: [PATCH 2/5] add an XmlBuilder class to help in generating XML
 documents (#9163)

 passerelle/xml_builder.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 passerelle/xml_builder.py
passerelle/xml_builder.py
1
import xml.etree.ElementTree as ET
2

  
3

  
4
class XmlBuilder(object):
5
    '''Build XML document interpolating value from context using str.format() in
6
       text data. Grammar for schema is:
7

  
8
           schema = tree
9
           tree = simple | loop 
10
           simple = (tag_name, attribs_dict?, tree*)
11
           loop = ('?loop', loop_var_name, tree*)
12

  
13
       where tag_name is an ElementTree tag name, or an XML tag name with prefix
14
       in namespaces, attribs_dict is a list of key values pairs
15

  
16
       The loop construct allow to iterate one variable, the one named by loop_var_name, of the
17
       context as a subcontext to pass to sub-schemas inside the loop tuple.
18
    '''
19
    schema = None
20
    encoding = 'us-ascii'
21
    namespaces = None
22

  
23
    def __init__(self, schema=None, encoding=None, namespaces=None):
24
        self.namespaces = {}
25
        if schema is not None:
26
            self.schema = schema
27
        if encoding is not None:
28
            self.encoding = encoding
29
        if namespaces is not None:
30
            self.namespaces.update(namespaces)
31

  
32
    def resolve_namespace(self, qname):
33
        if ':' in qname:
34
            prefix, name = qname.split(':')
35
            url = self.namespaces[prefix]
36
            return '{{{0}}}{1}'.format(url, name)
37
        return qname
38

  
39
    def build(self, context=None):
40
        tb = ET.TreeBuilder()
41
        def helper(schema, context):
42
            tag = schema[0]
43
            if tag == '?loop':
44
                var = schema[1]
45
                for subcontext in context[var]:
46
                    for subschema in schema[2:]:
47
                        helper(subschema, subcontext)
48
                return
49
            if context:
50
                tag = tag.format(**context)
51
            tag = self.resolve_namespace(tag)
52
            template_attribs = schema[1] if (len(schema) > 0
53
                                             and isinstance(schema[1], dict)) else None
54
            attribs = None
55
            if template_attribs:
56
                for key, value in template_attribs.items():
57
                    if context:
58
                        key = key.format(**context)
59
                    key = self.resolve_namespace(key)
60
                    value = value.format(**context)
61
                    attribs[key] = value
62
            tb.start(tag, attribs or {})
63
            if template_attribs is None:
64
                children = schema[1:]
65
            else:
66
                children = schema[2:]
67
            for child in children:
68
                if isinstance(child, basestring):
69
                    if context:
70
                       child = child.format(**context)
71
                    tb.data(child)
72
                else:
73
                    helper(child, context)
74
            tb.end(tag)
75
        helper(self.schema, context)
76
        return tb.close()
77

  
78
    def string(self, context=None, encoding=encoding):
79
        return ET.tostring(
80
            self.build(context=context),
81
            encoding=encoding or self.encoding)
0
-