Statistics
| Branch: | Tag: | Revision:

root / ncclient / content.py @ 94803aaf

History | View | Annotate | Download (2.9 kB)

1
# Copyright 2009 Shikhar Bhushan
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#    http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

    
15
"TODO: docstring"
16

    
17
from xml.etree import cElementTree as ET
18

    
19

    
20
### Namespace-related ###
21

    
22
BASE_NS = 'urn:ietf:params:xml:ns:netconf:base:1.0'
23
# and this is BASE_NS according to cisco devices...
24
CISCO_BS = 'urn:ietf:params:netconf:base:1.0'
25

    
26
try:
27
    register_namespace = ET.register_namespace
28
except AttributeError:
29
    def register_namespace(prefix, uri):
30
        from xml.etree import ElementTree
31
        # cElementTree uses ElementTree's _namespace_map, so that's ok
32
        ElementTree._namespace_map[uri] = prefix
33

    
34
# we'd like BASE_NS to be prefixed as "netconf"
35
register_namespace('netconf', BASE_NS)
36

    
37
qualify = lambda tag, ns=BASE_NS: '{%s}%s' % (ns, tag)
38

    
39
# i would have written a def if lambdas weren't so much fun
40
multiqualify = lambda tag, nslist=(BASE_NS, CISCO_BS): [qualify(tag, ns)
41
                                                        for ns in nslist]
42

    
43
unqualify = lambda tag: tag[tag.rfind('}')+1:]
44

    
45
### Build XML using Python data structures ###
46

    
47
class XMLConverter:
48
    """Build an ElementTree.Element instance from an XML tree specification
49
    based on nested dictionaries. TODO: describe spec
50
    """
51
    
52
    def __init__(self, spec):
53
        "TODO: docstring"
54
        self._root = XMLConverter.build(spec)
55
    
56
    def to_string(self, encoding='utf-8'):
57
        "TODO: docstring"
58
        xml = ET.tostring(self._root, encoding)
59
        # some etree versions don't always include xml decl e.g. with utf-8
60
        # this is a problem with some devices
61
        if not xml.startswith('<?xml'):
62
            return ((u'<?xml version="1.0" encoding="%s"?>'
63
                     % encoding).encode(encoding) + xml)
64
        else:
65
            return xml
66
    
67
    @property
68
    def tree(self):
69
        "TODO: docstring"
70
        return self._root
71
    
72
    @staticmethod
73
    def build(spec):
74
        "TODO: docstring"
75
        if 'tag' in spec:
76
            ele = ET.Element(spec.get('tag'), spec.get('attributes', {}))
77
            ele.text = spec.get('text', '')
78
            children = spec.get('children', [])
79
            if isinstance(children, dict):
80
                children = [children]
81
            for child in children:
82
                ele.append(TreeBuilder.build(child))
83
            return ele
84
        elif 'xml' in spec:
85
            return ET.XML(spec['xml'])
86
        elif 'comment' in spec:
87
            return ET.Comment(spec.get('comment'))
88
        else:
89
            raise ValueError('Invalid tree spec')