Revision e3b66e4b ncclient/xml_.py
b/ncclient/xml_.py | ||
---|---|---|
12 | 12 |
# See the License for the specific language governing permissions and |
13 | 13 |
# limitations under the License. |
14 | 14 |
|
15 |
|
|
16 | 15 |
"Methods for creating, parsing, and dealing with XML and ElementTree objects." |
17 | 16 |
|
18 | 17 |
from cStringIO import StringIO |
... | ... | |
25 | 24 |
### Namespace-related |
26 | 25 |
|
27 | 26 |
#: Base NETCONF namespace |
28 |
BASE_NS_1_0 = 'urn:ietf:params:xml:ns:netconf:base:1.0'
|
|
27 |
BASE_NS_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0"
|
|
29 | 28 |
#: Namespace for Tail-f core data model |
30 |
TAILF_AAA_1_1 = 'http://tail-f.com/ns/aaa/1.1'
|
|
29 |
TAILF_AAA_1_1 = "http://tail-f.com/ns/aaa/1.1"
|
|
31 | 30 |
#: Namespace for Tail-f execd data model |
32 |
TAILF_EXECD_1_1 = 'http://tail-f.com/ns/execd/1.1'
|
|
31 |
TAILF_EXECD_1_1 = "http://tail-f.com/ns/execd/1.1"
|
|
33 | 32 |
#: Namespace for Cisco data model |
34 |
CISCO_CPI_1_0 = 'http://www.cisco.com/cpi_10/schema'
|
|
33 |
CISCO_CPI_1_0 = "http://www.cisco.com/cpi_10/schema"
|
|
35 | 34 |
#: Namespace for Flowmon data model |
36 |
FLOWMON_1_0 = 'http://www.liberouter.org/ns/netopeer/flowmon/1.0'
|
|
35 |
FLOWMON_1_0 = "http://www.liberouter.org/ns/netopeer/flowmon/1.0"
|
|
37 | 36 |
|
38 | 37 |
try: |
39 | 38 |
register_namespace = ET.register_namespace |
... | ... | |
43 | 42 |
# cElementTree uses ElementTree's _namespace_map, so that's ok |
44 | 43 |
ElementTree._namespace_map[uri] = prefix |
45 | 44 |
|
46 |
prefix_map = {
|
|
45 |
for (ns, pre) in {
|
|
47 | 46 |
BASE_NS_1_0: 'nc', |
48 | 47 |
TAILF_AAA_1_1: 'aaa', |
49 | 48 |
TAILF_EXECD_1_1: 'execd', |
50 | 49 |
CISCO_CPI_1_0: 'cpi', |
51 | 50 |
FLOWMON_1_0: 'fm', |
52 |
} |
|
51 |
}.items(): register_namespace(pre, ns)
|
|
53 | 52 |
|
54 |
for (ns, pre) in prefix_map.items():
|
|
55 |
register_namespace(pre, ns)
|
|
53 |
qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else "{%s}%s" % (ns, tag)
|
|
54 |
"""Qualify a tag name with a namespace, in :mod:`~xml.etree.ElementTree` fashion i.e. *{namespace}tagname*.
|
|
56 | 55 |
|
57 |
qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else '{%s}%s' % (ns, tag) |
|
56 |
:arg tag: name of the tag |
|
57 |
:type arg: `string` |
|
58 | 58 |
|
59 |
#unqualify = lambda tag: tag[tag.rfind('}')+1:] |
|
59 |
:arg ns: namespace to qualify with |
|
60 |
:type ns: `string` |
|
61 |
""" |
|
60 | 62 |
|
61 | 63 |
def to_xml(ele, encoding="UTF-8"): |
62 |
"""Convert an :class:`~xml.etree.ElementTree.Element` to XML.
|
|
64 |
"""Convert an `~xml.etree.ElementTree.Element` to XML. |
|
63 | 65 |
|
64 |
:arg ele: the :class:`~xml.etree.ElementTree.Element`
|
|
66 |
:arg ele: the `~xml.etree.ElementTree.Element` |
|
65 | 67 |
:arg encoding: character encoding |
66 |
:rtype: :obj:`string`
|
|
68 |
:rtype: `string` |
|
67 | 69 |
""" |
68 | 70 |
xml = ET.tostring(ele, encoding) |
69 | 71 |
return xml if xml.startswith('<?xml') else '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml) |
70 | 72 |
|
71 | 73 |
def to_ele(x): |
72 |
"""Convert XML to :class:`~xml.etree.ElementTree.Element`. |
|
74 |
"""Convert XML to `~xml.etree.ElementTree.Element`. If passed an |
|
75 |
`~xml.etree.ElementTree.Element` simply returns that. |
|
73 | 76 |
|
74 |
:type xml: :obj:`string` |
|
75 |
:rtype: :class:`~xml.etree.ElementTree.Element` |
|
77 |
:arg x: the XML document or element |
|
78 |
:type x: `string` or `~xml.etree.ElementTree.Element` |
|
79 |
:rtype: `~xml.etree.ElementTree.Element` |
|
76 | 80 |
""" |
77 |
return x if iselement(x) else ET.fromstring(x) |
|
78 |
|
|
79 |
iselement = ET.iselement |
|
81 |
return x if ET.iselement(x) else ET.fromstring(x) |
|
80 | 82 |
|
81 | 83 |
def parse_root(raw): |
82 | 84 |
"""Efficiently parses the root element of an XML document. |
83 | 85 |
|
84 | 86 |
:arg raw: XML document |
85 |
:returns: a tuple of `(tag, attrib)`, where *tag* is the (qualified) |
|
86 |
name of the element and *attrib* is a dictionary of its attributes. |
|
87 |
:returns: a tuple of ``(tag, attrib)``, where *tag* is the (qualified) name of the element and *attrib* is a dictionary of its attributes. |
|
87 | 88 |
:rtype: `tuple` |
88 | 89 |
""" |
89 | 90 |
fp = StringIO(raw) |
... | ... | |
91 | 92 |
return (element.tag, element.attrib) |
92 | 93 |
|
93 | 94 |
def validated_element(x, tags=None, attrs=None): |
94 |
"Checks if the root element of an XML document or Element meets the supplied criteria." |
|
95 |
"""Checks if the root element of an XML document or Element meets the supplied criteria. |
|
96 |
|
|
97 |
:arg tags: allowable tag name or sequence of allowable alternatives |
|
98 |
:type tags: `string` or sequence of strings |
|
99 |
|
|
100 |
:arg attrs: list of required attributes, each of which may be a sequence of several allowable alternatives |
|
101 |
:type attrs: sequence of strings or sequence of sequences of strings |
|
102 |
|
|
103 |
:raises: `XMLError` if the requirements are not met |
|
104 |
""" |
|
95 | 105 |
ele = to_ele(x) |
96 | 106 |
if tags: |
97 | 107 |
if isinstance(tags, basestring): |
... | ... | |
108 | 118 |
raise XMLError("Element [%s] does not have required attributes" % ele.tag) |
109 | 119 |
return ele |
110 | 120 |
|
111 |
|
|
112 | 121 |
new_ele = lambda tag, attrs={}, **extra: ET.Element(tag, attrs, **extra) |
113 | 122 |
|
114 | 123 |
sub_ele = lambda parent, tag, attrs={}, **extra: ET.SubElement(parent, tag, attrs, **extra) |
Also available in: Unified diff