Statistics
| Branch: | Tag: | Revision:

root / ncclient / xml_.py @ dd8b8dd7

History | View | Annotate | Download (4.2 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 a7cb58ce Shikhar Bhushan
16 dd8b8dd7 Shikhar Bhushan
"""The :mod:`xml_` module provides methods for creating, parsing, and dealing
17 dd8b8dd7 Shikhar Bhushan
with XML. It uses :mod:`~xml.etree.ElementTree`."""
18 a7cb58ce Shikhar Bhushan
19 4de03d63 Shikhar Bhushan
from cStringIO import StringIO
20 94dd4342 Shikhar Bhushan
from xml.etree import cElementTree as ET
21 94dd4342 Shikhar Bhushan
22 ebf2bbc6 Shikhar Bhushan
from ncclient import NCClientError
23 ebf2bbc6 Shikhar Bhushan
24 9667bcb2 Shikhar Bhushan
class XMLError(NCClientError):
25 a14c36f9 Shikhar Bhushan
    pass
26 bf31e33e Shikhar Bhushan
27 65c6a607 Shikhar Bhushan
### Namespace-related
28 94dd4342 Shikhar Bhushan
29 57b5f922 Shikhar Bhushan
#: Base NETCONF namespace
30 dd225c7a Shikhar Bhushan
BASE_NS_1_0 = 'urn:ietf:params:xml:ns:netconf:base:1.0'
31 dd8b8dd7 Shikhar Bhushan
#: Namespace for Tail-f core data model
32 408abf6d Shikhar Bhushan
TAILF_AAA_1_1 = 'http://tail-f.com/ns/aaa/1.1'
33 dd8b8dd7 Shikhar Bhushan
#: Namespace for Tail-f execd data model
34 408abf6d Shikhar Bhushan
TAILF_EXECD_1_1 = 'http://tail-f.com/ns/execd/1.1'
35 dd8b8dd7 Shikhar Bhushan
#: Namespace for Cisco data model
36 dd225c7a Shikhar Bhushan
CISCO_CPI_1_0 = 'http://www.cisco.com/cpi_10/schema'
37 dd8b8dd7 Shikhar Bhushan
#: Namespace for Flowmon data model
38 dd225c7a Shikhar Bhushan
FLOWMON_1_0 = 'http://www.liberouter.org/ns/netopeer/flowmon/1.0'
39 94dd4342 Shikhar Bhushan
40 94dd4342 Shikhar Bhushan
try:
41 94dd4342 Shikhar Bhushan
    register_namespace = ET.register_namespace
42 94dd4342 Shikhar Bhushan
except AttributeError:
43 94dd4342 Shikhar Bhushan
    def register_namespace(prefix, uri):
44 94dd4342 Shikhar Bhushan
        from xml.etree import ElementTree
45 94dd4342 Shikhar Bhushan
        # cElementTree uses ElementTree's _namespace_map, so that's ok
46 94dd4342 Shikhar Bhushan
        ElementTree._namespace_map[uri] = prefix
47 94dd4342 Shikhar Bhushan
48 dd225c7a Shikhar Bhushan
prefix_map = {
49 dd225c7a Shikhar Bhushan
    BASE_NS_1_0: 'nc',
50 dd225c7a Shikhar Bhushan
    TAILF_AAA_1_1: 'aaa',
51 dd225c7a Shikhar Bhushan
    TAILF_EXECD_1_1: 'execd',
52 dd225c7a Shikhar Bhushan
    CISCO_CPI_1_0: 'cpi',
53 dd225c7a Shikhar Bhushan
    FLOWMON_1_0: 'fm',
54 dd225c7a Shikhar Bhushan
}
55 57b5f922 Shikhar Bhushan
56 dd225c7a Shikhar Bhushan
for (ns, pre) in prefix_map.items():
57 dd225c7a Shikhar Bhushan
    register_namespace(pre, ns)
58 94dd4342 Shikhar Bhushan
59 dd225c7a Shikhar Bhushan
qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else '{%s}%s' % (ns, tag)
60 bf31e33e Shikhar Bhushan
61 9667bcb2 Shikhar Bhushan
#unqualify = lambda tag: tag[tag.rfind('}')+1:]
62 d771dffc Shikhar Bhushan
63 9667bcb2 Shikhar Bhushan
def to_xml(ele, encoding="UTF-8"):
64 dd8b8dd7 Shikhar Bhushan
    """Convert an :class:`~xml.etree.ElementTree.Element` to XML.
65 9667bcb2 Shikhar Bhushan
    
66 dd8b8dd7 Shikhar Bhushan
    :arg ele: the :class:`~xml.etree.ElementTree.Element`
67 9667bcb2 Shikhar Bhushan
    :arg encoding: character encoding
68 9667bcb2 Shikhar Bhushan
    :rtype: :obj:`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 dd8b8dd7 Shikhar Bhushan
    """Convert XML to :class:`~xml.etree.ElementTree.Element`.
75 9667bcb2 Shikhar Bhushan
    
76 9667bcb2 Shikhar Bhushan
    :type xml: :obj:`string`
77 9667bcb2 Shikhar Bhushan
    :rtype: :class:`~xml.etree.ElementTree.Element`
78 9667bcb2 Shikhar Bhushan
    """
79 9667bcb2 Shikhar Bhushan
    return x if iselement(x) else ET.fromstring(x)
80 9667bcb2 Shikhar Bhushan
81 9667bcb2 Shikhar Bhushan
iselement = ET.iselement
82 d771dffc Shikhar Bhushan
83 d771dffc Shikhar Bhushan
def parse_root(raw):
84 614a698d Shikhar Bhushan
    """Efficiently parses the root element of an XML document.
85 4f650d54 Shikhar Bhushan

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