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
19 ### Namespace-related ###
21 BASE_NS = 'urn:ietf:params:xml:ns:netconf:base:1.0'
23 # cisco returns incorrectly namespaced xml
24 CISCO_BS = 'urn:ietf:params:netconf:base:1.0'
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
34 # we'd like BASE_NS to be prefixed as "netconf"
35 register_namespace('netconf', BASE_NS)
37 qualify = lambda tag, ns: '{%s}%s' % (namespace, tag)
39 unqualify = lambda tag: tag[tag.rfind('}')+1:]
41 ### Build XML using Python data structures ###
44 """Build an ElementTree.Element instance from an XML tree specification
45 based on nested dictionaries. TODO: describe spec
48 def __init__(self, spec):
50 self._root = TreeBuilder.build(spec)
52 def to_string(self, encoding='utf-8'):
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)
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):
76 for child in children:
77 ele.append(TreeBuilder.build(child))
79 elif spec.has_key('comment'):
80 return ET.Comment(spec.get('comment'))
82 raise ValueError('Invalid tree spec')