Revision c2a5b930 ncclient/rpc/reply.py

b/ncclient/rpc/reply.py
16 16

  
17 17
from xml.etree import cElementTree as ET
18 18

  
19
from ncclient.content import multiqualify as _
19
from ncclient.content import namespaced_find
20 20
from ncclient.content import unqualify as __
21 21

  
22 22
import logging
......
36 36
        return self._raw
37 37
    
38 38
    def parse(self):
39
        if self._parsed:
40
            return
41
        
39
        if self._parsed: return
42 40
        root = self._root = ET.fromstring(self._raw) # <rpc-reply> element
43
        
44
        if __(root.tag) != 'rpc-reply':
45
            raise ValueError('Root element is not RPC reply')
46
        
47
        ok = False
48 41
        # per rfc 4741 an <ok/> tag is sent when there are no errors or warnings
49
        oktags = _('ok')
50
        for oktag in oktags:
51
            if root.find(oktag) is not None:
52
                logger.debug('parsed [%s]' % oktag)
53
                break
54
        else:
55
            # create RPCError objects from <rpc-error> elements
56
            errtags = _('rpc-error')
57
            for errtag in errtags:
58
                for err in root.getiterator(errtag): # a particular <rpc-error>
59
                    logger.debug('parsed [%s]' % errtag)
42
        ok = namespaced_find(root, 'ok')
43
        if ok is not None:
44
            logger.debug('parsed [%s]' % ok.tag)
45
        else: # create RPCError objects from <rpc-error> elements
46
            error = namespaced_find(root, 'rpc-error')
47
            if error is not None:
48
                logger.debug('parsed [%s]' % error.tag)
49
                for err in root.getiterator(error.tag):
50
                    # process a particular <rpc-error>
60 51
                    d = {}
61 52
                    for err_detail in err.getchildren(): # <error-type> etc..
62 53
                        tag = __(err_detail.tag)
63 54
                        d[tag] = (err_detail.text.strip() if tag != 'error-info'
64 55
                                  else ET.tostring(err_detail, 'utf-8'))
65 56
                    self._errors.append(RPCError(d))
66
                if self._errors:
67
                    break
68
        
57
        self._parsing_hook(root)
69 58
        self._parsed = True
70 59
    
71
    @property
72
    def content_xml(self):
73
        '<rpc-reply> subtree'
74
        if not self._parsed: self.parse()
75
        return ''.join([ET.tostring(ele) for ele in self._root.getchildren()])
60
    def extract_subtree_xml(self):
61
        return ''.join([ET.tostring(ele)
62
                        for ele in ET.fromstring(self.xml).getchildren()])
76 63
    
77 64
    @property
78
    def content_element(self):
79
        if not self._parsed: self.parse()
80
        return self._root.getchildren()
81
    
82
    @property
83
    def root_xml(self):
65
    def xml(self):
84 66
        '<rpc-reply> as returned'
85 67
        return self._raw
86 68
    
87 69
    @property
88
    def root_element(self):
89
        if not self._parsed: self.parse()
90
        return self._root
91
    
92
    @property
93 70
    def ok(self):
94 71
        if not self._parsed: self.parse()
95 72
        return not self._errors # empty list => false

Also available in: Unified diff