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,841 +1,25 @@
|
|
|
1
1
|
"""Module for writing metadata to XML files."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from typing import
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Dict, Optional, Sequence, Union
|
|
5
5
|
|
|
6
|
-
from pysdmx.errors import Invalid
|
|
7
6
|
from pysdmx.io.format import Format
|
|
8
|
-
from pysdmx.io.xml.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
AS_STATUS,
|
|
12
|
-
ATT,
|
|
13
|
-
ATT_REL,
|
|
14
|
-
CL,
|
|
15
|
-
CL_LOW,
|
|
16
|
-
CLASS,
|
|
17
|
-
CON,
|
|
18
|
-
CON_ID,
|
|
19
|
-
CONDITIONAL,
|
|
20
|
-
CORE_REP,
|
|
21
|
-
CS,
|
|
22
|
-
DEPARTMENT,
|
|
23
|
-
DFW,
|
|
24
|
-
DIM,
|
|
25
|
-
DSD,
|
|
26
|
-
DSD_COMPS,
|
|
27
|
-
EMAIL,
|
|
28
|
-
ENUM,
|
|
29
|
-
ENUM_FORMAT,
|
|
30
|
-
FAX,
|
|
31
|
-
ID,
|
|
32
|
-
LOCAL_REP,
|
|
33
|
-
MANDATORY,
|
|
34
|
-
MEASURE,
|
|
35
|
-
NAME,
|
|
36
|
-
PACKAGE,
|
|
37
|
-
PAR_ID,
|
|
38
|
-
PAR_VER,
|
|
39
|
-
POSITION,
|
|
40
|
-
PRIM_MEASURE,
|
|
41
|
-
REF,
|
|
42
|
-
ROLE,
|
|
43
|
-
RULE,
|
|
44
|
-
RULE_SCHEME,
|
|
45
|
-
TELEPHONE,
|
|
46
|
-
TEXT_FORMAT,
|
|
47
|
-
TEXT_TYPE,
|
|
48
|
-
TIME_DIM,
|
|
49
|
-
TRANS_SCHEME,
|
|
50
|
-
TRANSFORMATION,
|
|
51
|
-
UDO,
|
|
52
|
-
UDO_SCHEME,
|
|
53
|
-
URI,
|
|
54
|
-
URN,
|
|
55
|
-
VERSION,
|
|
56
|
-
VTL_MAPPING_SCHEME,
|
|
57
|
-
VTLMAPPING,
|
|
7
|
+
from pysdmx.io.xml.__structure_aux_writer import (
|
|
8
|
+
STR_DICT_TYPE_LIST_21,
|
|
9
|
+
__write_structures,
|
|
58
10
|
)
|
|
59
|
-
from pysdmx.io.xml.
|
|
60
|
-
ABBR_COM,
|
|
61
|
-
ABBR_MSG,
|
|
62
|
-
ABBR_STR,
|
|
63
|
-
MSG_CONTENT_PKG,
|
|
64
|
-
__escape_xml,
|
|
65
|
-
__to_lower_camel_case,
|
|
11
|
+
from pysdmx.io.xml.__write_aux import (
|
|
66
12
|
__write_header,
|
|
67
|
-
add_indent,
|
|
68
13
|
create_namespaces,
|
|
69
14
|
get_end_message,
|
|
70
15
|
)
|
|
71
|
-
from pysdmx.model import
|
|
72
|
-
AgencyScheme,
|
|
73
|
-
Codelist,
|
|
74
|
-
Concept,
|
|
75
|
-
ConceptScheme,
|
|
76
|
-
DataType,
|
|
77
|
-
Facets,
|
|
78
|
-
Hierarchy,
|
|
79
|
-
Ruleset,
|
|
80
|
-
RulesetScheme,
|
|
81
|
-
Transformation,
|
|
82
|
-
TransformationScheme,
|
|
83
|
-
UserDefinedOperator,
|
|
84
|
-
UserDefinedOperatorScheme,
|
|
85
|
-
VtlDataflowMapping,
|
|
86
|
-
VtlMappingScheme,
|
|
87
|
-
VtlScheme,
|
|
88
|
-
)
|
|
89
|
-
from pysdmx.model.__base import (
|
|
90
|
-
Agency,
|
|
91
|
-
AnnotableArtefact,
|
|
92
|
-
Contact,
|
|
93
|
-
IdentifiableArtefact,
|
|
94
|
-
Item,
|
|
95
|
-
ItemReference,
|
|
96
|
-
ItemScheme,
|
|
97
|
-
MaintainableArtefact,
|
|
98
|
-
NameableArtefact,
|
|
99
|
-
Reference,
|
|
100
|
-
VersionableArtefact,
|
|
101
|
-
)
|
|
102
|
-
from pysdmx.model.dataflow import (
|
|
103
|
-
Component,
|
|
104
|
-
Dataflow,
|
|
105
|
-
DataStructureDefinition,
|
|
106
|
-
Role,
|
|
107
|
-
)
|
|
16
|
+
from pysdmx.model.__base import MaintainableArtefact
|
|
108
17
|
from pysdmx.model.message import Header
|
|
109
|
-
from pysdmx.util import (
|
|
110
|
-
parse_item_urn,
|
|
111
|
-
parse_short_urn,
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
ANNOTATION_WRITER = OrderedDict(
|
|
115
|
-
{
|
|
116
|
-
"title": "AnnotationTitle",
|
|
117
|
-
"type": "AnnotationType",
|
|
118
|
-
"text": "AnnotationText",
|
|
119
|
-
"url": "AnnotationURL",
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
ROLE_MAPPING = {
|
|
124
|
-
Role.DIMENSION: DIM,
|
|
125
|
-
Role.ATTRIBUTE: ATT,
|
|
126
|
-
Role.MEASURE: PRIM_MEASURE,
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
STR_TYPES = Union[
|
|
130
|
-
ItemScheme,
|
|
131
|
-
Codelist,
|
|
132
|
-
ConceptScheme,
|
|
133
|
-
DataStructureDefinition,
|
|
134
|
-
Dataflow,
|
|
135
|
-
RulesetScheme,
|
|
136
|
-
UserDefinedOperatorScheme,
|
|
137
|
-
TransformationScheme,
|
|
138
|
-
]
|
|
139
|
-
|
|
140
|
-
STR_DICT_TYPE_LIST = {
|
|
141
|
-
AgencyScheme: "OrganisationSchemes",
|
|
142
|
-
Codelist: "Codelists",
|
|
143
|
-
ConceptScheme: "Concepts",
|
|
144
|
-
DataStructureDefinition: "DataStructures",
|
|
145
|
-
Dataflow: "Dataflows",
|
|
146
|
-
RulesetScheme: "Rulesets",
|
|
147
|
-
UserDefinedOperatorScheme: "UserDefinedOperators",
|
|
148
|
-
TransformationScheme: "Transformations",
|
|
149
|
-
VtlMappingScheme: "VtlMappings",
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
def __write_annotable(annotable: AnnotableArtefact, indent: str) -> str:
|
|
154
|
-
"""Writes the annotations to the XML file."""
|
|
155
|
-
if len(annotable.annotations) == 0:
|
|
156
|
-
return ""
|
|
157
|
-
|
|
158
|
-
child1 = indent
|
|
159
|
-
child2 = add_indent(child1)
|
|
160
|
-
child3 = add_indent(child2)
|
|
161
|
-
|
|
162
|
-
outfile = f"{child1}<{ABBR_COM}:Annotations>"
|
|
163
|
-
for annotation in annotable.annotations:
|
|
164
|
-
if annotation.id is None:
|
|
165
|
-
outfile += f"{child2}<{ABBR_COM}:Annotation>"
|
|
166
|
-
else:
|
|
167
|
-
outfile += (
|
|
168
|
-
f"{child2}<{ABBR_COM}:Annotation " f"id={annotation.id!r}>"
|
|
169
|
-
)
|
|
170
|
-
outfile = outfile.replace("'", '"')
|
|
171
|
-
|
|
172
|
-
for attr, label in ANNOTATION_WRITER.items():
|
|
173
|
-
if getattr(annotation, attr, None) is not None:
|
|
174
|
-
value = getattr(annotation, attr)
|
|
175
|
-
value = __escape_xml(str(value))
|
|
176
|
-
|
|
177
|
-
if attr == "text":
|
|
178
|
-
head_tag = f'{ABBR_COM}:{label} xml:lang="en"'
|
|
179
|
-
|
|
180
|
-
else:
|
|
181
|
-
head_tag = f"{ABBR_COM}:{label}"
|
|
182
|
-
|
|
183
|
-
outfile += (
|
|
184
|
-
f"{child3}<{head_tag}>" f"{value}" f"</{ABBR_COM}:{label}>"
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
outfile += f"{child2}</{ABBR_COM}:Annotation>"
|
|
188
|
-
outfile += f"{child1}</{ABBR_COM}:Annotations>"
|
|
189
|
-
return outfile
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
def __write_identifiable(
|
|
193
|
-
identifiable: IdentifiableArtefact, indent: str
|
|
194
|
-
) -> Dict[str, Any]:
|
|
195
|
-
"""Writes the IdentifiableArtefact to the XML file."""
|
|
196
|
-
attributes = ""
|
|
197
|
-
|
|
198
|
-
attributes += f" id={identifiable.id!r}"
|
|
199
|
-
|
|
200
|
-
if identifiable.uri is not None:
|
|
201
|
-
attributes += f" uri={identifiable.uri!r}"
|
|
202
|
-
|
|
203
|
-
if identifiable.urn is not None:
|
|
204
|
-
attributes += f" urn={identifiable.urn!r}"
|
|
205
|
-
|
|
206
|
-
outfile = {
|
|
207
|
-
"Annotations": __write_annotable(identifiable, indent),
|
|
208
|
-
"Attributes": attributes,
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return outfile
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def __write_nameable(
|
|
215
|
-
nameable: NameableArtefact, indent: str
|
|
216
|
-
) -> Dict[str, Any]:
|
|
217
|
-
"""Writes the NameableArtefact to the XML file."""
|
|
218
|
-
outfile = __write_identifiable(nameable, indent)
|
|
219
|
-
attrs = ["Name", "Description"]
|
|
220
|
-
|
|
221
|
-
for attr in attrs:
|
|
222
|
-
value = getattr(nameable, attr.lower(), None)
|
|
223
|
-
if value is not None:
|
|
224
|
-
value = __escape_xml(str(value))
|
|
225
|
-
outfile[attr] = [
|
|
226
|
-
(
|
|
227
|
-
f"{indent}"
|
|
228
|
-
f'<{ABBR_COM}:{attr} xml:lang="en">'
|
|
229
|
-
f"{value}"
|
|
230
|
-
f"</{ABBR_COM}:{attr}>"
|
|
231
|
-
)
|
|
232
|
-
]
|
|
233
|
-
elif attr == "Name":
|
|
234
|
-
raise Invalid(
|
|
235
|
-
"Name is required for NameableArtefact" f" id= {nameable.id}"
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
return outfile
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
def __write_versionable(
|
|
242
|
-
versionable: VersionableArtefact, indent: str
|
|
243
|
-
) -> Dict[str, Any]:
|
|
244
|
-
"""Writes the VersionableArtefact to the XML file."""
|
|
245
|
-
outfile = __write_nameable(versionable, add_indent(indent))
|
|
246
|
-
|
|
247
|
-
outfile["Attributes"] += f" version={versionable.version!r}"
|
|
248
|
-
|
|
249
|
-
if versionable.valid_from is not None:
|
|
250
|
-
valid_from_str = versionable.valid_from.strftime("%Y-%m-%dT%H:%M:%S")
|
|
251
|
-
outfile["Attributes"] += f" validFrom={valid_from_str!r}"
|
|
252
|
-
|
|
253
|
-
if versionable.valid_to is not None:
|
|
254
|
-
valid_to_str = versionable.valid_to.strftime("%Y-%m-%dT%H:%M:%S")
|
|
255
|
-
outfile["Attributes"] += f" validTo={valid_to_str!r}"
|
|
256
|
-
|
|
257
|
-
return outfile
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
def __write_maintainable(
|
|
261
|
-
maintainable: MaintainableArtefact, indent: str
|
|
262
|
-
) -> Dict[str, Any]:
|
|
263
|
-
"""Writes the MaintainableArtefact to the XML file."""
|
|
264
|
-
outfile = __write_versionable(maintainable, indent)
|
|
265
|
-
|
|
266
|
-
outfile["Attributes"] += (
|
|
267
|
-
f" isExternalReference="
|
|
268
|
-
f"{str(maintainable.is_external_reference).lower()!r}"
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
outfile["Attributes"] += f" isFinal={str(maintainable.is_final).lower()!r}"
|
|
272
|
-
|
|
273
|
-
if isinstance(maintainable.agency, str):
|
|
274
|
-
outfile["Attributes"] += f" agencyID={maintainable.agency!r}"
|
|
275
|
-
else:
|
|
276
|
-
outfile["Attributes"] += f" agencyID={maintainable.agency.id!r}"
|
|
277
|
-
|
|
278
|
-
return outfile
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
def __write_contact(contact: Contact, indent: str) -> str:
|
|
282
|
-
"""Writes the contact to the XML file."""
|
|
283
|
-
|
|
284
|
-
def __item_to_str(item: Any, ns: str, tag: str) -> str:
|
|
285
|
-
return (
|
|
286
|
-
f"{add_indent(indent)}"
|
|
287
|
-
f"<{ns}:{tag}>"
|
|
288
|
-
f"{__escape_xml(str(item))}"
|
|
289
|
-
f"</{ns}:{tag}>"
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
def __items_to_str(items: Any, ns: str, tag: str) -> str:
|
|
293
|
-
return "".join([__item_to_str(item, ns, tag) for item in items])
|
|
294
|
-
|
|
295
|
-
outfile = f"{indent}<{ABBR_STR}:Contact>"
|
|
296
|
-
if contact.name is not None:
|
|
297
|
-
outfile += __item_to_str(contact.name, ABBR_COM, NAME)
|
|
298
|
-
if contact.department is not None:
|
|
299
|
-
outfile += __item_to_str(contact.department, ABBR_STR, DEPARTMENT)
|
|
300
|
-
if contact.role is not None:
|
|
301
|
-
outfile += __item_to_str(contact.role, ABBR_STR, ROLE)
|
|
302
|
-
if contact.telephones is not None:
|
|
303
|
-
outfile += __items_to_str(contact.telephones, ABBR_STR, TELEPHONE)
|
|
304
|
-
if contact.faxes is not None:
|
|
305
|
-
outfile += __items_to_str(contact.faxes, ABBR_STR, FAX)
|
|
306
|
-
if contact.uris is not None:
|
|
307
|
-
outfile += __items_to_str(contact.uris, ABBR_STR, URI)
|
|
308
|
-
if contact.emails is not None:
|
|
309
|
-
outfile += __items_to_str(contact.emails, ABBR_STR, EMAIL)
|
|
310
|
-
outfile += f"{indent}</{ABBR_STR}:Contact>"
|
|
311
|
-
|
|
312
|
-
return outfile
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
def __write_item(item: Item, indent: str) -> str:
|
|
316
|
-
"""Writes the item to the XML file."""
|
|
317
|
-
head = f"{ABBR_STR}:" + type(item).__name__
|
|
318
|
-
|
|
319
|
-
data = __write_nameable(item, add_indent(indent))
|
|
320
|
-
attributes = data["Attributes"].replace("'", '"')
|
|
321
|
-
outfile = f"{indent}<{head}{attributes}>"
|
|
322
|
-
outfile += __export_intern_data(data)
|
|
323
|
-
if isinstance(item, Agency) and len(item.contacts) > 0:
|
|
324
|
-
for contact in item.contacts:
|
|
325
|
-
outfile += __write_contact(contact, add_indent(indent))
|
|
326
|
-
if isinstance(item, Concept) and (
|
|
327
|
-
item.codes is not None
|
|
328
|
-
or item.facets is not None
|
|
329
|
-
or item.dtype is not None
|
|
330
|
-
):
|
|
331
|
-
outfile += f"{add_indent(indent)}<{ABBR_STR}:{CORE_REP}>"
|
|
332
|
-
if item.codes is not None:
|
|
333
|
-
outfile += __write_enumeration(item.codes, add_indent(indent))
|
|
334
|
-
if item.facets is not None or item.dtype is not None:
|
|
335
|
-
outfile += __write_text_format(
|
|
336
|
-
item.dtype, item.facets, TEXT_FORMAT, add_indent(indent)
|
|
337
|
-
)
|
|
338
|
-
outfile += f"{add_indent(indent)}</{ABBR_STR}:{CORE_REP}>"
|
|
339
|
-
outfile += f"{indent}</{head}>"
|
|
340
|
-
return outfile
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
def __write_components(item: DataStructureDefinition, indent: str) -> str:
|
|
344
|
-
"""Writes the components to the XML file."""
|
|
345
|
-
outfile = f"{indent}<{ABBR_STR}:{DSD_COMPS}>"
|
|
346
|
-
|
|
347
|
-
components: Dict[str, Any] = {
|
|
348
|
-
DIM: [],
|
|
349
|
-
ATT: [],
|
|
350
|
-
PRIM_MEASURE: [],
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
for comp in item.components:
|
|
354
|
-
if comp.role == Role.DIMENSION:
|
|
355
|
-
components[DIM].append(comp)
|
|
356
|
-
elif comp.role == Role.ATTRIBUTE:
|
|
357
|
-
components[ATT].append(comp)
|
|
358
|
-
else:
|
|
359
|
-
components[PRIM_MEASURE].append(comp)
|
|
360
|
-
|
|
361
|
-
position = 1
|
|
362
|
-
for _, comps in components.items():
|
|
363
|
-
if comps:
|
|
364
|
-
role_name = ROLE_MAPPING[comps[0].role]
|
|
365
|
-
if role_name == PRIM_MEASURE:
|
|
366
|
-
role_name = MEASURE
|
|
367
|
-
outfile += f"{add_indent(indent)}<{ABBR_STR}:{role_name}List>"
|
|
368
|
-
for comp in comps:
|
|
369
|
-
outfile += __write_component(
|
|
370
|
-
comp, position, add_indent(add_indent(indent)), components
|
|
371
|
-
)
|
|
372
|
-
position += 1
|
|
373
|
-
outfile += f"{add_indent(indent)}</{ABBR_STR}:{role_name}List>"
|
|
374
|
-
|
|
375
|
-
outfile += f"{indent}</{ABBR_STR}:{DSD_COMPS}>"
|
|
376
|
-
return outfile
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
def __write_attribute_relation(
|
|
380
|
-
item: Component, indent: str, component_info: Dict[str, Any]
|
|
381
|
-
) -> str:
|
|
382
|
-
outfile = f"{indent}<{ABBR_STR}:{ATT_REL}>"
|
|
383
|
-
att_rel = item.attachment_level
|
|
384
|
-
if att_rel is None or att_rel == "D":
|
|
385
|
-
outfile += f"{add_indent(indent)}<{ABBR_STR}:None/>"
|
|
386
|
-
else:
|
|
387
|
-
# Check if it is a list of Dimensions or it is related to the
|
|
388
|
-
# primary measure
|
|
389
|
-
if "," in att_rel:
|
|
390
|
-
comps_to_relate = att_rel.split(",")
|
|
391
|
-
elif att_rel == "O":
|
|
392
|
-
comps_to_relate = [component_info[PRIM_MEASURE][0].id]
|
|
393
|
-
else:
|
|
394
|
-
comps_to_relate = [att_rel]
|
|
395
|
-
|
|
396
|
-
dim_names = [comp.id for comp in component_info[DIM]]
|
|
397
|
-
|
|
398
|
-
for comp_name in comps_to_relate:
|
|
399
|
-
role = Role.DIMENSION if comp_name in dim_names else Role.MEASURE
|
|
400
|
-
related_role = ROLE_MAPPING[role]
|
|
401
|
-
outfile += f"{add_indent(indent)}<{ABBR_STR}:{related_role}>"
|
|
402
|
-
outfile += (
|
|
403
|
-
f"{add_indent(add_indent(indent))}"
|
|
404
|
-
f"<{REF} {ID}={comp_name!r}/>"
|
|
405
|
-
)
|
|
406
|
-
outfile += f"{add_indent(indent)}</{ABBR_STR}:{related_role}>"
|
|
407
|
-
outfile += f"{indent}</{ABBR_STR}:{ATT_REL}>"
|
|
408
|
-
|
|
409
|
-
return outfile
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
def __write_component(
|
|
413
|
-
item: Component, position: int, indent: str, component_info: Dict[str, Any]
|
|
414
|
-
) -> str:
|
|
415
|
-
"""Writes the component to the XML file."""
|
|
416
|
-
role_name = ROLE_MAPPING[item.role]
|
|
417
|
-
if role_name == DIM and item.id == "TIME_PERIOD":
|
|
418
|
-
role_name = TIME_DIM
|
|
419
|
-
head = f"{indent}<{ABBR_STR}:{role_name} "
|
|
420
|
-
|
|
421
|
-
attributes = ""
|
|
422
|
-
attribute_relation = ""
|
|
423
|
-
if item.role == Role.ATTRIBUTE:
|
|
424
|
-
status = MANDATORY if item.required else CONDITIONAL
|
|
425
|
-
attributes += f"{AS_STATUS}={status!r} "
|
|
426
|
-
attribute_relation = __write_attribute_relation(
|
|
427
|
-
item, add_indent(indent), component_info
|
|
428
|
-
)
|
|
429
|
-
|
|
430
|
-
attributes += f"{ID}={item.id!r}"
|
|
431
|
-
if item.role == Role.DIMENSION:
|
|
432
|
-
attributes += f" {POSITION}={str(position)!r}"
|
|
433
|
-
|
|
434
|
-
if item.urn is not None:
|
|
435
|
-
attributes += f" {URN.lower()}={item.urn!r}"
|
|
436
|
-
|
|
437
|
-
attributes += ">"
|
|
438
|
-
|
|
439
|
-
concept_identity = __write_concept_identity(
|
|
440
|
-
item.concept, add_indent(indent)
|
|
441
|
-
)
|
|
442
|
-
representation = __write_representation(item, add_indent(indent))
|
|
443
|
-
|
|
444
|
-
outfile = head
|
|
445
|
-
outfile += attributes
|
|
446
|
-
outfile += concept_identity
|
|
447
|
-
outfile += representation
|
|
448
|
-
outfile += attribute_relation
|
|
449
|
-
|
|
450
|
-
outfile += f"{indent}</{ABBR_STR}:{role_name}>"
|
|
451
|
-
|
|
452
|
-
outfile = outfile.replace("'", '"')
|
|
453
|
-
return outfile
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
def __write_concept_identity(
|
|
457
|
-
identity: Union[Concept, ItemReference], indent: str
|
|
458
|
-
) -> str:
|
|
459
|
-
if isinstance(identity, ItemReference):
|
|
460
|
-
ref = identity
|
|
461
|
-
else:
|
|
462
|
-
ref = parse_item_urn(identity.urn) # type: ignore[arg-type]
|
|
463
|
-
|
|
464
|
-
outfile = f"{indent}<{ABBR_STR}:{CON_ID}>"
|
|
465
|
-
outfile += f"{add_indent(indent)}<{REF} "
|
|
466
|
-
outfile += f"{AGENCY_ID}={ref.agency!r} "
|
|
467
|
-
outfile += f"{CLASS}={CON!r} "
|
|
468
|
-
outfile += f"{ID}={ref.item_id!r} "
|
|
469
|
-
outfile += f"{PAR_ID}={ref.id!r} "
|
|
470
|
-
outfile += f"{PAR_VER}={ref.version!r} "
|
|
471
|
-
outfile += f"{PACKAGE}={CS.lower()!r}/>"
|
|
472
|
-
outfile += f"{indent}</{ABBR_STR}:{CON_ID}>"
|
|
473
|
-
|
|
474
|
-
outfile = outfile.replace("'", '"')
|
|
475
|
-
return outfile
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
def __write_representation(item: Component, indent: str) -> str:
|
|
479
|
-
representation = ""
|
|
480
|
-
local_representation = ""
|
|
481
|
-
|
|
482
|
-
if item.local_codes is not None:
|
|
483
|
-
local_representation += __write_enumeration(item.local_codes, indent)
|
|
484
|
-
|
|
485
|
-
if item.local_facets is not None or item.local_dtype is not None:
|
|
486
|
-
type_ = ENUM_FORMAT if item.local_codes is not None else TEXT_FORMAT
|
|
487
|
-
local_representation += __write_text_format(
|
|
488
|
-
item.local_dtype, item.local_facets, type_, indent
|
|
489
|
-
)
|
|
490
|
-
|
|
491
|
-
representation += f"{indent}<{ABBR_STR}:{LOCAL_REP}>"
|
|
492
|
-
if len(local_representation) == 0:
|
|
493
|
-
representation += f"{add_indent(indent)}<{ABBR_STR}:{TEXT_FORMAT}/>"
|
|
494
|
-
representation += local_representation
|
|
495
|
-
representation += f"{indent}</{ABBR_STR}:{LOCAL_REP}>"
|
|
496
|
-
|
|
497
|
-
return representation
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
def __write_text_format(
|
|
501
|
-
dtype: Optional[DataType],
|
|
502
|
-
facets: Optional[Facets],
|
|
503
|
-
type_: str,
|
|
504
|
-
indent: str,
|
|
505
|
-
) -> str:
|
|
506
|
-
"""Writes the text format to the XML file."""
|
|
507
|
-
outfile = f"{add_indent(indent)}<{ABBR_STR}:{type_}"
|
|
508
|
-
if facets is not None:
|
|
509
|
-
active_facets = facets.__str__().replace("=", '="').split(", ")
|
|
510
|
-
for facet in active_facets:
|
|
511
|
-
facet = __to_lower_camel_case(facet)
|
|
512
|
-
outfile += f' {facet}"'
|
|
513
|
-
if dtype is not None:
|
|
514
|
-
outfile += f" {TEXT_TYPE}={dtype.value!r}"
|
|
515
|
-
outfile += "/>"
|
|
516
|
-
|
|
517
|
-
outfile = outfile.replace("'", '"')
|
|
518
|
-
return outfile
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
def __write_enumeration(codes: Union[Codelist, Hierarchy], indent: str) -> str:
|
|
522
|
-
"""Writes the enumeration to the XML file."""
|
|
523
|
-
ref = parse_short_urn(codes.short_urn)
|
|
524
|
-
|
|
525
|
-
outfile = f"{add_indent(indent)}<{ABBR_STR}:{ENUM}>"
|
|
526
|
-
outfile += f"{add_indent(add_indent(indent))}<{REF} "
|
|
527
|
-
outfile += f"{AGENCY_ID}={ref.agency!r} "
|
|
528
|
-
outfile += f"{CLASS}={CL!r} "
|
|
529
|
-
outfile += f"{ID}={ref.id!r} "
|
|
530
|
-
outfile += f"{PACKAGE}={CL_LOW!r} "
|
|
531
|
-
outfile += f"{VERSION}={ref.version!r}/>"
|
|
532
|
-
outfile += f"{add_indent(indent)}</{ABBR_STR}:{ENUM}>"
|
|
533
|
-
|
|
534
|
-
outfile = outfile.replace("'", '"')
|
|
535
|
-
return outfile
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
def __write_structure(item: str, indent: str) -> str:
|
|
539
|
-
"""Writes the dataflow structure to the XML file."""
|
|
540
|
-
ref = parse_short_urn(item)
|
|
541
|
-
outfile = f"{indent}<{ABBR_STR}:Structure>"
|
|
542
|
-
outfile += (
|
|
543
|
-
f"{add_indent(indent)}<{REF} "
|
|
544
|
-
f'{PACKAGE}="datastructure" '
|
|
545
|
-
f"{AGENCY_ID}={ref.agency!r} "
|
|
546
|
-
f"{ID}={ref.id!r} "
|
|
547
|
-
f"{VERSION}={ref.version!r} "
|
|
548
|
-
f"{CLASS}={DSD!r}/>"
|
|
549
|
-
)
|
|
550
|
-
outfile += f"{indent}</{ABBR_STR}:Structure>"
|
|
551
|
-
|
|
552
|
-
outfile = outfile.replace("'", '"')
|
|
553
|
-
return outfile
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
def __write_scheme(item_scheme: Any, indent: str, scheme: str) -> str:
|
|
557
|
-
"""Writes the scheme to the XML file."""
|
|
558
|
-
label = f"{ABBR_STR}:{scheme}"
|
|
559
|
-
components = ""
|
|
560
|
-
data = __write_maintainable(item_scheme, indent)
|
|
561
|
-
|
|
562
|
-
if scheme == DSD:
|
|
563
|
-
components = __write_components(item_scheme, add_indent(indent))
|
|
564
|
-
|
|
565
|
-
if scheme not in [
|
|
566
|
-
DSD,
|
|
567
|
-
DFW,
|
|
568
|
-
RULE_SCHEME,
|
|
569
|
-
UDO_SCHEME,
|
|
570
|
-
TRANS_SCHEME,
|
|
571
|
-
VTL_MAPPING_SCHEME,
|
|
572
|
-
]:
|
|
573
|
-
data["Attributes"] += (
|
|
574
|
-
f" isPartial={str(item_scheme.is_final).lower()!r}"
|
|
575
|
-
)
|
|
576
|
-
if scheme in [RULE_SCHEME, UDO_SCHEME, TRANS_SCHEME, VTL_MAPPING_SCHEME]:
|
|
577
|
-
data["Attributes"] += f" {_write_vtl(item_scheme, indent)}"
|
|
578
|
-
|
|
579
|
-
outfile = ""
|
|
580
|
-
|
|
581
|
-
attributes = data.get("Attributes") or ""
|
|
582
|
-
attributes = attributes.replace("'", '"')
|
|
583
|
-
|
|
584
|
-
outfile += f"{indent}<{label}{attributes}>"
|
|
585
|
-
|
|
586
|
-
outfile += __export_intern_data(data)
|
|
587
|
-
|
|
588
|
-
outfile += components
|
|
589
|
-
|
|
590
|
-
if scheme == DFW:
|
|
591
|
-
outfile += __write_structure(item_scheme.structure, add_indent(indent))
|
|
592
|
-
|
|
593
|
-
if scheme not in [
|
|
594
|
-
DSD,
|
|
595
|
-
DFW,
|
|
596
|
-
RULE_SCHEME,
|
|
597
|
-
UDO_SCHEME,
|
|
598
|
-
TRANS_SCHEME,
|
|
599
|
-
VTL_MAPPING_SCHEME,
|
|
600
|
-
]:
|
|
601
|
-
for item in item_scheme.items:
|
|
602
|
-
outfile += __write_item(item, add_indent(indent))
|
|
603
|
-
if scheme in [RULE_SCHEME, UDO_SCHEME, TRANS_SCHEME, VTL_MAPPING_SCHEME]:
|
|
604
|
-
for item in item_scheme.items:
|
|
605
|
-
outfile += _write_vtl(item, add_indent(indent))
|
|
606
|
-
outfile += _write_vtl_references(item_scheme, add_indent(indent))
|
|
607
|
-
outfile += f"{indent}</{label}>"
|
|
608
|
-
|
|
609
|
-
return outfile
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
def __write_metadata_element(
|
|
613
|
-
package: Dict[str, Any], key: str, prettyprint: object
|
|
614
|
-
) -> str:
|
|
615
|
-
"""Writes the metadata element to the XML file.
|
|
616
|
-
|
|
617
|
-
Args:
|
|
618
|
-
package: The package to be written
|
|
619
|
-
key: The key to be used
|
|
620
|
-
prettyprint: Prettyprint or not
|
|
621
|
-
|
|
622
|
-
Returns:
|
|
623
|
-
A string with the metadata element
|
|
624
|
-
"""
|
|
625
|
-
outfile = ""
|
|
626
|
-
nl = "\n" if prettyprint else ""
|
|
627
|
-
child2 = "\t\t" if prettyprint else ""
|
|
628
|
-
|
|
629
|
-
base_indent = f"{nl}{child2}"
|
|
630
|
-
|
|
631
|
-
if key in package:
|
|
632
|
-
outfile += f"{base_indent}<{ABBR_STR}:{MSG_CONTENT_PKG[key]}>"
|
|
633
|
-
for element in package[key].values():
|
|
634
|
-
item = (
|
|
635
|
-
DSD
|
|
636
|
-
if issubclass(element.__class__, DataStructureDefinition)
|
|
637
|
-
else (
|
|
638
|
-
AGENCIES
|
|
639
|
-
if element.id == "AGENCIES"
|
|
640
|
-
else type(element).__name__
|
|
641
|
-
)
|
|
642
|
-
)
|
|
643
|
-
outfile += __write_scheme(element, add_indent(base_indent), item)
|
|
644
|
-
outfile += f"{base_indent}</{ABBR_STR}:{MSG_CONTENT_PKG[key]}>"
|
|
645
|
-
|
|
646
|
-
return outfile
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
def __get_outfile(obj_: Dict[str, Any], key: str = "") -> str:
|
|
650
|
-
"""Generates an outfile from the object.
|
|
651
|
-
|
|
652
|
-
Args:
|
|
653
|
-
obj_: The object to be used
|
|
654
|
-
key: The key to be used
|
|
655
|
-
|
|
656
|
-
Returns:
|
|
657
|
-
A string with the outfile
|
|
658
|
-
|
|
659
|
-
"""
|
|
660
|
-
element = obj_.get(key) or []
|
|
661
|
-
|
|
662
|
-
return "".join(element)
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
def __export_intern_data(data: Dict[str, Any]) -> str:
|
|
666
|
-
"""Export internal data (Annotations, Name, Description) on the XML file.
|
|
667
|
-
|
|
668
|
-
Args:
|
|
669
|
-
data: Information to be exported
|
|
670
|
-
|
|
671
|
-
Returns:
|
|
672
|
-
The XML string with the exported data
|
|
673
|
-
"""
|
|
674
|
-
outfile = __get_outfile(data, "Annotations")
|
|
675
|
-
outfile += __get_outfile(data, "Name")
|
|
676
|
-
outfile += __get_outfile(data, "Description")
|
|
677
|
-
|
|
678
|
-
return outfile
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
def __write_structures(content: Dict[str, Any], prettyprint: bool) -> str:
|
|
682
|
-
"""Writes the structures to the XML file.
|
|
683
|
-
|
|
684
|
-
Args:
|
|
685
|
-
content: The Message Content to be written
|
|
686
|
-
prettyprint: Prettyprint or not
|
|
687
|
-
|
|
688
|
-
Returns:
|
|
689
|
-
A string with the structures
|
|
690
|
-
"""
|
|
691
|
-
nl = "\n" if prettyprint else ""
|
|
692
|
-
child1 = "\t" if prettyprint else ""
|
|
693
|
-
|
|
694
|
-
outfile = f"{nl}{child1}<{ABBR_MSG}:Structures>"
|
|
695
|
-
|
|
696
|
-
for key in MSG_CONTENT_PKG:
|
|
697
|
-
outfile += __write_metadata_element(content, key, prettyprint)
|
|
698
|
-
|
|
699
|
-
outfile += f"{nl}{child1}</{ABBR_MSG}:Structures>"
|
|
700
|
-
|
|
701
|
-
# Replace & with & in the outfile
|
|
702
|
-
outfile = outfile.replace("& ", "& ")
|
|
703
|
-
|
|
704
|
-
return outfile
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
def _write_vtl(item_or_scheme: Union[Item, ItemScheme], indent: str) -> str:
|
|
708
|
-
"""Writes the VTL attribute to the XML file for a single item.
|
|
709
|
-
|
|
710
|
-
This function writes an item or an item scheme to the XML file,
|
|
711
|
-
following the standard format.
|
|
712
|
-
|
|
713
|
-
Args:
|
|
714
|
-
item_or_scheme: The item or item scheme to be written
|
|
715
|
-
Item: The item to be written
|
|
716
|
-
ItemScheme: The item scheme to be written
|
|
717
|
-
indent: The current indentation level
|
|
718
|
-
"""
|
|
719
|
-
outfile = ""
|
|
720
|
-
|
|
721
|
-
if isinstance(item_or_scheme, Item):
|
|
722
|
-
label = ""
|
|
723
|
-
nameable = __write_nameable(item_or_scheme, add_indent(indent))
|
|
724
|
-
attrib = nameable["Attributes"].replace("'", '"')
|
|
725
|
-
data = __export_intern_data(nameable)
|
|
726
|
-
|
|
727
|
-
if isinstance(item_or_scheme, Ruleset):
|
|
728
|
-
label = f"{ABBR_STR}:{RULE}"
|
|
729
|
-
data += f"{add_indent(indent)}<{ABBR_STR}:RulesetDefinition>"
|
|
730
|
-
data += (
|
|
731
|
-
f"{__escape_xml(item_or_scheme.ruleset_definition)}"
|
|
732
|
-
f"</{ABBR_STR}:RulesetDefinition>"
|
|
733
|
-
)
|
|
734
|
-
attrib += (
|
|
735
|
-
f" rulesetScope={item_or_scheme.ruleset_scope!r} "
|
|
736
|
-
f"rulesetType={item_or_scheme.ruleset_type!r}"
|
|
737
|
-
)
|
|
738
|
-
|
|
739
|
-
if isinstance(item_or_scheme, Transformation):
|
|
740
|
-
label = f"{ABBR_STR}:{TRANSFORMATION}"
|
|
741
|
-
data += f"{add_indent(indent)}<{ABBR_STR}:Expression>"
|
|
742
|
-
data += (
|
|
743
|
-
f"{__escape_xml(item_or_scheme.expression)}"
|
|
744
|
-
f"</{ABBR_STR}:Expression>"
|
|
745
|
-
)
|
|
746
|
-
data += f"{add_indent(indent)}<{ABBR_STR}:Result>"
|
|
747
|
-
data += f"{item_or_scheme.result}</{ABBR_STR}:Result>"
|
|
748
|
-
attrib += (
|
|
749
|
-
f" isPersistent="
|
|
750
|
-
f"{str(item_or_scheme.is_persistent).lower()!r}"
|
|
751
|
-
)
|
|
752
|
-
|
|
753
|
-
if isinstance(item_or_scheme, UserDefinedOperator):
|
|
754
|
-
label = f"{ABBR_STR}:{UDO}"
|
|
755
|
-
data += f"{add_indent(indent)}<{ABBR_STR}:OperatorDefinition>"
|
|
756
|
-
data += (
|
|
757
|
-
f"{__escape_xml(item_or_scheme.operator_definition)}"
|
|
758
|
-
f"</{ABBR_STR}:OperatorDefinition>"
|
|
759
|
-
)
|
|
760
|
-
if isinstance(item_or_scheme, VtlDataflowMapping):
|
|
761
|
-
label = f"{ABBR_STR}:{VTLMAPPING}"
|
|
762
|
-
data += f"{add_indent(indent)}<{ABBR_STR}:Dataflow>"
|
|
763
|
-
reference = item_or_scheme.dataflow
|
|
764
|
-
data += (
|
|
765
|
-
f"{indent}\t\t<{REF} package='datastructure' "
|
|
766
|
-
f"agencyID={reference.agency!r} id={reference.id!r} "
|
|
767
|
-
f"version={reference.version!r} class={DFW!r} />"
|
|
768
|
-
f"{add_indent(indent)}</{ABBR_STR}:Dataflow>"
|
|
769
|
-
)
|
|
770
|
-
attrib += f" alias={item_or_scheme.dataflow_alias!r}"
|
|
771
|
-
|
|
772
|
-
outfile += f"{indent}<{label}{attrib}>"
|
|
773
|
-
outfile += data
|
|
774
|
-
outfile += f"{indent}</{label}>"
|
|
775
|
-
|
|
776
|
-
if isinstance(item_or_scheme, VtlScheme):
|
|
777
|
-
outfile += f" vtlVersion={item_or_scheme.vtl_version!r}"
|
|
778
|
-
|
|
779
|
-
outfile = outfile.replace("'", '"')
|
|
780
|
-
|
|
781
|
-
return outfile
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
def _write_vtl_references(scheme: ItemScheme, indent: str) -> str:
|
|
785
|
-
"""Writes references to VTL elements to the XML file."""
|
|
786
|
-
|
|
787
|
-
def process_references(
|
|
788
|
-
references: Union[Any, Sequence[Any]], element_name: str
|
|
789
|
-
) -> str:
|
|
790
|
-
"""Process the references to VTL elements."""
|
|
791
|
-
outreference = []
|
|
792
|
-
if not isinstance(references, (list, tuple)):
|
|
793
|
-
references = [references]
|
|
794
|
-
|
|
795
|
-
for ref in references:
|
|
796
|
-
if isinstance(ref, Reference):
|
|
797
|
-
outreference.append(
|
|
798
|
-
f"{indent}<{ABBR_STR}:{element_name}>"
|
|
799
|
-
f"{add_indent(indent)}<{REF} "
|
|
800
|
-
f"{PACKAGE}={TRANSFORMATION.lower()!r} "
|
|
801
|
-
f"{AGENCY_ID}={ref.agency!r} "
|
|
802
|
-
f"{ID}={ref.id!r} "
|
|
803
|
-
f"{VERSION}={ref.version!r} "
|
|
804
|
-
f"{CLASS}={ref.sdmx_type!r}/>"
|
|
805
|
-
f"{indent}</{ABBR_STR}:{element_name}>"
|
|
806
|
-
)
|
|
807
|
-
if isinstance(ref, ItemScheme):
|
|
808
|
-
ref_to_use = parse_short_urn(ref.short_urn)
|
|
809
|
-
outreference.append(
|
|
810
|
-
f"{indent}<{ABBR_STR}:{element_name}>"
|
|
811
|
-
f"{add_indent(indent)}<{REF} "
|
|
812
|
-
f"{PACKAGE}={TRANSFORMATION.lower()!r} "
|
|
813
|
-
f"{AGENCY_ID}={ref_to_use.agency!r} "
|
|
814
|
-
f"{ID}={ref_to_use.id!r} "
|
|
815
|
-
f"{VERSION}={ref_to_use.version!r} "
|
|
816
|
-
f"{CLASS}={ref_to_use.sdmx_type!r}/>"
|
|
817
|
-
f"{indent}</{ABBR_STR}:{element_name}>"
|
|
818
|
-
)
|
|
819
|
-
|
|
820
|
-
return "".join(outreference)
|
|
821
|
-
|
|
822
|
-
outfile = ""
|
|
823
|
-
if isinstance(scheme, TransformationScheme):
|
|
824
|
-
outfile += process_references(scheme.ruleset_schemes, "RulesetScheme")
|
|
825
|
-
outfile += process_references(
|
|
826
|
-
scheme.user_defined_operator_schemes, "UserDefinedOperatorScheme"
|
|
827
|
-
)
|
|
828
|
-
if isinstance(scheme, UserDefinedOperatorScheme):
|
|
829
|
-
outfile += process_references(scheme.ruleset_schemes, "RulesetScheme")
|
|
830
|
-
|
|
831
|
-
outfile = outfile.replace("'", '"')
|
|
832
|
-
|
|
833
|
-
return outfile
|
|
834
18
|
|
|
835
19
|
|
|
836
20
|
def write(
|
|
837
|
-
structures: Sequence[
|
|
838
|
-
output_path: str =
|
|
21
|
+
structures: Sequence[MaintainableArtefact],
|
|
22
|
+
output_path: Optional[Union[str, Path]] = None,
|
|
839
23
|
prettyprint: bool = True,
|
|
840
24
|
header: Optional[Header] = None,
|
|
841
25
|
) -> Optional[str]:
|
|
@@ -855,9 +39,9 @@ def write(
|
|
|
855
39
|
if header is None:
|
|
856
40
|
header = Header()
|
|
857
41
|
|
|
858
|
-
content: Dict[str, Dict[str,
|
|
42
|
+
content: Dict[str, Dict[str, MaintainableArtefact]] = {}
|
|
859
43
|
for urn, element in elements.items():
|
|
860
|
-
list_ =
|
|
44
|
+
list_ = STR_DICT_TYPE_LIST_21[type(element)]
|
|
861
45
|
if list_ not in content:
|
|
862
46
|
content[list_] = {}
|
|
863
47
|
content[list_][urn] = element
|
|
@@ -871,7 +55,11 @@ def write(
|
|
|
871
55
|
|
|
872
56
|
outfile += get_end_message(type_, prettyprint)
|
|
873
57
|
|
|
874
|
-
|
|
58
|
+
output_path = (
|
|
59
|
+
str(output_path) if isinstance(output_path, Path) else output_path
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if output_path is None or output_path == "":
|
|
875
63
|
return outfile
|
|
876
64
|
with open(output_path, "w", encoding="UTF-8", errors="replace") as f:
|
|
877
65
|
f.write(outfile)
|