Statistics
| Branch: | Tag: | Revision:

root / ncclient / xml_.py @ b2d60e49

History | View | Annotate | Download (4.3 kB)

1 94dd4342 Shikhar Bhushan
# Copyright 2009 Shikhar Bhushan
2 94dd4342 Shikhar Bhushan
#
3 94dd4342 Shikhar Bhushan
# Licensed under the Apache License, Version 2.0 (the "License");
4 94dd4342 Shikhar Bhushan
# you may not use this file except in compliance with the License.
5 94dd4342 Shikhar Bhushan
# You may obtain a copy of the License at
6 94dd4342 Shikhar Bhushan
#
7 94dd4342 Shikhar Bhushan
#    http://www.apache.org/licenses/LICENSE-2.0
8 94dd4342 Shikhar Bhushan
#
9 94dd4342 Shikhar Bhushan
# Unless required by applicable law or agreed to in writing, software
10 94dd4342 Shikhar Bhushan
# distributed under the License is distributed on an "AS IS" BASIS,
11 94dd4342 Shikhar Bhushan
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 94dd4342 Shikhar Bhushan
# See the License for the specific language governing permissions and
13 94dd4342 Shikhar Bhushan
# limitations under the License.
14 94dd4342 Shikhar Bhushan
15 bfcf8aea Shikhar Bhushan
"Methods for creating, parsing, and dealing with XML and ElementTree objects."
16 a7cb58ce Shikhar Bhushan
17 4de03d63 Shikhar Bhushan
from cStringIO import StringIO
18 94dd4342 Shikhar Bhushan
from xml.etree import cElementTree as ET
19 94dd4342 Shikhar Bhushan
20 ebf2bbc6 Shikhar Bhushan
from ncclient import NCClientError
21 ebf2bbc6 Shikhar Bhushan
22 bfcf8aea Shikhar Bhushan
class XMLError(NCClientError): pass
23 bf31e33e Shikhar Bhushan
24 65c6a607 Shikhar Bhushan
### Namespace-related
25 94dd4342 Shikhar Bhushan
26 57b5f922 Shikhar Bhushan
#: Base NETCONF namespace
27 e3b66e4b Shikhar Bhushan
BASE_NS_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0"
28 dd8b8dd7 Shikhar Bhushan
#: Namespace for Tail-f core data model
29 e3b66e4b Shikhar Bhushan
TAILF_AAA_1_1 = "http://tail-f.com/ns/aaa/1.1"
30 dd8b8dd7 Shikhar Bhushan
#: Namespace for Tail-f execd data model
31 e3b66e4b Shikhar Bhushan
TAILF_EXECD_1_1 = "http://tail-f.com/ns/execd/1.1"
32 dd8b8dd7 Shikhar Bhushan
#: Namespace for Cisco data model
33 e3b66e4b Shikhar Bhushan
CISCO_CPI_1_0 = "http://www.cisco.com/cpi_10/schema"
34 dd8b8dd7 Shikhar Bhushan
#: Namespace for Flowmon data model
35 e3b66e4b Shikhar Bhushan
FLOWMON_1_0 = "http://www.liberouter.org/ns/netopeer/flowmon/1.0"
36 94dd4342 Shikhar Bhushan
37 94dd4342 Shikhar Bhushan
try:
38 94dd4342 Shikhar Bhushan
    register_namespace = ET.register_namespace
39 94dd4342 Shikhar Bhushan
except AttributeError:
40 94dd4342 Shikhar Bhushan
    def register_namespace(prefix, uri):
41 94dd4342 Shikhar Bhushan
        from xml.etree import ElementTree
42 94dd4342 Shikhar Bhushan
        # cElementTree uses ElementTree's _namespace_map, so that's ok
43 94dd4342 Shikhar Bhushan
        ElementTree._namespace_map[uri] = prefix
44 94dd4342 Shikhar Bhushan
45 e3b66e4b Shikhar Bhushan
for (ns, pre) in {
46 dd225c7a Shikhar Bhushan
    BASE_NS_1_0: 'nc',
47 dd225c7a Shikhar Bhushan
    TAILF_AAA_1_1: 'aaa',
48 dd225c7a Shikhar Bhushan
    TAILF_EXECD_1_1: 'execd',
49 dd225c7a Shikhar Bhushan
    CISCO_CPI_1_0: 'cpi',
50 dd225c7a Shikhar Bhushan
    FLOWMON_1_0: 'fm',
51 e3b66e4b Shikhar Bhushan
}.items(): register_namespace(pre, ns)
52 57b5f922 Shikhar Bhushan
53 e3b66e4b Shikhar Bhushan
qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else "{%s}%s" % (ns, tag)
54 e3b66e4b Shikhar Bhushan
"""Qualify a tag name with a namespace, in :mod:`~xml.etree.ElementTree` fashion i.e. *{namespace}tagname*.
55 94dd4342 Shikhar Bhushan

56 e3b66e4b Shikhar Bhushan
:arg tag: name of the tag
57 e3b66e4b Shikhar Bhushan
:type arg: `string`
58 bf31e33e Shikhar Bhushan

59 e3b66e4b Shikhar Bhushan
:arg ns: namespace to qualify with
60 e3b66e4b Shikhar Bhushan
:type ns: `string`
61 e3b66e4b Shikhar Bhushan
"""
62 d771dffc Shikhar Bhushan
63 9667bcb2 Shikhar Bhushan
def to_xml(ele, encoding="UTF-8"):
64 e3b66e4b Shikhar Bhushan
    """Convert an `~xml.etree.ElementTree.Element` to XML.
65 9667bcb2 Shikhar Bhushan
    
66 e3b66e4b Shikhar Bhushan
    :arg ele: the `~xml.etree.ElementTree.Element`
67 9667bcb2 Shikhar Bhushan
    :arg encoding: character encoding
68 e3b66e4b Shikhar Bhushan
    :rtype: `string`
69 d771dffc Shikhar Bhushan
    """
70 9667bcb2 Shikhar Bhushan
    xml = ET.tostring(ele, encoding)
71 9667bcb2 Shikhar Bhushan
    return xml if xml.startswith('<?xml') else '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml)
72 9667bcb2 Shikhar Bhushan
73 9667bcb2 Shikhar Bhushan
def to_ele(x):
74 b2d60e49 Shikhar Bhushan
    """Convert XML to `~xml.etree.ElementTree.Element`. If passed an `~xml.etree.ElementTree.Element` simply returns that.
75 9667bcb2 Shikhar Bhushan
    
76 e3b66e4b Shikhar Bhushan
    :arg x: the XML document or element
77 e3b66e4b Shikhar Bhushan
    :type x: `string` or `~xml.etree.ElementTree.Element`
78 e3b66e4b Shikhar Bhushan
    :rtype: `~xml.etree.ElementTree.Element`
79 9667bcb2 Shikhar Bhushan
    """
80 e3b66e4b Shikhar Bhushan
    return x if ET.iselement(x) else ET.fromstring(x)
81 d771dffc Shikhar Bhushan
82 d771dffc Shikhar Bhushan
def parse_root(raw):
83 614a698d Shikhar Bhushan
    """Efficiently parses the root element of an XML document.
84 4f650d54 Shikhar Bhushan

85 216bb34c Shikhar Bhushan
    :arg raw: XML document
86 e3b66e4b Shikhar Bhushan
    :returns: a tuple of ``(tag, attrib)``, where *tag* is the (qualified) name of the element and *attrib* is a dictionary of its attributes.
87 216bb34c Shikhar Bhushan
    :rtype: `tuple`
88 0cdb8b3c Shikhar Bhushan
    """
89 9667bcb2 Shikhar Bhushan
    fp = StringIO(raw)
90 d771dffc Shikhar Bhushan
    for event, element in ET.iterparse(fp, events=('start',)):
91 d771dffc Shikhar Bhushan
        return (element.tag, element.attrib)
92 d771dffc Shikhar Bhushan
93 9667bcb2 Shikhar Bhushan
def validated_element(x, tags=None, attrs=None):
94 e3b66e4b Shikhar Bhushan
    """Checks if the root element of an XML document or Element meets the supplied criteria.
95 e3b66e4b Shikhar Bhushan
    
96 e3b66e4b Shikhar Bhushan
    :arg tags: allowable tag name or sequence of allowable alternatives
97 e3b66e4b Shikhar Bhushan
    :type tags: `string` or sequence of strings
98 e3b66e4b Shikhar Bhushan
    
99 e3b66e4b Shikhar Bhushan
    :arg attrs: list of required attributes, each of which may be a sequence of several allowable alternatives
100 e3b66e4b Shikhar Bhushan
    :type attrs: sequence of strings or sequence of sequences of strings
101 e3b66e4b Shikhar Bhushan
    
102 e3b66e4b Shikhar Bhushan
    :raises: `XMLError` if the requirements are not met
103 e3b66e4b Shikhar Bhushan
    """
104 9667bcb2 Shikhar Bhushan
    ele = to_ele(x)
105 0b7d3b31 Shikhar Bhushan
    if tags:
106 0b7d3b31 Shikhar Bhushan
        if isinstance(tags, basestring):
107 0b7d3b31 Shikhar Bhushan
            tags = [tags]
108 614a698d Shikhar Bhushan
        if ele.tag not in tags:
109 9667bcb2 Shikhar Bhushan
            raise XMLError("Element [%s] does not meet requirement" % ele.tag)
110 614a698d Shikhar Bhushan
    if attrs:
111 d771dffc Shikhar Bhushan
        for req in attrs:
112 614a698d Shikhar Bhushan
            if isinstance(req, basestring): req = [req]
113 614a698d Shikhar Bhushan
            for alt in req:
114 614a698d Shikhar Bhushan
                if alt in ele.attrib:
115 d771dffc Shikhar Bhushan
                    break
116 d771dffc Shikhar Bhushan
            else:
117 9667bcb2 Shikhar Bhushan
                raise XMLError("Element [%s] does not have required attributes" % ele.tag)
118 d771dffc Shikhar Bhushan
    return ele
119 9667bcb2 Shikhar Bhushan
120 bfcf8aea Shikhar Bhushan
new_ele = lambda tag, attrs={}, **extra: ET.Element(tag, attrs, **extra)
121 bfcf8aea Shikhar Bhushan
122 bfcf8aea Shikhar Bhushan
sub_ele = lambda parent, tag, attrs={}, **extra: ET.SubElement(parent, tag, attrs, **extra)