pysdmx 1.3.0__py3-none-any.whl → 1.4.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pysdmx/__extras_check.py +3 -2
- pysdmx/__init__.py +1 -1
- pysdmx/api/fmr/__init__.py +4 -4
- pysdmx/api/gds/__init__.py +328 -0
- pysdmx/api/qb/gds.py +153 -0
- pysdmx/api/qb/service.py +91 -3
- pysdmx/api/qb/structure.py +1 -0
- pysdmx/api/qb/util.py +1 -0
- pysdmx/io/__init__.py +2 -1
- pysdmx/io/csv/sdmx10/reader/__init__.py +4 -2
- pysdmx/io/csv/sdmx10/writer/__init__.py +15 -2
- pysdmx/io/csv/sdmx20/reader/__init__.py +5 -2
- pysdmx/io/csv/sdmx20/writer/__init__.py +13 -2
- pysdmx/io/format.py +4 -0
- pysdmx/io/input_processor.py +12 -3
- pysdmx/io/json/fusion/messages/core.py +2 -0
- pysdmx/io/json/fusion/messages/report.py +13 -7
- pysdmx/io/json/gds/messages/__init__.py +35 -0
- pysdmx/io/json/gds/messages/agencies.py +41 -0
- pysdmx/io/json/gds/messages/catalog.py +79 -0
- pysdmx/io/json/gds/messages/sdmx_api.py +23 -0
- pysdmx/io/json/gds/messages/services.py +49 -0
- pysdmx/io/json/gds/messages/urn_resolver.py +43 -0
- pysdmx/io/json/gds/reader/__init__.py +12 -0
- pysdmx/io/json/sdmxjson2/messages/__init__.py +12 -4
- pysdmx/io/json/sdmxjson2/messages/agency.py +72 -0
- pysdmx/io/json/sdmxjson2/messages/category.py +22 -29
- pysdmx/io/json/sdmxjson2/messages/code.py +68 -64
- pysdmx/io/json/sdmxjson2/messages/concept.py +9 -18
- pysdmx/io/json/sdmxjson2/messages/constraint.py +2 -13
- pysdmx/io/json/sdmxjson2/messages/core.py +113 -21
- pysdmx/io/json/sdmxjson2/messages/dataflow.py +51 -21
- pysdmx/io/json/sdmxjson2/messages/dsd.py +110 -36
- pysdmx/io/json/sdmxjson2/messages/map.py +61 -49
- pysdmx/io/json/sdmxjson2/messages/pa.py +9 -17
- pysdmx/io/json/sdmxjson2/messages/provider.py +88 -0
- pysdmx/io/json/sdmxjson2/messages/report.py +84 -14
- pysdmx/io/json/sdmxjson2/messages/schema.py +14 -5
- pysdmx/io/json/sdmxjson2/messages/structure.py +105 -36
- pysdmx/io/json/sdmxjson2/messages/vtl.py +42 -96
- pysdmx/io/pd.py +2 -9
- pysdmx/io/reader.py +72 -27
- pysdmx/io/serde.py +11 -0
- pysdmx/io/writer.py +134 -0
- pysdmx/io/xml/{sdmx21/reader/__data_aux.py → __data_aux.py} +9 -2
- pysdmx/io/xml/{sdmx21/reader/__parse_xml.py → __parse_xml.py} +30 -6
- pysdmx/io/xml/__ss_aux_reader.py +96 -0
- pysdmx/io/xml/__structure_aux_reader.py +1174 -0
- pysdmx/io/xml/__structure_aux_writer.py +1233 -0
- pysdmx/io/xml/{sdmx21/__tokens.py → __tokens.py} +33 -1
- pysdmx/io/xml/{sdmx21/writer/__write_aux.py → __write_aux.py} +129 -37
- pysdmx/io/xml/{sdmx21/writer/__write_data_aux.py → __write_data_aux.py} +1 -1
- pysdmx/io/xml/__write_structure_specific_aux.py +254 -0
- pysdmx/io/xml/{sdmx21/reader/doc_validation.py → doc_validation.py} +10 -2
- pysdmx/io/xml/{sdmx21/reader/header.py → header.py} +11 -3
- pysdmx/io/xml/sdmx21/reader/error.py +2 -2
- pysdmx/io/xml/sdmx21/reader/generic.py +12 -8
- pysdmx/io/xml/sdmx21/reader/structure.py +5 -840
- pysdmx/io/xml/sdmx21/reader/structure_specific.py +13 -97
- pysdmx/io/xml/sdmx21/reader/submission.py +2 -2
- pysdmx/io/xml/sdmx21/writer/error.py +1 -1
- pysdmx/io/xml/sdmx21/writer/generic.py +13 -7
- pysdmx/io/xml/sdmx21/writer/structure.py +16 -828
- pysdmx/io/xml/sdmx21/writer/structure_specific.py +13 -238
- pysdmx/io/xml/sdmx30/__init__.py +1 -0
- pysdmx/io/xml/sdmx30/reader/__init__.py +1 -0
- pysdmx/io/xml/sdmx30/reader/structure.py +39 -0
- pysdmx/io/xml/sdmx30/reader/structure_specific.py +39 -0
- pysdmx/io/xml/sdmx30/writer/__init__.py +1 -0
- pysdmx/io/xml/sdmx30/writer/structure.py +67 -0
- pysdmx/io/xml/sdmx30/writer/structure_specific.py +108 -0
- pysdmx/model/__base.py +99 -34
- pysdmx/model/__init__.py +4 -0
- pysdmx/model/category.py +20 -0
- pysdmx/model/code.py +29 -8
- pysdmx/model/concept.py +52 -11
- pysdmx/model/dataflow.py +117 -33
- pysdmx/model/dataset.py +66 -14
- pysdmx/model/gds.py +161 -0
- pysdmx/model/map.py +51 -8
- pysdmx/model/message.py +235 -55
- pysdmx/model/metadata.py +79 -16
- pysdmx/model/submission.py +12 -7
- pysdmx/model/vtl.py +30 -13
- pysdmx/toolkit/__init__.py +1 -1
- pysdmx/toolkit/pd/__init__.py +85 -0
- pysdmx/toolkit/vtl/__init__.py +2 -1
- pysdmx/toolkit/vtl/_validations.py +1 -1
- pysdmx/toolkit/vtl/{generate_vtl_script.py → script_generation.py} +30 -4
- pysdmx/toolkit/vtl/validation.py +119 -0
- pysdmx/util/_model_utils.py +1 -1
- pysdmx-1.4.0rc1.dist-info/METADATA +119 -0
- pysdmx-1.4.0rc1.dist-info/RECORD +140 -0
- pysdmx/io/json/sdmxjson2/messages/org.py +0 -140
- pysdmx/toolkit/vtl/model_validations.py +0 -50
- pysdmx-1.3.0.dist-info/METADATA +0 -76
- pysdmx-1.3.0.dist-info/RECORD +0 -116
- /pysdmx/io/xml/{sdmx21/writer/config.py → config.py} +0 -0
- {pysdmx-1.3.0.dist-info → pysdmx-1.4.0rc1.dist-info}/LICENSE +0 -0
- {pysdmx-1.3.0.dist-info → pysdmx-1.4.0rc1.dist-info}/WHEEL +0 -0
|
@@ -1,856 +1,21 @@
|
|
|
1
1
|
"""Parsers for reading metadata."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from typing import Any, Callable, Dict, List, Optional, Sequence, Union
|
|
5
|
-
|
|
6
|
-
from msgspec import Struct
|
|
3
|
+
from typing import Sequence, Union
|
|
7
4
|
|
|
8
5
|
from pysdmx.errors import Invalid
|
|
9
|
-
from pysdmx.io.xml.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
AGENCY_ID,
|
|
13
|
-
ALIAS_LOW,
|
|
14
|
-
ANNOTATION,
|
|
15
|
-
ANNOTATION_TEXT,
|
|
16
|
-
ANNOTATION_TITLE,
|
|
17
|
-
ANNOTATION_TYPE,
|
|
18
|
-
ANNOTATION_URL,
|
|
19
|
-
ANNOTATIONS,
|
|
20
|
-
AS_STATUS,
|
|
21
|
-
ATT,
|
|
22
|
-
ATT_LIST,
|
|
23
|
-
ATT_LVL,
|
|
24
|
-
ATT_REL,
|
|
25
|
-
CL,
|
|
26
|
-
CLASS,
|
|
27
|
-
CLS,
|
|
28
|
-
CODE,
|
|
29
|
-
CODES_LOW,
|
|
30
|
-
COMPS,
|
|
31
|
-
CON,
|
|
32
|
-
CON_ID,
|
|
33
|
-
CON_LOW,
|
|
34
|
-
CON_ROLE,
|
|
35
|
-
CONCEPTS,
|
|
36
|
-
CONTACT,
|
|
37
|
-
CORE_REP,
|
|
38
|
-
CS,
|
|
39
|
-
DEPARTMENT,
|
|
40
|
-
DESC,
|
|
41
|
-
DFW,
|
|
42
|
-
DFW_ALIAS_LOW,
|
|
43
|
-
DFW_LOW,
|
|
44
|
-
DFWS,
|
|
45
|
-
DIM,
|
|
46
|
-
DIM_LIST,
|
|
47
|
-
DSD,
|
|
48
|
-
DSD_COMPS,
|
|
49
|
-
DSDS,
|
|
50
|
-
DTYPE,
|
|
51
|
-
EMAIL,
|
|
52
|
-
EMAILS,
|
|
53
|
-
ENUM,
|
|
54
|
-
ENUM_FORMAT,
|
|
55
|
-
FACETS,
|
|
56
|
-
FAX,
|
|
57
|
-
FAXES,
|
|
58
|
-
GROUP,
|
|
59
|
-
GROUP_DIM,
|
|
60
|
-
ID,
|
|
61
|
-
IS_EXTERNAL_REF,
|
|
62
|
-
IS_EXTERNAL_REF_LOW,
|
|
63
|
-
IS_FINAL,
|
|
64
|
-
IS_FINAL_LOW,
|
|
65
|
-
IS_PARTIAL,
|
|
66
|
-
IS_PARTIAL_LOW,
|
|
67
|
-
LOCAL_CODES_LOW,
|
|
68
|
-
LOCAL_DTYPE,
|
|
69
|
-
LOCAL_FACETS_LOW,
|
|
70
|
-
LOCAL_REP,
|
|
71
|
-
MANDATORY,
|
|
72
|
-
ME_LIST,
|
|
73
|
-
NAME,
|
|
74
|
-
ORGS,
|
|
75
|
-
PAR_ID,
|
|
76
|
-
PAR_VER,
|
|
77
|
-
PRIM_MEASURE,
|
|
78
|
-
REF,
|
|
79
|
-
REQUIRED,
|
|
80
|
-
ROLE,
|
|
81
|
-
RULE,
|
|
82
|
-
RULE_SCHEME,
|
|
83
|
-
RULESETS,
|
|
84
|
-
SER_URL,
|
|
85
|
-
SER_URL_LOW,
|
|
86
|
-
STR_URL,
|
|
87
|
-
STR_URL_LOW,
|
|
6
|
+
from pysdmx.io.xml.__parse_xml import parse_xml
|
|
7
|
+
from pysdmx.io.xml.__structure_aux_reader import StructureParser
|
|
8
|
+
from pysdmx.io.xml.__tokens import (
|
|
88
9
|
STRUCTURE,
|
|
89
10
|
STRUCTURES,
|
|
90
|
-
TELEPHONE,
|
|
91
|
-
TELEPHONES,
|
|
92
|
-
TEXT,
|
|
93
|
-
TEXT_FORMAT,
|
|
94
|
-
TEXT_TYPE,
|
|
95
|
-
TIME_DIM,
|
|
96
|
-
TITLE,
|
|
97
|
-
TRANS_SCHEME,
|
|
98
|
-
TRANSFORMATION,
|
|
99
|
-
TRANSFORMATIONS,
|
|
100
|
-
TYPE,
|
|
101
|
-
UDO,
|
|
102
|
-
UDO_SCHEME,
|
|
103
|
-
UDOS,
|
|
104
|
-
URI,
|
|
105
|
-
URIS,
|
|
106
|
-
URL,
|
|
107
|
-
URN,
|
|
108
|
-
VALID_FROM,
|
|
109
|
-
VALID_FROM_LOW,
|
|
110
|
-
VALID_TO,
|
|
111
|
-
VALID_TO_LOW,
|
|
112
|
-
VERSION,
|
|
113
|
-
VTL_MAPPING_SCHEME,
|
|
114
|
-
VTLMAPPING,
|
|
115
|
-
VTLMAPPINGS,
|
|
116
|
-
)
|
|
117
|
-
from pysdmx.io.xml.sdmx21.reader.__parse_xml import parse_xml
|
|
118
|
-
from pysdmx.io.xml.utils import add_list
|
|
119
|
-
from pysdmx.model import (
|
|
120
|
-
AgencyScheme,
|
|
121
|
-
Code,
|
|
122
|
-
Codelist,
|
|
123
|
-
Concept,
|
|
124
|
-
ConceptScheme,
|
|
125
|
-
DataType,
|
|
126
|
-
Facets,
|
|
127
11
|
)
|
|
128
12
|
from pysdmx.model.__base import (
|
|
129
|
-
Agency,
|
|
130
|
-
Annotation,
|
|
131
|
-
Contact,
|
|
132
|
-
DataflowRef,
|
|
133
|
-
Item,
|
|
134
|
-
ItemReference,
|
|
135
13
|
ItemScheme,
|
|
136
|
-
Reference,
|
|
137
14
|
)
|
|
138
15
|
from pysdmx.model.dataflow import (
|
|
139
|
-
Component,
|
|
140
|
-
Components,
|
|
141
16
|
Dataflow,
|
|
142
17
|
DataStructureDefinition,
|
|
143
|
-
Role,
|
|
144
18
|
)
|
|
145
|
-
from pysdmx.model.vtl import (
|
|
146
|
-
Ruleset,
|
|
147
|
-
RulesetScheme,
|
|
148
|
-
Transformation,
|
|
149
|
-
TransformationScheme,
|
|
150
|
-
UserDefinedOperator,
|
|
151
|
-
UserDefinedOperatorScheme,
|
|
152
|
-
VtlDataflowMapping,
|
|
153
|
-
VtlMappingScheme,
|
|
154
|
-
)
|
|
155
|
-
from pysdmx.util import find_by_urn, parse_urn
|
|
156
|
-
|
|
157
|
-
STRUCTURES_MAPPING = {
|
|
158
|
-
CL: Codelist,
|
|
159
|
-
AGENCIES: AgencyScheme,
|
|
160
|
-
CS: ConceptScheme,
|
|
161
|
-
DFWS: Dataflow,
|
|
162
|
-
DSDS: DataStructureDefinition,
|
|
163
|
-
RULE_SCHEME: RulesetScheme,
|
|
164
|
-
UDO_SCHEME: UserDefinedOperatorScheme,
|
|
165
|
-
TRANS_SCHEME: TransformationScheme,
|
|
166
|
-
VTL_MAPPING_SCHEME: VtlMappingScheme,
|
|
167
|
-
}
|
|
168
|
-
ITEMS_CLASSES = {
|
|
169
|
-
AGENCY: Agency,
|
|
170
|
-
CODE: Code,
|
|
171
|
-
CON: Concept,
|
|
172
|
-
RULE: Ruleset,
|
|
173
|
-
UDO: UserDefinedOperator,
|
|
174
|
-
TRANSFORMATION: Transformation,
|
|
175
|
-
VTLMAPPING: VtlDataflowMapping,
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
COMP_TYPES = [DIM, ATT, PRIM_MEASURE, GROUP_DIM]
|
|
179
|
-
|
|
180
|
-
ROLE_MAPPING = {
|
|
181
|
-
DIM: Role.DIMENSION,
|
|
182
|
-
ATT: Role.ATTRIBUTE,
|
|
183
|
-
PRIM_MEASURE: Role.MEASURE,
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
FACETS_MAPPING = {
|
|
187
|
-
"minLength": "min_length",
|
|
188
|
-
"maxLength": "max_length",
|
|
189
|
-
"minValue": "min_value",
|
|
190
|
-
"maxValue": "max_value",
|
|
191
|
-
"startValue": "start_value",
|
|
192
|
-
"endValue": "end_value",
|
|
193
|
-
"interval": "interval",
|
|
194
|
-
"timeInterval": "time_interval",
|
|
195
|
-
"decimals": "decimals",
|
|
196
|
-
"pattern": "pattern",
|
|
197
|
-
"startTime": "start_time",
|
|
198
|
-
"endTime": "end_time",
|
|
199
|
-
"isSequence": "is_sequence",
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def _extract_text(element: Any) -> str:
|
|
204
|
-
"""Extracts the text from the element.
|
|
205
|
-
|
|
206
|
-
Args:
|
|
207
|
-
element: The element to extract the text from
|
|
208
|
-
|
|
209
|
-
Returns:
|
|
210
|
-
The text extracted from the element
|
|
211
|
-
"""
|
|
212
|
-
if isinstance(element, list):
|
|
213
|
-
aux = {}
|
|
214
|
-
for language_element in element:
|
|
215
|
-
if "lang" in language_element and language_element["lang"] == "en":
|
|
216
|
-
aux = language_element
|
|
217
|
-
if not aux:
|
|
218
|
-
aux = element[0]
|
|
219
|
-
element = aux
|
|
220
|
-
if isinstance(element, dict) and "#text" in element:
|
|
221
|
-
element = element["#text"]
|
|
222
|
-
return element
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
class StructureParser(Struct):
|
|
226
|
-
"""StructureParser class for SDMX-ML 2.1."""
|
|
227
|
-
|
|
228
|
-
agencies: Dict[str, Any] = {}
|
|
229
|
-
codelists: Dict[str, Any] = {}
|
|
230
|
-
concepts: Dict[str, Any] = {}
|
|
231
|
-
datastructures: Dict[str, Any] = {}
|
|
232
|
-
dataflows: Dict[str, Any] = {}
|
|
233
|
-
rulesets: Dict[str, Any] = {}
|
|
234
|
-
udos: Dict[str, Any] = {}
|
|
235
|
-
transformations: Dict[str, Any] = {}
|
|
236
|
-
|
|
237
|
-
def __format_contact(self, json_contact: Dict[str, Any]) -> Contact:
|
|
238
|
-
"""Creates a Contact object from a json_contact.
|
|
239
|
-
|
|
240
|
-
Args:
|
|
241
|
-
json_contact: The element to create the Contact object from
|
|
242
|
-
|
|
243
|
-
Returns:
|
|
244
|
-
Contact object created from the json_contact
|
|
245
|
-
"""
|
|
246
|
-
self.__format_name_description(json_contact)
|
|
247
|
-
|
|
248
|
-
xml_node_to_attribute = {
|
|
249
|
-
NAME: NAME.lower(),
|
|
250
|
-
DEPARTMENT: DEPARTMENT.lower(),
|
|
251
|
-
ROLE: ROLE.lower(),
|
|
252
|
-
URI: URIS,
|
|
253
|
-
EMAIL: EMAILS,
|
|
254
|
-
TELEPHONE: TELEPHONES,
|
|
255
|
-
FAX: FAXES,
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
for k, v in xml_node_to_attribute.items():
|
|
259
|
-
if k in json_contact:
|
|
260
|
-
if k in [DEPARTMENT, ROLE]:
|
|
261
|
-
json_contact[v] = _extract_text(json_contact.pop(k))
|
|
262
|
-
continue
|
|
263
|
-
field_info = add_list(json_contact.pop(k))
|
|
264
|
-
for i, element in enumerate(field_info):
|
|
265
|
-
field_info[i] = _extract_text(element)
|
|
266
|
-
json_contact[v] = field_info
|
|
267
|
-
|
|
268
|
-
return Contact(**json_contact)
|
|
269
|
-
|
|
270
|
-
@staticmethod
|
|
271
|
-
def __format_annotations(item_elem: Any) -> Dict[str, Any]:
|
|
272
|
-
"""Formats the annotations in this element.
|
|
273
|
-
|
|
274
|
-
Args:
|
|
275
|
-
item_elem: The element to be formatted
|
|
276
|
-
|
|
277
|
-
Returns:
|
|
278
|
-
annotations formatted
|
|
279
|
-
"""
|
|
280
|
-
if ANNOTATIONS not in item_elem:
|
|
281
|
-
return item_elem
|
|
282
|
-
annotations = []
|
|
283
|
-
|
|
284
|
-
ann = item_elem[ANNOTATIONS]
|
|
285
|
-
ann[ANNOTATION] = add_list(ann[ANNOTATION])
|
|
286
|
-
for e in ann[ANNOTATION]:
|
|
287
|
-
if ANNOTATION_TITLE in e:
|
|
288
|
-
e[TITLE] = e.pop(ANNOTATION_TITLE)
|
|
289
|
-
if ANNOTATION_TYPE in e:
|
|
290
|
-
e[TYPE] = e.pop(ANNOTATION_TYPE)
|
|
291
|
-
if ANNOTATION_TEXT in e:
|
|
292
|
-
e[TEXT] = _extract_text(e[ANNOTATION_TEXT])
|
|
293
|
-
del e[ANNOTATION_TEXT]
|
|
294
|
-
if ANNOTATION_URL in e:
|
|
295
|
-
e[URL] = e.pop(ANNOTATION_URL)
|
|
296
|
-
|
|
297
|
-
annotations.append(Annotation(**e))
|
|
298
|
-
|
|
299
|
-
item_elem[ANNOTATIONS.lower()] = annotations
|
|
300
|
-
del item_elem[ANNOTATIONS]
|
|
301
|
-
|
|
302
|
-
return item_elem
|
|
303
|
-
|
|
304
|
-
@staticmethod
|
|
305
|
-
def __format_name_description(element: Any) -> Dict[str, Any]:
|
|
306
|
-
node = [NAME, DESC]
|
|
307
|
-
for field in node:
|
|
308
|
-
if field in element:
|
|
309
|
-
element[field.lower()] = _extract_text(element[field])
|
|
310
|
-
del element[field]
|
|
311
|
-
return element
|
|
312
|
-
|
|
313
|
-
@staticmethod
|
|
314
|
-
def __format_facets(
|
|
315
|
-
json_fac: Dict[str, Any], json_obj: Dict[str, Any]
|
|
316
|
-
) -> None:
|
|
317
|
-
"""Formats the facets from the JSON information.
|
|
318
|
-
|
|
319
|
-
Args:
|
|
320
|
-
json_fac: The element with the facets to be formatted
|
|
321
|
-
json_obj: The element to store the formatted facets
|
|
322
|
-
"""
|
|
323
|
-
if json_fac is None:
|
|
324
|
-
return
|
|
325
|
-
for key, _value in json_fac.items():
|
|
326
|
-
if key == TEXT_TYPE and json_fac[TEXT_TYPE] in list(DataType):
|
|
327
|
-
json_obj["dtype"] = DataType(json_fac[TEXT_TYPE])
|
|
328
|
-
|
|
329
|
-
if key in FACETS_MAPPING:
|
|
330
|
-
facet_kwargs = {
|
|
331
|
-
FACETS_MAPPING[k]: v
|
|
332
|
-
for k, v in json_fac.items()
|
|
333
|
-
if k in FACETS_MAPPING
|
|
334
|
-
}
|
|
335
|
-
json_obj[FACETS.lower()] = Facets(**facet_kwargs)
|
|
336
|
-
|
|
337
|
-
@staticmethod
|
|
338
|
-
def __format_validity(element: Dict[str, Any]) -> Dict[str, Any]:
|
|
339
|
-
if VALID_FROM in element:
|
|
340
|
-
element[VALID_FROM_LOW] = datetime.fromisoformat(
|
|
341
|
-
element.pop(VALID_FROM)
|
|
342
|
-
)
|
|
343
|
-
if VALID_TO in element:
|
|
344
|
-
element[VALID_TO_LOW] = datetime.fromisoformat(
|
|
345
|
-
element.pop(VALID_TO)
|
|
346
|
-
)
|
|
347
|
-
return element
|
|
348
|
-
|
|
349
|
-
@staticmethod
|
|
350
|
-
def __format_urls(json_elem: Dict[str, Any]) -> Dict[str, Any]:
|
|
351
|
-
"""Formats the STR_URL and SER_URL keys in the element.
|
|
352
|
-
|
|
353
|
-
Args:
|
|
354
|
-
json_elem: The element to be formatted
|
|
355
|
-
|
|
356
|
-
Returns:
|
|
357
|
-
The json_elem with STR_URL and SER_URL keys formatted.
|
|
358
|
-
"""
|
|
359
|
-
if STR_URL in json_elem:
|
|
360
|
-
json_elem[STR_URL_LOW] = json_elem.pop(STR_URL)
|
|
361
|
-
if SER_URL in json_elem:
|
|
362
|
-
json_elem[SER_URL_LOW] = json_elem.pop(SER_URL)
|
|
363
|
-
return json_elem
|
|
364
|
-
|
|
365
|
-
def __format_agency(self, element: Dict[str, Any]) -> Dict[str, Any]:
|
|
366
|
-
"""Formats the AGENCY_ID key in the element to the maintainer.
|
|
367
|
-
|
|
368
|
-
Args:
|
|
369
|
-
element: The element with the Agency ID to be formatted
|
|
370
|
-
|
|
371
|
-
Returns:
|
|
372
|
-
element with the Agency ID formatted
|
|
373
|
-
"""
|
|
374
|
-
element[AGENCY.lower()] = self.agencies.get(
|
|
375
|
-
element[AGENCY_ID], element[AGENCY_ID]
|
|
376
|
-
)
|
|
377
|
-
del element[AGENCY_ID]
|
|
378
|
-
return element
|
|
379
|
-
|
|
380
|
-
def __format_orgs(self, json_orgs: Dict[str, Any]) -> Dict[str, Any]:
|
|
381
|
-
orgs: Dict[str, Any] = {}
|
|
382
|
-
json_list = add_list(json_orgs)
|
|
383
|
-
for e in json_list:
|
|
384
|
-
ag_sch = self.__format_scheme(
|
|
385
|
-
e,
|
|
386
|
-
AGENCIES,
|
|
387
|
-
AGENCY,
|
|
388
|
-
)
|
|
389
|
-
orgs = {**orgs, **ag_sch}
|
|
390
|
-
return orgs
|
|
391
|
-
|
|
392
|
-
def __format_representation(
|
|
393
|
-
self, json_rep: Dict[str, Any], json_obj: Dict[str, Any]
|
|
394
|
-
) -> None:
|
|
395
|
-
"""Formats the representation in the JSON Representation."""
|
|
396
|
-
if TEXT_FORMAT in json_rep:
|
|
397
|
-
self.__format_facets(json_rep[TEXT_FORMAT], json_obj)
|
|
398
|
-
|
|
399
|
-
if ENUM in json_rep and len(self.codelists) > 0:
|
|
400
|
-
ref = json_rep[ENUM].get(REF, json_rep[ENUM])
|
|
401
|
-
|
|
402
|
-
if "URN" in ref:
|
|
403
|
-
codelist = find_by_urn(
|
|
404
|
-
list(self.codelists.values()), ref["URN"]
|
|
405
|
-
).codes
|
|
406
|
-
|
|
407
|
-
else:
|
|
408
|
-
short_urn = str(
|
|
409
|
-
Reference(
|
|
410
|
-
sdmx_type=ref[CLASS],
|
|
411
|
-
agency=ref[AGENCY_ID],
|
|
412
|
-
id=ref[ID],
|
|
413
|
-
version=ref[VERSION],
|
|
414
|
-
)
|
|
415
|
-
)
|
|
416
|
-
codelist = self.codelists[short_urn]
|
|
417
|
-
|
|
418
|
-
json_obj[CODES_LOW] = codelist
|
|
419
|
-
if ENUM_FORMAT in json_rep:
|
|
420
|
-
self.__format_facets(json_rep[ENUM_FORMAT], json_obj)
|
|
421
|
-
|
|
422
|
-
def __format_local_rep(self, representation_info: Dict[str, Any]) -> None:
|
|
423
|
-
rep: Dict[str, Any] = {}
|
|
424
|
-
|
|
425
|
-
self.__format_representation(representation_info[LOCAL_REP], rep)
|
|
426
|
-
del representation_info[LOCAL_REP]
|
|
427
|
-
|
|
428
|
-
if CODES_LOW in rep:
|
|
429
|
-
representation_info[LOCAL_CODES_LOW] = rep.pop(CODES_LOW)
|
|
430
|
-
|
|
431
|
-
if DTYPE in rep:
|
|
432
|
-
representation_info[LOCAL_DTYPE] = rep.pop(DTYPE)
|
|
433
|
-
|
|
434
|
-
if FACETS.lower() in rep:
|
|
435
|
-
representation_info[LOCAL_FACETS_LOW] = rep.pop(FACETS.lower())
|
|
436
|
-
|
|
437
|
-
def __format_con_id(self, concept_ref: Dict[str, Any]) -> Dict[str, Any]:
|
|
438
|
-
rep = {}
|
|
439
|
-
item_reference = ItemReference(
|
|
440
|
-
sdmx_type=concept_ref[CLASS],
|
|
441
|
-
agency=concept_ref[AGENCY_ID],
|
|
442
|
-
id=concept_ref[PAR_ID],
|
|
443
|
-
version=concept_ref[PAR_VER],
|
|
444
|
-
item_id=concept_ref[ID],
|
|
445
|
-
)
|
|
446
|
-
scheme_reference = Reference(
|
|
447
|
-
sdmx_type=CS,
|
|
448
|
-
agency=concept_ref[AGENCY_ID],
|
|
449
|
-
id=concept_ref[PAR_ID],
|
|
450
|
-
version=concept_ref[PAR_VER],
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
concept_scheme = self.concepts.get(str(scheme_reference))
|
|
454
|
-
if concept_scheme is None:
|
|
455
|
-
return {CON: item_reference}
|
|
456
|
-
for con in concept_scheme.concepts:
|
|
457
|
-
if con.id == concept_ref[ID]:
|
|
458
|
-
rep[CON] = con
|
|
459
|
-
break
|
|
460
|
-
if CON not in rep:
|
|
461
|
-
return {CON: item_reference}
|
|
462
|
-
return rep
|
|
463
|
-
|
|
464
|
-
@staticmethod
|
|
465
|
-
def __format_relationship(json_rel: Dict[str, Any]) -> Optional[str]:
|
|
466
|
-
att_level = None
|
|
467
|
-
|
|
468
|
-
for scheme in [DIM, PRIM_MEASURE]:
|
|
469
|
-
if scheme in json_rel:
|
|
470
|
-
if scheme == DIM:
|
|
471
|
-
dims = add_list(json_rel[DIM])
|
|
472
|
-
dims = [dim[REF][ID] for dim in dims]
|
|
473
|
-
att_level = ",".join(dims)
|
|
474
|
-
else:
|
|
475
|
-
att_level = "O"
|
|
476
|
-
|
|
477
|
-
return att_level
|
|
478
|
-
|
|
479
|
-
def __format_vtl_references(
|
|
480
|
-
self, json_elem: Dict[str, Any]
|
|
481
|
-
) -> Dict[str, Any]:
|
|
482
|
-
"""Formats the references in the VTL element."""
|
|
483
|
-
|
|
484
|
-
def extract_references(
|
|
485
|
-
scheme: str, new_key: str, object_list: Dict[str, Any]
|
|
486
|
-
) -> None:
|
|
487
|
-
if scheme in json_elem:
|
|
488
|
-
references = []
|
|
489
|
-
scheme_entries = (
|
|
490
|
-
json_elem[scheme]
|
|
491
|
-
if isinstance(json_elem[scheme], list)
|
|
492
|
-
else [json_elem[scheme]]
|
|
493
|
-
)
|
|
494
|
-
for entry in scheme_entries:
|
|
495
|
-
ref = entry[REF]
|
|
496
|
-
|
|
497
|
-
ref_id = ref[ID]
|
|
498
|
-
matching_object = next(
|
|
499
|
-
(
|
|
500
|
-
obj
|
|
501
|
-
for obj in object_list.values()
|
|
502
|
-
if getattr(obj, ID, None) == ref_id
|
|
503
|
-
),
|
|
504
|
-
None,
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
if matching_object:
|
|
508
|
-
references.append(matching_object)
|
|
509
|
-
else:
|
|
510
|
-
references.append(
|
|
511
|
-
Reference(
|
|
512
|
-
sdmx_type=ref[CLASS],
|
|
513
|
-
agency=ref[AGENCY_ID],
|
|
514
|
-
id=ref_id,
|
|
515
|
-
version=ref[VERSION],
|
|
516
|
-
)
|
|
517
|
-
)
|
|
518
|
-
|
|
519
|
-
json_elem[new_key] = references
|
|
520
|
-
json_elem.pop(scheme)
|
|
521
|
-
|
|
522
|
-
extract_references(RULE_SCHEME, "ruleset_schemes", self.rulesets)
|
|
523
|
-
extract_references(
|
|
524
|
-
UDO_SCHEME, "user_defined_operator_schemes", self.udos
|
|
525
|
-
)
|
|
526
|
-
|
|
527
|
-
return json_elem
|
|
528
|
-
|
|
529
|
-
def __format_dataflow(
|
|
530
|
-
self, json_rep: Dict[str, Any], json_obj: Dict[str, Any]
|
|
531
|
-
) -> None:
|
|
532
|
-
json_obj[DFW_ALIAS_LOW] = json_obj.pop(ALIAS_LOW)
|
|
533
|
-
dataflow_ref = {
|
|
534
|
-
"agency": json_rep[REF][AGENCY_ID],
|
|
535
|
-
"id": json_rep[REF][ID],
|
|
536
|
-
"version": json_rep[REF][VERSION],
|
|
537
|
-
}
|
|
538
|
-
json_obj[DFW_LOW] = DataflowRef(**dataflow_ref)
|
|
539
|
-
json_rep.pop(REF)
|
|
540
|
-
json_obj.pop(DFW)
|
|
541
|
-
if self.dataflows:
|
|
542
|
-
for dataflow in self.dataflows.values():
|
|
543
|
-
if dataflow.id == dataflow_ref[ID]:
|
|
544
|
-
json_obj[DFW_LOW] = dataflow
|
|
545
|
-
|
|
546
|
-
def __format_component(
|
|
547
|
-
self, comp: Dict[str, Any], role: Role
|
|
548
|
-
) -> Component:
|
|
549
|
-
comp[ROLE.lower()] = role
|
|
550
|
-
comp[REQUIRED] = True
|
|
551
|
-
|
|
552
|
-
self.__format_local_rep(comp) if LOCAL_REP in comp else None
|
|
553
|
-
|
|
554
|
-
concept_id = self.__format_con_id(comp[CON_ID][REF])
|
|
555
|
-
comp[CON_LOW] = concept_id.pop(CON)
|
|
556
|
-
del comp[CON_ID]
|
|
557
|
-
|
|
558
|
-
# Attribute Handling
|
|
559
|
-
if ATT_REL in comp:
|
|
560
|
-
comp[ATT_LVL] = self.__format_relationship(comp[ATT_REL])
|
|
561
|
-
del comp[ATT_REL]
|
|
562
|
-
|
|
563
|
-
if AS_STATUS in comp:
|
|
564
|
-
if comp[AS_STATUS] != MANDATORY:
|
|
565
|
-
comp[REQUIRED] = False
|
|
566
|
-
del comp[AS_STATUS]
|
|
567
|
-
|
|
568
|
-
if "position" in comp:
|
|
569
|
-
del comp["position"]
|
|
570
|
-
|
|
571
|
-
if ANNOTATIONS in comp:
|
|
572
|
-
del comp[ANNOTATIONS]
|
|
573
|
-
|
|
574
|
-
if CON_ROLE in comp:
|
|
575
|
-
del comp[CON_ROLE]
|
|
576
|
-
|
|
577
|
-
return Component(**comp)
|
|
578
|
-
|
|
579
|
-
def __format_component_lists(
|
|
580
|
-
self, element: Dict[str, Any]
|
|
581
|
-
) -> List[Component]:
|
|
582
|
-
comp_list = []
|
|
583
|
-
|
|
584
|
-
if TIME_DIM in element:
|
|
585
|
-
element[DIM] = add_list(element[DIM])
|
|
586
|
-
element[DIM].append(element[TIME_DIM])
|
|
587
|
-
del element[TIME_DIM]
|
|
588
|
-
|
|
589
|
-
role_name = list(set(element.keys()).intersection(COMP_TYPES))[0]
|
|
590
|
-
role = ROLE_MAPPING[role_name]
|
|
591
|
-
element[role_name] = add_list(element[role_name])
|
|
592
|
-
|
|
593
|
-
for comp in element[role_name]:
|
|
594
|
-
formatted_comp = self.__format_component(comp, role)
|
|
595
|
-
comp_list.append(formatted_comp)
|
|
596
|
-
|
|
597
|
-
return comp_list
|
|
598
|
-
|
|
599
|
-
def __format_components(self, element: Dict[str, Any]) -> Dict[str, Any]:
|
|
600
|
-
if DSD_COMPS in element:
|
|
601
|
-
element[COMPS] = []
|
|
602
|
-
comps = element[DSD_COMPS]
|
|
603
|
-
|
|
604
|
-
for comp_list in [DIM_LIST, ME_LIST, GROUP, ATT_LIST]:
|
|
605
|
-
if comp_list == GROUP and comp_list in comps:
|
|
606
|
-
del comps[GROUP]
|
|
607
|
-
|
|
608
|
-
elif comp_list in comps:
|
|
609
|
-
fmt_comps = self.__format_component_lists(comps[comp_list])
|
|
610
|
-
element[COMPS].extend(fmt_comps)
|
|
611
|
-
|
|
612
|
-
element[COMPS] = Components(element[COMPS])
|
|
613
|
-
del element[DSD_COMPS]
|
|
614
|
-
|
|
615
|
-
return element
|
|
616
|
-
|
|
617
|
-
@staticmethod
|
|
618
|
-
def __format_vtl(json_vtl: Dict[str, Any]) -> Dict[str, Any]:
|
|
619
|
-
if "isPersistent" in json_vtl:
|
|
620
|
-
json_vtl["is_persistent"] = (
|
|
621
|
-
json_vtl.pop("isPersistent").lower() == "true"
|
|
622
|
-
)
|
|
623
|
-
if "Expression" in json_vtl:
|
|
624
|
-
json_vtl["expression"] = json_vtl.pop("Expression")
|
|
625
|
-
if "Result" in json_vtl:
|
|
626
|
-
json_vtl["result"] = json_vtl.pop("Result")
|
|
627
|
-
if "vtlVersion" in json_vtl:
|
|
628
|
-
json_vtl["vtl_version"] = json_vtl.pop("vtlVersion")
|
|
629
|
-
if "rulesetScope" in json_vtl:
|
|
630
|
-
json_vtl["ruleset_scope"] = json_vtl.pop("rulesetScope")
|
|
631
|
-
if "rulesetType" in json_vtl:
|
|
632
|
-
json_vtl["ruleset_type"] = json_vtl.pop("rulesetType")
|
|
633
|
-
if "RulesetDefinition" in json_vtl:
|
|
634
|
-
json_vtl["ruleset_definition"] = json_vtl.pop("RulesetDefinition")
|
|
635
|
-
if "OperatorDefinition" in json_vtl:
|
|
636
|
-
json_vtl["operator_definition"] = json_vtl.pop(
|
|
637
|
-
"OperatorDefinition"
|
|
638
|
-
)
|
|
639
|
-
return json_vtl
|
|
640
|
-
|
|
641
|
-
def __format_item(
|
|
642
|
-
self, item_json_info: Dict[str, Any], item_name_class: str
|
|
643
|
-
) -> Item:
|
|
644
|
-
item_json_info = self.__format_annotations(item_json_info)
|
|
645
|
-
item_json_info = self.__format_name_description(item_json_info)
|
|
646
|
-
if CONTACT in item_json_info and item_name_class == AGENCY:
|
|
647
|
-
item_json_info[CONTACT] = add_list(item_json_info[CONTACT])
|
|
648
|
-
contacts = []
|
|
649
|
-
for e in item_json_info[CONTACT]:
|
|
650
|
-
contacts.append(self.__format_contact(e))
|
|
651
|
-
item_json_info[CONTACT.lower() + "s"] = contacts
|
|
652
|
-
del item_json_info[CONTACT]
|
|
653
|
-
|
|
654
|
-
if CORE_REP in item_json_info and item_name_class == CON:
|
|
655
|
-
self.__format_representation(
|
|
656
|
-
item_json_info[CORE_REP], item_json_info
|
|
657
|
-
)
|
|
658
|
-
del item_json_info[CORE_REP]
|
|
659
|
-
|
|
660
|
-
if "Parent" in item_json_info:
|
|
661
|
-
del item_json_info["Parent"]
|
|
662
|
-
if DFW in item_json_info:
|
|
663
|
-
self.__format_dataflow(item_json_info[DFW], item_json_info)
|
|
664
|
-
|
|
665
|
-
item_json_info = self.__format_vtl(item_json_info)
|
|
666
|
-
|
|
667
|
-
return ITEMS_CLASSES[item_name_class](**item_json_info)
|
|
668
|
-
|
|
669
|
-
def __format_scheme(
|
|
670
|
-
self, json_elem: Dict[str, Any], scheme: str, item: str
|
|
671
|
-
) -> Dict[str, ItemScheme]:
|
|
672
|
-
elements: Dict[str, ItemScheme] = {}
|
|
673
|
-
|
|
674
|
-
json_elem[scheme] = add_list(json_elem[scheme])
|
|
675
|
-
for element in json_elem[scheme]:
|
|
676
|
-
element["items"] = []
|
|
677
|
-
|
|
678
|
-
element = self.__format_annotations(element)
|
|
679
|
-
element = self.__format_name_description(element)
|
|
680
|
-
element = self.__format_urls(element)
|
|
681
|
-
if IS_EXTERNAL_REF in element:
|
|
682
|
-
element[IS_EXTERNAL_REF_LOW] = (
|
|
683
|
-
element.pop(IS_EXTERNAL_REF) == "true"
|
|
684
|
-
)
|
|
685
|
-
if IS_FINAL in element:
|
|
686
|
-
element[IS_FINAL_LOW] = element.pop(IS_FINAL) == "true"
|
|
687
|
-
if IS_PARTIAL in element:
|
|
688
|
-
element[IS_PARTIAL_LOW] = element.pop(IS_PARTIAL) == "true"
|
|
689
|
-
element[item] = add_list(element[item])
|
|
690
|
-
items = []
|
|
691
|
-
for item_elem in element[item]:
|
|
692
|
-
# Dynamic
|
|
693
|
-
items.append(self.__format_item(item_elem, item))
|
|
694
|
-
del element[item]
|
|
695
|
-
element["items"] = items
|
|
696
|
-
element = self.__format_agency(element)
|
|
697
|
-
element = self.__format_validity(element)
|
|
698
|
-
element = self.__format_vtl(element)
|
|
699
|
-
element = self.__format_vtl_references(element)
|
|
700
|
-
if "xmlns" in element:
|
|
701
|
-
del element["xmlns"]
|
|
702
|
-
# Dynamic creation with specific class
|
|
703
|
-
result: ItemScheme = STRUCTURES_MAPPING[scheme](**element)
|
|
704
|
-
elements[result.short_urn] = result
|
|
705
|
-
|
|
706
|
-
return elements
|
|
707
|
-
|
|
708
|
-
def __format_schema(
|
|
709
|
-
self, json_element: Dict[str, Any], schema: str, item: str
|
|
710
|
-
) -> Dict[str, Any]:
|
|
711
|
-
"""Formats the structures in json format.
|
|
712
|
-
|
|
713
|
-
Args:
|
|
714
|
-
json_element: The structures in json format
|
|
715
|
-
schema: The scheme of the structures
|
|
716
|
-
item: The item of the structures
|
|
717
|
-
|
|
718
|
-
Returns:
|
|
719
|
-
A dictionary with the structures formatted
|
|
720
|
-
"""
|
|
721
|
-
schemas = {}
|
|
722
|
-
|
|
723
|
-
json_element[item] = add_list(json_element[item])
|
|
724
|
-
for element in json_element[item]:
|
|
725
|
-
if URN.lower() in element and element[URN.lower()] is not None:
|
|
726
|
-
short_urn = parse_urn(element[URN.lower()]).__str__()
|
|
727
|
-
else:
|
|
728
|
-
short_urn = Reference(
|
|
729
|
-
sdmx_type=item,
|
|
730
|
-
agency=element[AGENCY_ID],
|
|
731
|
-
id=element[ID],
|
|
732
|
-
version=element[VERSION],
|
|
733
|
-
).__str__()
|
|
734
|
-
|
|
735
|
-
element = self.__format_annotations(element)
|
|
736
|
-
element = self.__format_name_description(element)
|
|
737
|
-
element = self.__format_urls(element)
|
|
738
|
-
element = self.__format_agency(element)
|
|
739
|
-
element = self.__format_validity(element)
|
|
740
|
-
element = self.__format_components(element)
|
|
741
|
-
|
|
742
|
-
if "xmlns" in element:
|
|
743
|
-
del element["xmlns"]
|
|
744
|
-
if IS_EXTERNAL_REF in element:
|
|
745
|
-
element[IS_EXTERNAL_REF_LOW] = element.pop(IS_EXTERNAL_REF)
|
|
746
|
-
element[IS_EXTERNAL_REF_LOW] = (
|
|
747
|
-
str(element[IS_EXTERNAL_REF_LOW]).lower() == "true"
|
|
748
|
-
)
|
|
749
|
-
if IS_FINAL in element:
|
|
750
|
-
element[IS_FINAL_LOW] = element.pop(IS_FINAL)
|
|
751
|
-
element[IS_FINAL_LOW] = (
|
|
752
|
-
str(element[IS_FINAL_LOW]).lower() == "true"
|
|
753
|
-
)
|
|
754
|
-
|
|
755
|
-
if item == DFW:
|
|
756
|
-
ref_data = element[STRUCTURE][REF]
|
|
757
|
-
reference_str = (
|
|
758
|
-
f"{ref_data[CLASS]}={ref_data[AGENCY_ID]}"
|
|
759
|
-
f":{ref_data[ID]}({ref_data[VERSION]})"
|
|
760
|
-
)
|
|
761
|
-
element[STRUCTURE] = reference_str
|
|
762
|
-
|
|
763
|
-
structure = {key.lower(): value for key, value in element.items()}
|
|
764
|
-
if schema == DSDS:
|
|
765
|
-
if COMPS in structure:
|
|
766
|
-
structure[COMPS] = Components(structure[COMPS])
|
|
767
|
-
else:
|
|
768
|
-
structure[COMPS] = Components([])
|
|
769
|
-
schemas[short_urn] = STRUCTURES_MAPPING[schema](**structure)
|
|
770
|
-
|
|
771
|
-
return schemas
|
|
772
|
-
|
|
773
|
-
def format_structures(
|
|
774
|
-
self, json_meta: Dict[str, Any]
|
|
775
|
-
) -> Sequence[Union[ItemScheme, DataStructureDefinition, Dataflow]]:
|
|
776
|
-
"""Formats the structures in JSON format.
|
|
777
|
-
|
|
778
|
-
Args:
|
|
779
|
-
json_meta: The structures in JSON format.
|
|
780
|
-
|
|
781
|
-
Returns:
|
|
782
|
-
A list with the formatted structures.
|
|
783
|
-
"""
|
|
784
|
-
|
|
785
|
-
def process_structure(
|
|
786
|
-
key: str,
|
|
787
|
-
formatter: Callable[[Dict[str, Any]], Dict[Any, Any]],
|
|
788
|
-
attr: Optional[str] = None,
|
|
789
|
-
) -> Dict[Any, Any]:
|
|
790
|
-
"""Helper function to process and store formatted structures."""
|
|
791
|
-
if key in json_meta:
|
|
792
|
-
formatted = formatter(json_meta[key])
|
|
793
|
-
if attr:
|
|
794
|
-
setattr(self, attr, formatted)
|
|
795
|
-
return formatted
|
|
796
|
-
return {}
|
|
797
|
-
|
|
798
|
-
structures = {
|
|
799
|
-
ORGS: process_structure(ORGS, self.__format_orgs, "agencies"),
|
|
800
|
-
CLS: process_structure(
|
|
801
|
-
CLS,
|
|
802
|
-
lambda data: self.__format_scheme(data, CL, CODE),
|
|
803
|
-
"codelists",
|
|
804
|
-
),
|
|
805
|
-
CONCEPTS: process_structure(
|
|
806
|
-
CONCEPTS,
|
|
807
|
-
lambda data: self.__format_scheme(data, CS, CON),
|
|
808
|
-
"concepts",
|
|
809
|
-
),
|
|
810
|
-
DSDS: process_structure(
|
|
811
|
-
DSDS,
|
|
812
|
-
lambda data: self.__format_schema(data, DSDS, DSD),
|
|
813
|
-
"datastructures",
|
|
814
|
-
),
|
|
815
|
-
DFWS: process_structure(
|
|
816
|
-
DFWS,
|
|
817
|
-
lambda data: self.__format_schema(data, DFWS, DFW),
|
|
818
|
-
"dataflows",
|
|
819
|
-
),
|
|
820
|
-
RULESETS: process_structure(
|
|
821
|
-
RULESETS,
|
|
822
|
-
lambda data: self.__format_scheme(data, RULE_SCHEME, RULE),
|
|
823
|
-
"rulesets",
|
|
824
|
-
),
|
|
825
|
-
UDOS: process_structure(
|
|
826
|
-
UDOS,
|
|
827
|
-
lambda data: self.__format_scheme(data, UDO_SCHEME, UDO),
|
|
828
|
-
"udos",
|
|
829
|
-
),
|
|
830
|
-
TRANSFORMATIONS: process_structure(
|
|
831
|
-
TRANSFORMATIONS,
|
|
832
|
-
lambda data: self.__format_scheme(
|
|
833
|
-
data,
|
|
834
|
-
TRANS_SCHEME,
|
|
835
|
-
TRANSFORMATION,
|
|
836
|
-
),
|
|
837
|
-
"transformations",
|
|
838
|
-
),
|
|
839
|
-
VTLMAPPINGS: process_structure(
|
|
840
|
-
VTLMAPPINGS,
|
|
841
|
-
lambda data: self.__format_scheme(
|
|
842
|
-
data,
|
|
843
|
-
VTL_MAPPING_SCHEME,
|
|
844
|
-
VTLMAPPING,
|
|
845
|
-
),
|
|
846
|
-
),
|
|
847
|
-
}
|
|
848
|
-
return [
|
|
849
|
-
compound
|
|
850
|
-
for value in structures.values()
|
|
851
|
-
if value
|
|
852
|
-
for compound in value.values()
|
|
853
|
-
]
|
|
854
19
|
|
|
855
20
|
|
|
856
21
|
def read(
|
|
@@ -860,7 +25,7 @@ def read(
|
|
|
860
25
|
"""Reads an SDMX-ML 2.1 Structure data and returns the structures.
|
|
861
26
|
|
|
862
27
|
Args:
|
|
863
|
-
input_str: SDMX-ML
|
|
28
|
+
input_str: SDMX-ML structure message to read.
|
|
864
29
|
validate: If True, the XML data will be validated against the XSD.
|
|
865
30
|
|
|
866
31
|
Returns:
|