1 # Copyright 2009 Shikhar Bhushan
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 from xml.etree import cElementTree as ET
20 ### Namespace-related ###
22 BASE_NS = 'urn:ietf:params:xml:ns:netconf:base:1.0'
24 # cisco returns incorrectly namespaced xml
25 CISCO_BS = 'urn:ietf:params:netconf:base:1.0'
28 register_namespace = ET.register_namespace
29 except AttributeError:
30 def register_namespace(prefix, uri):
31 from xml.etree import ElementTree
32 # cElementTree uses ElementTree's _namespace_map, so that's ok
33 ElementTree._namespace_map[uri] = prefix
35 # we'd like BASE_NS to be prefixed as "netconf"
36 register_namespace('netconf', BASE_NS)
38 qualify = lambda tag, ns: '{%s}%s' % (namespace, tag)
40 unqualify = lambda tag: tag[tag.rfind('}')+1:]
43 ### Build XML using Python data structures :-) ###
46 """Build an ElementTree.Element instance from an XML tree specification
47 based on nested dictionaries. TODO: describe spec
50 def __init__(self, spec):
52 self._root = TreeBuilder.build(spec)
54 def to_string(self, encoding='utf-8'):
56 xml = ET.tostring(self._root, encoding)
57 # some etree versions don't always include xml decl
58 # this is a problem with some devices
59 if not xml.startswith('<?xml'):
60 return '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml)
72 if spec.has_key('tag'):
73 ele = ET.Element(spec.get('tag'), spec.get('attributes', {}))
74 ele.text = spec.get('text', '')
75 children = spec.get('children', [])
76 if isinstance(children, dict):
78 for child in children:
79 ele.append(TreeBuilder.build(child))
81 elif spec.has_key('comment'):
82 return ET.Comment(spec.get('comment'))
84 raise ValueError('Invalid tree spec')