git-svn-id: http://ncclient.googlecode.com/svn/trunk@82 6dbcf712-26ac-11de-a2f3-13738...
[ncclient] / ncclient / content.py
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 ### Namespace-related ###
20
21 BASE_NS = 'urn:ietf:params:xml:ns:netconf:base:1.0'
22
23 # cisco returns incorrectly namespaced xml
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: '{%s}%s' % (namespace, tag)
38
39 unqualify = lambda tag: tag[tag.rfind('}')+1:]
40
41 ### Build XML using Python data structures ###
42
43 class TreeBuilder:
44     """Build an ElementTree.Element instance from an XML tree specification
45     based on nested dictionaries. TODO: describe spec
46     """
47     
48     def __init__(self, spec):
49         "TODO: docstring"
50         self._root = TreeBuilder.build(spec)
51         
52     def to_string(self, encoding='utf-8'):
53         "TODO: docstring"
54         xml = ET.tostring(self._root, encoding)
55         # some etree versions don't always include xml decl
56         # this is a problem with some devices
57         if not xml.startswith('<?xml'):
58             return '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml)
59         else:
60             return xml
61     
62     @property
63     def tree(self):
64         "TODO: docstring"
65         return self._root
66     
67     @staticmethod
68     def build(spec):
69         "TODO: docstring"
70         if spec.has_key('tag'):
71             ele = ET.Element(spec.get('tag'), spec.get('attributes', {}))
72             ele.text = spec.get('text', '')
73             children = spec.get('children', [])
74             if isinstance(children, dict):
75                 children = [children]
76             for child in children:
77                 ele.append(TreeBuilder.build(child))
78             return ele
79         elif spec.has_key('comment'):
80             return ET.Comment(spec.get('comment'))
81         else:
82             raise ValueError('Invalid tree spec')