Statistics
| Branch: | Tag: | Revision:

root / ncclient / xml_.py @ bfcf8aea

History | View | Annotate | Download (3.7 kB)

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

    
16
"Methods for creating, parsing, and dealing with XML and ElementTree objects."
17

    
18
from cStringIO import StringIO
19
from xml.etree import cElementTree as ET
20

    
21
from ncclient import NCClientError
22

    
23
class XMLError(NCClientError): pass
24

    
25
### Namespace-related
26

    
27
#: Base NETCONF namespace
28
BASE_NS_1_0 = 'urn:ietf:params:xml:ns:netconf:base:1.0'
29
#: Namespace for Tail-f core data model
30
TAILF_AAA_1_1 = 'http://tail-f.com/ns/aaa/1.1'
31
#: Namespace for Tail-f execd data model
32
TAILF_EXECD_1_1 = 'http://tail-f.com/ns/execd/1.1'
33
#: Namespace for Cisco data model
34
CISCO_CPI_1_0 = 'http://www.cisco.com/cpi_10/schema'
35
#: Namespace for Flowmon data model
36
FLOWMON_1_0 = 'http://www.liberouter.org/ns/netopeer/flowmon/1.0'
37

    
38
try:
39
    register_namespace = ET.register_namespace
40
except AttributeError:
41
    def register_namespace(prefix, uri):
42
        from xml.etree import ElementTree
43
        # cElementTree uses ElementTree's _namespace_map, so that's ok
44
        ElementTree._namespace_map[uri] = prefix
45

    
46
prefix_map = {
47
    BASE_NS_1_0: 'nc',
48
    TAILF_AAA_1_1: 'aaa',
49
    TAILF_EXECD_1_1: 'execd',
50
    CISCO_CPI_1_0: 'cpi',
51
    FLOWMON_1_0: 'fm',
52
}
53

    
54
for (ns, pre) in prefix_map.items():
55
    register_namespace(pre, ns)
56

    
57
qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else '{%s}%s' % (ns, tag)
58

    
59
#unqualify = lambda tag: tag[tag.rfind('}')+1:]
60

    
61
def to_xml(ele, encoding="UTF-8"):
62
    """Convert an :class:`~xml.etree.ElementTree.Element` to XML.
63
    
64
    :arg ele: the :class:`~xml.etree.ElementTree.Element`
65
    :arg encoding: character encoding
66
    :rtype: :obj:`string`
67
    """
68
    xml = ET.tostring(ele, encoding)
69
    return xml if xml.startswith('<?xml') else '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml)
70

    
71
def to_ele(x):
72
    """Convert XML to :class:`~xml.etree.ElementTree.Element`.
73
    
74
    :type xml: :obj:`string`
75
    :rtype: :class:`~xml.etree.ElementTree.Element`
76
    """
77
    return x if iselement(x) else ET.fromstring(x)
78

    
79
iselement = ET.iselement
80

    
81
def parse_root(raw):
82
    """Efficiently parses the root element of an XML document.
83

84
    :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
    :rtype: `tuple`
88
    """
89
    fp = StringIO(raw)
90
    for event, element in ET.iterparse(fp, events=('start',)):
91
        return (element.tag, element.attrib)
92

    
93
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
    ele = to_ele(x)
96
    if tags:
97
        if isinstance(tags, basestring):
98
            tags = [tags]
99
        if ele.tag not in tags:
100
            raise XMLError("Element [%s] does not meet requirement" % ele.tag)
101
    if attrs:
102
        for req in attrs:
103
            if isinstance(req, basestring): req = [req]
104
            for alt in req:
105
                if alt in ele.attrib:
106
                    break
107
            else:
108
                raise XMLError("Element [%s] does not have required attributes" % ele.tag)
109
    return ele
110

    
111

    
112
new_ele = lambda tag, attrs={}, **extra: ET.Element(tag, attrs, **extra)
113

    
114
sub_ele = lambda parent, tag, attrs={}, **extra: ET.SubElement(parent, tag, attrs, **extra)