Passed
Pull Request — master (#69)
by
unknown
01:10
created

nextcloud.common.simplexml.SimpleXml._tostring()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
# -*- coding: utf-8 -*-
2
"""
3
XML builder/parser
4
"""
5
import xml.etree.ElementTree as ET
6
from nextcloud.compat import encode_string
7
from nextcloud.common.properties import NAMESPACES_MAP
8
9
10
def _prepare_xml_parsing(string):
11
    return encode_string(string)
12
13
14
class SimpleXml:
15
    """
16
    Static class to build and parse XML datas
17
    """
18
    namespaces_map = NAMESPACES_MAP
19
    supported_field_types = list(NAMESPACES_MAP.keys())
20
    xml_namespaces_map = {'xmlns:' + k: v for k, v in NAMESPACES_MAP.items()}
21
22
    @classmethod
23
    def _to_fields_list(cls, fields_hash):
24
        props_xml = []
25
        for field_type in fields_hash:
26
            if field_type not in cls.supported_field_types:
27
                pass
28
            else:
29
                for field in fields_hash[field_type]:
30
                    props_xml.append('{}:{}'.format(field_type, field))
31
32
        return props_xml
33
34
    @classmethod
35
    def _to_field_vals_list(cls, fields_hash):
36
        props_xml = {}
37
        for field_type in fields_hash:
38
            if field_type not in cls.supported_field_types:
39
                pass
40
            else:
41
                vals = fields_hash[field_type]
42
                for field in vals:
43
                    props_xml['{}:{}'.format(field_type, field)] = vals[field]
44
45
        return props_xml
46
47
    @classmethod
48
    def _tostring(cls, root):
49
        return ET.tostring(root)
50
51
    @classmethod
52
    def fromstring(cls, data):
53
        """
54
        Fetch xml.etree.ElementTree for input data
55
56
        :param data:   raw xml data
57
        :returns:      :class:xml.etree.ElementTree
58
        """
59
        return ET.fromstring(_prepare_xml_parsing(data))
60
61
    @classmethod
62
    def build_propfind_datas(cls, instr=None, filter_rules=None, fields=None):
63
        """
64
        Build XML datas for a PROPFIND querry.
65
66
        :param instr:        http instruction (default: PROPFIND)
67
        :param filter_rules: a dict containing filter rules separated by
68
                             namespace. e.g. {'oc': {'favorite': 1}}
69
        :param fields:       a dict containing fields separated by namespace
70
                             e.g. {'oc': ['id']}
71
        :returns:            xml data (string)
72
        """
73
        if not instr:
74
            instr = 'd:propfind'
75
76
        root = ET.Element(instr, cls.xml_namespaces_map)
77
        props = cls._to_fields_list(fields or {})
78
        if props:
79
            prop_group = ET.SubElement(root, 'd:prop')
80
            for prop in props:
81
                ET.SubElement(prop_group, prop)
82
83
        rules = cls._to_field_vals_list(filter_rules or {})
84
        if rules:
85
            rule_group = ET.SubElement(root, 'oc:filter-rules')
86
            for k in rules:
87
                rule = ET.SubElement(rule_group, k)
88
                val = rules[k]
89
                if isinstance(val, int):
90
                    val = str(val)
91
                rule.text = val
92
93
        return cls._tostring(root)
94
95
    @classmethod
96
    def build_propupdate_datas(cls, values):
97
        """
98
        Build XML datas for a PROPUPDATE querry.
99
100
        :param values:       a dict containing values separated by namespace
101
                             e.g. {'oc': {'favorite': 1}}
102
        :returns:            xml data (string)
103
        """
104
        root = ET.Element('d:propertyupdate', cls.xml_namespaces_map)
105
        vals = cls._to_field_vals_list(values)
106
        if vals:
107
            set_group = ET.SubElement(root, 'd:set')
108
            val_group = ET.SubElement(set_group, 'd:prop')
109
            for k in vals:
110
                val = ET.SubElement(val_group, k)
111
                val.text = vals[k]
112
113
        return cls._tostring(root)
114