cognite-neat 0.119.1__py3-none-any.whl → 0.119.3__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.
Potentially problematic release.
This version of cognite-neat might be problematic. Click here for more details.
- cognite/neat/_constants.py +34 -70
- cognite/neat/_graph/extractors/__init__.py +0 -6
- cognite/neat/_graph/loaders/_rdf2dms.py +5 -5
- cognite/neat/_graph/queries/__init__.py +1 -1
- cognite/neat/_graph/queries/_base.py +2 -456
- cognite/neat/_graph/queries/_queries.py +16 -0
- cognite/neat/_graph/queries/_select.py +440 -0
- cognite/neat/_graph/queries/_update.py +37 -0
- cognite/neat/_issues/errors/_external.py +4 -2
- cognite/neat/_rules/exporters/_rules2excel.py +240 -107
- cognite/neat/_rules/importers/_yaml2rules.py +7 -1
- cognite/neat/_rules/models/_base_rules.py +16 -1
- cognite/neat/_rules/models/dms/_validation.py +11 -2
- cognite/neat/_rules/transformers/_converters.py +16 -6
- cognite/neat/_session/_drop.py +2 -2
- cognite/neat/_session/_explore.py +4 -4
- cognite/neat/_session/_prepare.py +5 -5
- cognite/neat/_session/_read.py +6 -0
- cognite/neat/_session/_set.py +3 -3
- cognite/neat/_session/_show.py +1 -1
- cognite/neat/_session/_template.py +21 -2
- cognite/neat/_state/README.md +23 -0
- cognite/neat/_store/_graph_store.py +5 -5
- cognite/neat/_version.py +1 -1
- {cognite_neat-0.119.1.dist-info → cognite_neat-0.119.3.dist-info}/METADATA +37 -2
- {cognite_neat-0.119.1.dist-info → cognite_neat-0.119.3.dist-info}/RECORD +29 -28
- cognite/neat/_graph/extractors/_dexpi.py +0 -234
- cognite/neat/_graph/extractors/_iodd.py +0 -403
- cognite/neat/_graph/transformers/_iodd.py +0 -30
- {cognite_neat-0.119.1.dist-info → cognite_neat-0.119.3.dist-info}/LICENSE +0 -0
- {cognite_neat-0.119.1.dist-info → cognite_neat-0.119.3.dist-info}/WHEEL +0 -0
- {cognite_neat-0.119.1.dist-info → cognite_neat-0.119.3.dist-info}/entry_points.txt +0 -0
cognite/neat/_session/_read.py
CHANGED
|
@@ -511,6 +511,8 @@ class CSVReadAPI(BaseReadAPI):
|
|
|
511
511
|
column_with_identifier = "UNIQUE_TAG_NAME"
|
|
512
512
|
neat.read.csv("url_or_path_to_csv_file", type=type_described_in_table, primary_key=column_with_identifier)
|
|
513
513
|
```
|
|
514
|
+
|
|
515
|
+
!!! note "Method read.csv requires NEATEngine plug-in"
|
|
514
516
|
"""
|
|
515
517
|
|
|
516
518
|
def __call__(self, io: Any, type: str, primary_key: str) -> None:
|
|
@@ -565,6 +567,8 @@ class XMLReadAPI(BaseReadAPI):
|
|
|
565
567
|
neat.read.xml.dexpi("url_or_path_to_dexpi_file")
|
|
566
568
|
```
|
|
567
569
|
|
|
570
|
+
!!! note "Method read.xml.dexpi requires NEATEngine plug-in"
|
|
571
|
+
|
|
568
572
|
!!! note "This method bundles several graph transformers which"
|
|
569
573
|
- attach values of generic attributes to nodes
|
|
570
574
|
- create associations between nodes
|
|
@@ -627,6 +631,8 @@ class XMLReadAPI(BaseReadAPI):
|
|
|
627
631
|
neat.read.xml.aml("url_or_path_to_aml_file")
|
|
628
632
|
```
|
|
629
633
|
|
|
634
|
+
!!! note "Method read.xml.aml requires NEATEngine plug-in"
|
|
635
|
+
|
|
630
636
|
!!! note "This method bundles several graph transformers which"
|
|
631
637
|
- attach values of attributes to nodes
|
|
632
638
|
- remove unused attributes
|
cognite/neat/_session/_set.py
CHANGED
|
@@ -76,8 +76,8 @@ class SetInstances:
|
|
|
76
76
|
neat.set.instances.replace_type("Asset", "assetCategory")
|
|
77
77
|
```
|
|
78
78
|
"""
|
|
79
|
-
type_uri = self._state.instances.store.queries.type_uri(current_type)
|
|
80
|
-
property_uri = self._state.instances.store.queries.property_uri(property_type)
|
|
79
|
+
type_uri = self._state.instances.store.queries.select.type_uri(current_type)
|
|
80
|
+
property_uri = self._state.instances.store.queries.select.property_uri(property_type)
|
|
81
81
|
|
|
82
82
|
if not type_uri:
|
|
83
83
|
raise NeatValueError(f"Type {current_type} does not exist in the graph.")
|
|
@@ -93,7 +93,7 @@ class SetInstances:
|
|
|
93
93
|
f"{property_type} has multiple ids found in the graph: {humanize_collection(property_uri)}."
|
|
94
94
|
)
|
|
95
95
|
|
|
96
|
-
if not self._state.instances.store.queries.type_with_property(type_uri[0], property_uri[0]):
|
|
96
|
+
if not self._state.instances.store.queries.select.type_with_property(type_uri[0], property_uri[0]):
|
|
97
97
|
raise NeatValueError(f"Property {property_type} is not defined for type {current_type}.")
|
|
98
98
|
|
|
99
99
|
self._state.instances.store.transform(SetType(type_uri[0], property_uri[0], drop_property))
|
cognite/neat/_session/_show.py
CHANGED
|
@@ -247,7 +247,7 @@ class ShowInstanceAPI(ShowBaseAPI):
|
|
|
247
247
|
|
|
248
248
|
di_graph = nx.DiGraph()
|
|
249
249
|
|
|
250
|
-
types = [type_ for type_, _ in self._state.instances.store.queries.summarize_instances()]
|
|
250
|
+
types = [type_ for type_, _ in self._state.instances.store.queries.select.summarize_instances()]
|
|
251
251
|
hex_colored_types = _generate_hex_color_per_type(types)
|
|
252
252
|
|
|
253
253
|
for ( # type: ignore
|
|
@@ -9,6 +9,7 @@ from cognite.neat._rules._shared import ReadRules
|
|
|
9
9
|
from cognite.neat._rules.exporters import ExcelExporter
|
|
10
10
|
from cognite.neat._rules.importers import ExcelImporter
|
|
11
11
|
from cognite.neat._rules.models import InformationInputRules
|
|
12
|
+
from cognite.neat._rules.models._base_rules import RoleTypes
|
|
12
13
|
from cognite.neat._rules.models.dms import DMSValidation
|
|
13
14
|
from cognite.neat._rules.transformers import (
|
|
14
15
|
AddCogniteProperties,
|
|
@@ -174,7 +175,21 @@ class TemplateAPI:
|
|
|
174
175
|
self._state.last_reference = last_rules
|
|
175
176
|
return issues
|
|
176
177
|
|
|
177
|
-
def
|
|
178
|
+
def conceptual_model(self, io: Any) -> None:
|
|
179
|
+
"""This method will create a template for a conceptual data modeling
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
io: file path to the Excel sheet
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
reader = NeatReader.create(io)
|
|
186
|
+
path = reader.materialize_path()
|
|
187
|
+
|
|
188
|
+
ExcelExporter().template(RoleTypes.information, path)
|
|
189
|
+
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
def extension(self, io: Any, output: str | Path | None = None, dummy_property: str = "GUID") -> IssueList:
|
|
178
193
|
"""Creates a template for an extension of a Cognite model.
|
|
179
194
|
|
|
180
195
|
The input is a spreadsheet of a conceptual model in which the concepts are defined
|
|
@@ -193,6 +208,10 @@ class TemplateAPI:
|
|
|
193
208
|
io: The input spreadsheet.
|
|
194
209
|
output: The output spreadsheet. If None, the output will be the same
|
|
195
210
|
as the input with `_extension` added to the name.
|
|
211
|
+
dummy_property: The dummy property to use as placeholder for user-defined properties
|
|
212
|
+
for each user-defined concept, and to alleviate need for usage of filters in
|
|
213
|
+
physical data model. When converting a data model, it is recommended to have at least
|
|
214
|
+
one property for each concept. This ensures that you follow that recommendation.
|
|
196
215
|
"""
|
|
197
216
|
ExperimentalFlags.extension.warn()
|
|
198
217
|
reader = NeatReader.create(io)
|
|
@@ -214,7 +233,7 @@ class TemplateAPI:
|
|
|
214
233
|
raise NeatSessionError(f"The input {reader.name} must contain an InformationInputRules object. ")
|
|
215
234
|
if self._state.client is None:
|
|
216
235
|
raise NeatSessionError("Client must be set in the session to run the extension.")
|
|
217
|
-
modified = AddCogniteProperties(self._state.client).transform(read)
|
|
236
|
+
modified = AddCogniteProperties(self._state.client, dummy_property).transform(read)
|
|
218
237
|
if modified.rules is not None:
|
|
219
238
|
# If rules are None there will be issues that are already caught.
|
|
220
239
|
info = modified.rules.as_verified_rules()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# NeatState
|
|
2
|
+
|
|
3
|
+
**IN DEVELOPMENT**
|
|
4
|
+
The neat state controls the `NeatGraphStore` and `NeatRuleStore`. It is implementing a state machine pattern
|
|
5
|
+
to ensure valid state transitions. The diagram below shows the state machine:
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
stateDiagram-v2
|
|
9
|
+
state excel_importer <<fork>>
|
|
10
|
+
[*] --> EmptyState
|
|
11
|
+
EmptyState --> Instances: extractor
|
|
12
|
+
Instances --> Instances: graph transformer
|
|
13
|
+
EmptyState --> Conceptual: importer
|
|
14
|
+
EmptyState --> Physical: DMS importer/extractor
|
|
15
|
+
Instances --> Conceptual: infer/importer
|
|
16
|
+
Conceptual --> Physical: convert
|
|
17
|
+
Conceptual --> Conceptual: conceptual transformer/infer
|
|
18
|
+
Physical --> Physical: physical transformer/infer
|
|
19
|
+
EmptyState --> excel_importer: Excel/YAML importer
|
|
20
|
+
state excel_importer <<join>>
|
|
21
|
+
excel_importer --> Conceptual
|
|
22
|
+
excel_importer --> Physical
|
|
23
|
+
```
|
|
@@ -243,10 +243,10 @@ class NeatGraphStore:
|
|
|
243
243
|
) -> Iterable[tuple[URIRef, dict[str | InstanceType, list[Any]]]]:
|
|
244
244
|
named_graph = named_graph or self.default_named_graph
|
|
245
245
|
|
|
246
|
-
instance_ids = self.queries.list_instances_ids(class_uri, named_graph=named_graph)
|
|
246
|
+
instance_ids = self.queries.select.list_instances_ids(class_uri, named_graph=named_graph)
|
|
247
247
|
|
|
248
248
|
for instance_id in instance_ids:
|
|
249
|
-
if res := self.queries.describe(
|
|
249
|
+
if res := self.queries.select.describe(
|
|
250
250
|
instance_id=instance_id,
|
|
251
251
|
instance_type=class_uri,
|
|
252
252
|
property_renaming_config=property_renaming_config,
|
|
@@ -363,7 +363,7 @@ class NeatGraphStore:
|
|
|
363
363
|
def summary(self) -> dict[URIRef, pd.DataFrame]:
|
|
364
364
|
return {
|
|
365
365
|
named_graph: pd.DataFrame(
|
|
366
|
-
self.queries.summarize_instances(named_graph),
|
|
366
|
+
self.queries.select.summarize_instances(named_graph),
|
|
367
367
|
columns=["Type", "Occurrence"],
|
|
368
368
|
)
|
|
369
369
|
for named_graph in self.named_graphs
|
|
@@ -371,7 +371,7 @@ class NeatGraphStore:
|
|
|
371
371
|
|
|
372
372
|
@property
|
|
373
373
|
def multi_type_instances(self) -> dict[URIRef, dict[str, list[str]]]:
|
|
374
|
-
return {named_graph: self.queries.multi_type_instances(named_graph) for named_graph in self.named_graphs}
|
|
374
|
+
return {named_graph: self.queries.select.multi_type_instances(named_graph) for named_graph in self.named_graphs}
|
|
375
375
|
|
|
376
376
|
def _repr_html_(self) -> str:
|
|
377
377
|
provenance = self.provenance._repr_html_()
|
|
@@ -448,4 +448,4 @@ class NeatGraphStore:
|
|
|
448
448
|
@property
|
|
449
449
|
def empty(self) -> bool:
|
|
450
450
|
"""Cheap way to check if the graph store is empty."""
|
|
451
|
-
return not self.queries.has_data()
|
|
451
|
+
return not self.queries.select.has_data()
|
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.119.
|
|
1
|
+
__version__ = "0.119.3"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: cognite-neat
|
|
3
|
-
Version: 0.119.
|
|
3
|
+
Version: 0.119.3
|
|
4
4
|
Summary: Knowledge graph transformation
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: Nikola Vasiljevic
|
|
@@ -80,7 +80,42 @@ NEAT is a domain expert centric and developer friendly solution for rapid:
|
|
|
80
80
|
NEAT is using open and globally recognized standards maintained by the [World Wide Web Consortium (W3C)](https://www.w3.org/RDF/).
|
|
81
81
|
NEAT represents an essential tool for creation of standardized, machine-actionable, linked and semantic (meta)data.
|
|
82
82
|
|
|
83
|
-
> NEAT is
|
|
83
|
+
> NEAT is a funny acronym derived from k**N**owl**Ed**ge gr**A**ph **T**ransformer produced using [ACRONIMIFY](https://acronymify.com/NEAT/?q=knowledge+graph+transformer).
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## History
|
|
87
|
+
|
|
88
|
+
NEAT emerged from years of experience in semantic tooling and knowledge graph development. The foundation was laid in 2020 with [sheet2rdf](https://github.com/nikokaoja/sheet2rdf), an Excel-based tool that trained data stewards to build domain-specific knowledge graphs and supported CI/CD processes in the Dutch Covid program and european wind energy community.
|
|
89
|
+
|
|
90
|
+
By mid of 2022, sheet2rdf was used in several POCs in Cognite. As Cognite's Data Modeling Service (DMS) development progressed, the need for simplified data modeling experience led to demonstration of proto-NEAT, known as [sheet2fdm](https://github.com/cognitedata/sheet2fdm), an extension of sheet2rdf, enabling semantic data model definitions in OWL, SHACL, Python and GraphQL (see e.g., [wind energy data model](https://cognitedata.github.io/wind-energy-data-model/)) using a simplified version of sheet2rdf Excel template.
|
|
91
|
+
|
|
92
|
+
Presented in various forums in 2022, this approach paved the way for NEAT’s formal development in November 2022 to enable cost-saving and empowerment of Cognite customers to self-sufficiently maintain and onboard knowledge graphs to Cognite Data Fusion.
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
## Authorship
|
|
96
|
+
|
|
97
|
+
### Authors
|
|
98
|
+
The plot below shows the NEAT authorship from the start until present day.
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
#### Current authors
|
|
103
|
+
- [Nikola Vasiljević](www.linkedin.com/in/thisisnikola)
|
|
104
|
+
- [Anders Albert](https://www.linkedin.com/in/anders-albert-00790483/)
|
|
105
|
+
- [Rogerio Júnior](https://www.linkedin.com/in/rogerio-saboia-j%C3%BAnior-087118a7/)
|
|
106
|
+
|
|
107
|
+
#### Former authors
|
|
108
|
+
- [Aleksandrs Livincovs](https://www.linkedin.com/in/aleksandrslivincovs/)
|
|
109
|
+
- [Julia Graham](https://www.linkedin.com/in/julia-graham-959a78a7/)
|
|
110
|
+
|
|
111
|
+
### Contributors
|
|
112
|
+
We are very grateful for the contributions made by:
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
- [Marie Solvik Lepoutre](https://www.linkedin.com/in/mslepoutre/), who improved RDF triples projections to Cognite Data Fusion
|
|
116
|
+
- [Bård Henning Tvedt](https://www.linkedin.com/in/bhtvedt/), who implemented IMF importer
|
|
117
|
+
- [Kristina Tomičić](https://www.linkedin.com/in/kristina-tomicic-6bb443108/), who implemented Data Model and Instances visualization
|
|
118
|
+
|
|
84
119
|
|
|
85
120
|
## Installation
|
|
86
121
|
|
|
@@ -12,7 +12,7 @@ cognite/neat/_client/data_classes/neat_sequence.py,sha256=QZWSfWnwk6KlYJvsInco4W
|
|
|
12
12
|
cognite/neat/_client/data_classes/schema.py,sha256=LFRj6-noSO23bxA2I-RdRXMHHc9AHptOXlSVHj1tVHg,25047
|
|
13
13
|
cognite/neat/_client/testing.py,sha256=JnzLQegw2f6SATWRNDQ8Fui6qBYyz7vFgA5myjioohY,1175
|
|
14
14
|
cognite/neat/_config.py,sha256=WT1BS8uADcFvGoUYOOfwFOVq_VBl472TisdoA3wLick,280
|
|
15
|
-
cognite/neat/_constants.py,sha256=
|
|
15
|
+
cognite/neat/_constants.py,sha256=WO_kl74JrUWfuapEah4vC8e3SaRm4XQaTcCcws_n8AU,7382
|
|
16
16
|
cognite/neat/_graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
cognite/neat/_graph/_shared.py,sha256=6avH6mtjxjHI7JDLkXwICxGvZwooGBr6APs1_w1To-A,940
|
|
18
18
|
cognite/neat/_graph/_tracking/__init__.py,sha256=WOwsYieZtCW-iW15YkxUFrfKVVdLWdXHOGGStTwvE8A,91
|
|
@@ -22,7 +22,7 @@ cognite/neat/_graph/examples/Knowledge-Graph-Nordic44-dirty.xml,sha256=ujJip6XBs
|
|
|
22
22
|
cognite/neat/_graph/examples/Knowledge-Graph-Nordic44.xml,sha256=U2Ns-M4LRjT1fBkhmRj63ur7jDzlRtHK9yOLf_npZ_g,1437996
|
|
23
23
|
cognite/neat/_graph/examples/__init__.py,sha256=yAjHVY3b5jOjmbW-iLbhvu7BG014TpGi3K4igkDqW5I,368
|
|
24
24
|
cognite/neat/_graph/examples/skos-capturing-sheet-wind-topics.xlsx,sha256=CV_yK5ZSbYS_ktfIZUPD8Sevs47zpswLXQUDFkGE4Gw,45798
|
|
25
|
-
cognite/neat/_graph/extractors/__init__.py,sha256=
|
|
25
|
+
cognite/neat/_graph/extractors/__init__.py,sha256=OlPnJc55utagsvRcBOt1kIiP68yeK6e2I_TX5S-do1w,2210
|
|
26
26
|
cognite/neat/_graph/extractors/_base.py,sha256=qQE-fl3f1hfqZg5KLF3zLHybP0u8ofRKf4jk7pEHnl4,1907
|
|
27
27
|
cognite/neat/_graph/extractors/_classic_cdf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
cognite/neat/_graph/extractors/_classic_cdf/_assets.py,sha256=9WVFrAtUFAp_AAlb26Rtt2Axz9xsPQYetg7SKVrNCr4,1474
|
|
@@ -35,23 +35,23 @@ cognite/neat/_graph/extractors/_classic_cdf/_labels.py,sha256=7guTZdGFT1r7ItE2VN
|
|
|
35
35
|
cognite/neat/_graph/extractors/_classic_cdf/_relationships.py,sha256=wQDR0DFmGqXFiRHxQtQWNTVk4zVKhZzjrCfCHihXvlU,5293
|
|
36
36
|
cognite/neat/_graph/extractors/_classic_cdf/_sequences.py,sha256=pkCtjH7I1Z6naWDtItHGDirqKSdCTbX_DmXwz_23VLQ,11306
|
|
37
37
|
cognite/neat/_graph/extractors/_classic_cdf/_timeseries.py,sha256=6CmmxWWG2IErfNKOPhsjQ5wSOTUZZMjulpaRbHj0Q-g,1560
|
|
38
|
-
cognite/neat/_graph/extractors/_dexpi.py,sha256=pX1G8nISQ0CP60yXLzsjDPEZ8niuFcm2eb_GTd34ZRA,9489
|
|
39
38
|
cognite/neat/_graph/extractors/_dict.py,sha256=CmXvYkzhRjWDPEaXZAb_YyWCwJDeNzdWBkmFyc2K90s,4321
|
|
40
39
|
cognite/neat/_graph/extractors/_dms.py,sha256=fpr9jmJlnB9IS9sdDA7RV50e_RedF7AEVE25qLlgtp4,13810
|
|
41
40
|
cognite/neat/_graph/extractors/_dms_graph.py,sha256=b_OpXsLZ1xCGEWAqsF5Qk6EknZzxDbcfaZ5NOZGaYrE,9441
|
|
42
|
-
cognite/neat/_graph/extractors/_iodd.py,sha256=iZABOBqLIKyqIQ-RG6Z-FMTRcV5Ul8Ch1gAZygwN1Nk,18540
|
|
43
41
|
cognite/neat/_graph/extractors/_mock_graph_generator.py,sha256=uAGyLMxaeWBlcSFQx0nArr1ChlDF8ZR3EcLM1akwAII,15443
|
|
44
42
|
cognite/neat/_graph/extractors/_raw.py,sha256=xU3SmeLBCeqbs1WBdGCge8ZMnlOU6wgkKX5GRNXc0D0,2499
|
|
45
43
|
cognite/neat/_graph/extractors/_rdf_file.py,sha256=8BWDk1oQPzo2w2HVmGah4rppIGqihX98SBbTB1SB_6o,2900
|
|
46
44
|
cognite/neat/_graph/loaders/__init__.py,sha256=XS6vwmxgBzntg7UuG_ct_1hfhShVnFH5u0gGrdA8WfA,699
|
|
47
45
|
cognite/neat/_graph/loaders/_base.py,sha256=Xq91-4GeQF2XN90-QgEFCU4aJabBXkeFeFXS2k4mWU4,4472
|
|
48
|
-
cognite/neat/_graph/loaders/_rdf2dms.py,sha256=
|
|
49
|
-
cognite/neat/_graph/queries/__init__.py,sha256=
|
|
50
|
-
cognite/neat/_graph/queries/_base.py,sha256=
|
|
46
|
+
cognite/neat/_graph/loaders/_rdf2dms.py,sha256=GD9EuZGs7ybFgTRF4Gm-VOvulny4slSsIOiRPvx7cm8,33908
|
|
47
|
+
cognite/neat/_graph/queries/__init__.py,sha256=W477LMyB4l6HIRbQhJoFgA_MUBwVCh2GBvtFeZu0AUA,53
|
|
48
|
+
cognite/neat/_graph/queries/_base.py,sha256=APevHeeWQDEoOQ0MlBtVlPf9hbZukVkI5fOvt5oPJCE,543
|
|
49
|
+
cognite/neat/_graph/queries/_queries.py,sha256=4BidSQXhdZYZ6_kyG7jMJ2iG0UtSrbQxfmwPM7V167A,466
|
|
50
|
+
cognite/neat/_graph/queries/_select.py,sha256=Bm16EnE-gg0fnzw0dxfhnUgeWRprVBTljdWyqG07QrI,18518
|
|
51
|
+
cognite/neat/_graph/queries/_update.py,sha256=RBY_QyRu1HNAErGxnzpZKiaajb739fC1pd_RHWeeSp0,1285
|
|
51
52
|
cognite/neat/_graph/transformers/__init__.py,sha256=YzC1Z8BuT77NwagWX4Z-F9R9BARLSS7zM4bCdxBbqKg,1761
|
|
52
53
|
cognite/neat/_graph/transformers/_base.py,sha256=8W_PSlsp-jQuKNb9z-lN0Khdq1tKsnWxXAMj2XnXcTc,4561
|
|
53
54
|
cognite/neat/_graph/transformers/_classic_cdf.py,sha256=XjsMj5J0cmZyNzuGnGdlWec_drjaUNSgWwqIIa-YE7Y,25294
|
|
54
|
-
cognite/neat/_graph/transformers/_iodd.py,sha256=oHBS-7wr8n80QfSliRaEzo6jpwRrpJczQg90T-KvD3o,882
|
|
55
55
|
cognite/neat/_graph/transformers/_prune_graph.py,sha256=AJuDqpeaSzk7kY6PlO3JiqGmsfAkEq7s3ubZ5P2r1uI,12615
|
|
56
56
|
cognite/neat/_graph/transformers/_rdfpath.py,sha256=9KCiq8UCeNWcV9VAmyV5gbqwmozUaHRJuMyzVmL3ji4,3156
|
|
57
57
|
cognite/neat/_graph/transformers/_value_type.py,sha256=9Ihk-NMra91c_KOKonKUNgZXwylSrE7pDluzd31NHfM,15797
|
|
@@ -60,7 +60,7 @@ cognite/neat/_issues/_base.py,sha256=UDcx0s9_PqLD4z1NnOxI4wgsk2z6IiVCuJoG-V8aPyQ
|
|
|
60
60
|
cognite/neat/_issues/_contextmanagers.py,sha256=lfASjmq0wHHCJQtgChvOMFZGp_rL513baHSRXbW0ugU,1577
|
|
61
61
|
cognite/neat/_issues/_factory.py,sha256=-22ptgqVeqkaL7RqaIEexhXh3Z27dFvj7Q-9D0tu-4E,2811
|
|
62
62
|
cognite/neat/_issues/errors/__init__.py,sha256=1MK8nHFrN5c2Uiq9r4PkjL8GnBY7TGhcqGNkgQzVmKs,2359
|
|
63
|
-
cognite/neat/_issues/errors/_external.py,sha256=
|
|
63
|
+
cognite/neat/_issues/errors/_external.py,sha256=LIze-eY3gEWEA_UmCGmknoazhKa73-ZGaHDz3xsR9DM,2349
|
|
64
64
|
cognite/neat/_issues/errors/_general.py,sha256=MnBm9V1S-Agr9kUfTMvviBB4_NkuOXamlgJCu2UojEM,849
|
|
65
65
|
cognite/neat/_issues/errors/_properties.py,sha256=T_nquQeEQS3DQY--DQ13acxhGX_-gpUMjWGTBKCh6r8,2536
|
|
66
66
|
cognite/neat/_issues/errors/_resources.py,sha256=qndhGGPdulWpU7G4PkFHsF4Bjflf3lehGV4A0l-BeNI,3966
|
|
@@ -85,7 +85,7 @@ cognite/neat/_rules/catalog/info-rules-imf.xlsx,sha256=vrE5g8vBtsGpwJqygxG3t9I3x
|
|
|
85
85
|
cognite/neat/_rules/exporters/__init__.py,sha256=IYBa0DIYlx8cFItgYRw9W4FY_LmVEjuaqMz3JORZZX0,1204
|
|
86
86
|
cognite/neat/_rules/exporters/_base.py,sha256=VkNMy8wsH-x4tAjS44cXgzzNH0CM2k_4RhkMwK50J7g,2284
|
|
87
87
|
cognite/neat/_rules/exporters/_rules2dms.py,sha256=ddlRbEgKBDLiO-DBM4A5fGpiF5nDgVpzdT3YGchAHNM,19625
|
|
88
|
-
cognite/neat/_rules/exporters/_rules2excel.py,sha256=
|
|
88
|
+
cognite/neat/_rules/exporters/_rules2excel.py,sha256=xh8oDkDAvnLMCYU2iuuDSnUw1G3erxV62KwPSnYs4ok,24264
|
|
89
89
|
cognite/neat/_rules/exporters/_rules2instance_template.py,sha256=6hvuqb5cdO5IqbFKPaoZxIF-fG9gxo0c0pLWLJmKioA,5989
|
|
90
90
|
cognite/neat/_rules/exporters/_rules2ontology.py,sha256=4Z8Qf8H3Ksz0xAtyj5A3oyIKFJNljfMKKqYLxtiQfKs,23057
|
|
91
91
|
cognite/neat/_rules/exporters/_rules2yaml.py,sha256=ggaPR8FO8PwZk1_nhwb5wVHk_C4s6qh1RrlbPkNcbBo,3160
|
|
@@ -105,17 +105,17 @@ cognite/neat/_rules/importers/_rdf/_inference2rules.py,sha256=NSPFEe6ZLHbFTUGTpQ
|
|
|
105
105
|
cognite/neat/_rules/importers/_rdf/_owl2rules.py,sha256=gTMe94DC9xe8NR9KNVHTMTshg_NzVuN1v8Lz95BUshI,3392
|
|
106
106
|
cognite/neat/_rules/importers/_rdf/_shared.py,sha256=nLHEXOwEs9n-4t6kIGyPJIlFMGw4VKCpU8_NBC0XLr0,5876
|
|
107
107
|
cognite/neat/_rules/importers/_spreadsheet2rules.py,sha256=wjB7RVevjvXL3gaL1SGEW411ie76ZrFbe9fngzO-ncQ,10977
|
|
108
|
-
cognite/neat/_rules/importers/_yaml2rules.py,sha256=
|
|
108
|
+
cognite/neat/_rules/importers/_yaml2rules.py,sha256=tqfHhLnlcu4iFrF5ol26lUquBoXHW95mfpmtjdTQx-Q,3896
|
|
109
109
|
cognite/neat/_rules/models/__init__.py,sha256=tf6tyWiYO0eC2PHCcpy208dwOHjEi9hg0sEaQLcB3uA,1024
|
|
110
110
|
cognite/neat/_rules/models/_base_input.py,sha256=ZcSheXMz72w907RAcuMMupTk35zApQ8lS43As7dFVgA,6661
|
|
111
|
-
cognite/neat/_rules/models/_base_rules.py,sha256=
|
|
111
|
+
cognite/neat/_rules/models/_base_rules.py,sha256=ONwBYq7YVUL4R9KL4iLhgbC2ZhGkl6HZtC9Dgx3pI5A,15460
|
|
112
112
|
cognite/neat/_rules/models/_types.py,sha256=OjEV-eDIYTzoMbuazWtNTZgWhthntknqMPS_E9ts22s,5430
|
|
113
113
|
cognite/neat/_rules/models/data_types.py,sha256=OyiAiszU59wQssv05XHX8SihLkYmtfgmgmdVypJ7cwc,10095
|
|
114
114
|
cognite/neat/_rules/models/dms/__init__.py,sha256=fRaUH0IwG0YwWd_DNKM6j-jHHFyiIVz4_8DPiS1KR0Y,695
|
|
115
115
|
cognite/neat/_rules/models/dms/_exporter.py,sha256=2QiTLX4UF89jGd_YRz9EczDFprBphdO_oyaQWMBmSiM,28576
|
|
116
116
|
cognite/neat/_rules/models/dms/_rules.py,sha256=QEKNw31nkTwzjyNEnWYUdDFUdJvDJ5_14iQzWsFizxs,23537
|
|
117
117
|
cognite/neat/_rules/models/dms/_rules_input.py,sha256=HfC4Z9UfDSBlKhoBdk57NqyPic1pVNymZYYEeV8Ow-k,16410
|
|
118
|
-
cognite/neat/_rules/models/dms/_validation.py,sha256=
|
|
118
|
+
cognite/neat/_rules/models/dms/_validation.py,sha256=qImtBMWCKC_C2zrfeTxQrjhTTL1MJt8cFqKMYQwNiEs,32871
|
|
119
119
|
cognite/neat/_rules/models/entities/__init__.py,sha256=Hlucp3LyV6ncLl79aqRTbSy2qgiGzoyN8x54D_zaJCY,1469
|
|
120
120
|
cognite/neat/_rules/models/entities/_constants.py,sha256=GXRzVfArwxF3C67VCkzy0JWTZRkRJUYXBQaaecrqcWc,351
|
|
121
121
|
cognite/neat/_rules/models/entities/_loaders.py,sha256=OQDbz5ANMQ_7ZcdMIBdTR94BoCpWrBA2KBH3fCW0JQo,2728
|
|
@@ -132,24 +132,24 @@ cognite/neat/_rules/models/mapping/_classic2core.py,sha256=AhLWoXk4PlBVA6SgBtY9d
|
|
|
132
132
|
cognite/neat/_rules/models/mapping/_classic2core.yaml,sha256=ei-nuivNWVW9HmvzDBKIPF6ZdgaMq64XHw_rKm0CMxg,22584
|
|
133
133
|
cognite/neat/_rules/transformers/__init__.py,sha256=icjtZq6Hc122fEj9AGEcDB8QuF2JL6dWe4utne73naQ,1617
|
|
134
134
|
cognite/neat/_rules/transformers/_base.py,sha256=9LnjKbYIf9238PQXedkTZsMXAyEND6glUD187iEaHfc,2783
|
|
135
|
-
cognite/neat/_rules/transformers/_converters.py,sha256
|
|
135
|
+
cognite/neat/_rules/transformers/_converters.py,sha256=-veWPRxJJGYBtExSZGlTm3obeG_AE6lSKyaaWNjlHGY,105167
|
|
136
136
|
cognite/neat/_rules/transformers/_mapping.py,sha256=QVd96vMF9sGailN5hB22KGdmOU8GzFwZ7IPMD0aVCYY,18237
|
|
137
137
|
cognite/neat/_rules/transformers/_verification.py,sha256=coZjoLqdfS8yrPP62T_xEKrDZc9ETbPWrLuwEVBSLZQ,4370
|
|
138
138
|
cognite/neat/_session/__init__.py,sha256=fxQ5URVlUnmEGYyB8Baw7IDq-uYacqkigbc4b-Pr9Fw,58
|
|
139
139
|
cognite/neat/_session/_base.py,sha256=WrX4g-pf4GnnYpusSoNkmKyjH_IfB9ZWfXw34THMqy0,12344
|
|
140
140
|
cognite/neat/_session/_collector.py,sha256=ipYlwBBgjF53adjDW_D1U39mLEviB3UOVSGgeqHkEuc,4228
|
|
141
|
-
cognite/neat/_session/_drop.py,sha256=
|
|
142
|
-
cognite/neat/_session/_explore.py,sha256=
|
|
141
|
+
cognite/neat/_session/_drop.py,sha256=yXCZVL2PdVHffu5x630etuYEa3hBNhsZqhlryZVUkOQ,4181
|
|
142
|
+
cognite/neat/_session/_explore.py,sha256=KX0_iNRospxhcgC5O2grvbVbRqaDszeZ3AG5SYqjzcM,1589
|
|
143
143
|
cognite/neat/_session/_fix.py,sha256=wYXIIHKmWTNmOLr9RvDSkBJllKoomP2mCnMdB9x2ojw,898
|
|
144
144
|
cognite/neat/_session/_inspect.py,sha256=qoBAfCQnzC40ef91gxJmhonWo1Kr_VEjBb2KhbCOO_s,10084
|
|
145
145
|
cognite/neat/_session/_mapping.py,sha256=AkQwmqYH-0EgqoXHqCFwJY92hNSGzfojOelhVFlqH4c,2655
|
|
146
|
-
cognite/neat/_session/_prepare.py,sha256=
|
|
147
|
-
cognite/neat/_session/_read.py,sha256=
|
|
148
|
-
cognite/neat/_session/_set.py,sha256=
|
|
149
|
-
cognite/neat/_session/_show.py,sha256=
|
|
146
|
+
cognite/neat/_session/_prepare.py,sha256=js4R1ssvWZRUDTDas228HVPGLuRABLHrliTTDNCFLOg,12692
|
|
147
|
+
cognite/neat/_session/_read.py,sha256=rjQqFU9VzyPSdNmaKaMo-E5em6LZHa3iDAjdvRLX9rI,30193
|
|
148
|
+
cognite/neat/_session/_set.py,sha256=a16aKeip7Y3qAhU0AzmJlMaEXe5ifDBXFYq4tXZNanI,4472
|
|
149
|
+
cognite/neat/_session/_show.py,sha256=9c0eUGtvN6pIX594P6hVofxDwO7lDE-N3A52htJjcv0,10546
|
|
150
150
|
cognite/neat/_session/_state.py,sha256=6b0BSXm7m5-OcsF_O0A_7ec9tt8oPqH8zHImyEhVQQA,6313
|
|
151
151
|
cognite/neat/_session/_subset.py,sha256=4RFGC8apNLnRSKcoDh95ksXA7zLy8vGLxEV5U0H3Hoc,2687
|
|
152
|
-
cognite/neat/_session/_template.py,sha256=
|
|
152
|
+
cognite/neat/_session/_template.py,sha256=UEKvSAZJg08Vfb0TTUq7K7X3gcjP_pJEazyugPXFTq0,11318
|
|
153
153
|
cognite/neat/_session/_to.py,sha256=S7209afgOlLWbsKOA0Z4lAwT57gzLmSDaUWpUaWjJJY,19118
|
|
154
154
|
cognite/neat/_session/_wizard.py,sha256=9idlzhZy54h2Iwupe9iXKX3RDb5jJQuBZFEouni50L0,1476
|
|
155
155
|
cognite/neat/_session/engine/__init__.py,sha256=D3MxUorEs6-NtgoICqtZ8PISQrjrr4dvca6n48bu_bI,120
|
|
@@ -158,8 +158,9 @@ cognite/neat/_session/engine/_interface.py,sha256=3W-cYr493c_mW3P5O6MKN1xEQg3cA7
|
|
|
158
158
|
cognite/neat/_session/engine/_load.py,sha256=LcoYVthQyCzLWKzRE_75_nElS-n_eMWSPAgNJBnh5dA,5193
|
|
159
159
|
cognite/neat/_session/exceptions.py,sha256=kRNKnhvOEPnF8TdcKP-lWbHvAwn-MOtGxKZdUpnJ_Q8,3239
|
|
160
160
|
cognite/neat/_shared.py,sha256=Ov59SWYboRRsncB_5V1ZC_BAoACfNLjo80vqE5Ru6wo,2325
|
|
161
|
+
cognite/neat/_state/README.md,sha256=G6my1CtTDNyIR7G3H1Is_92dHsH_dXjmJmYQb9xh_dk,898
|
|
161
162
|
cognite/neat/_store/__init__.py,sha256=RrvuZrMdezqun5dOrwHWSk26kampZcvqiHBqSFumkEE,130
|
|
162
|
-
cognite/neat/_store/_graph_store.py,sha256=
|
|
163
|
+
cognite/neat/_store/_graph_store.py,sha256=jEAGNhMhzOdnBESDfWt6yF6qyJZ61gWCrEQDsMfMhdI,17177
|
|
163
164
|
cognite/neat/_store/_provenance.py,sha256=V2rBK3L4wneoiTBvir3AbmrcPsl6XVmefovkkjHYhNE,7301
|
|
164
165
|
cognite/neat/_store/_rules_store.py,sha256=dh2GfDRRtQ2F00I5hdqYveULQKx2_kt630Mac_ZFF2k,18562
|
|
165
166
|
cognite/neat/_store/exceptions.py,sha256=XznWE3X8iBpnTKcC2SpInwesQVpfinGBzQT6xX9GANg,1614
|
|
@@ -177,10 +178,10 @@ cognite/neat/_utils/text.py,sha256=9T0mzcNn6J9X8DriNntLN5ThCXOWbU1BYareukbLT7A,8
|
|
|
177
178
|
cognite/neat/_utils/time_.py,sha256=7ayUm0OWZm1JDmy32E4ip8WRr2o0GLwrHwJA8sJ43Z4,357
|
|
178
179
|
cognite/neat/_utils/upload.py,sha256=xWtM6mFuD2QYQHaZ7zCAuGptbEpPIxcH-raWQu93-Ug,5845
|
|
179
180
|
cognite/neat/_utils/xml_.py,sha256=FQkq84u35MUsnKcL6nTMJ9ajtG9D5i1u4VBnhGqP2DQ,1710
|
|
180
|
-
cognite/neat/_version.py,sha256=
|
|
181
|
+
cognite/neat/_version.py,sha256=d27As8_j5YQxh9_ZmNwoy0v_fx27xmBROZeiFkXTUNE,46
|
|
181
182
|
cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
182
|
-
cognite_neat-0.119.
|
|
183
|
-
cognite_neat-0.119.
|
|
184
|
-
cognite_neat-0.119.
|
|
185
|
-
cognite_neat-0.119.
|
|
186
|
-
cognite_neat-0.119.
|
|
183
|
+
cognite_neat-0.119.3.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
|
|
184
|
+
cognite_neat-0.119.3.dist-info/METADATA,sha256=L1WOkKQhfbfheXIZ3UaLUI2JPAsF8qbx-dUfGxpbh84,7646
|
|
185
|
+
cognite_neat-0.119.3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
186
|
+
cognite_neat-0.119.3.dist-info/entry_points.txt,sha256=SsQlnl8SNMSSjE3acBI835JYFtsIinLSbVmHmMEXv6E,51
|
|
187
|
+
cognite_neat-0.119.3.dist-info/RECORD,,
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import xml.etree.ElementTree as ET
|
|
2
|
-
from collections import defaultdict
|
|
3
|
-
from collections.abc import Iterable
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from xml.etree.ElementTree import Element
|
|
6
|
-
|
|
7
|
-
from rdflib import RDF, RDFS, XSD, Literal, Namespace, URIRef
|
|
8
|
-
from typing_extensions import Self
|
|
9
|
-
|
|
10
|
-
from cognite.neat._constants import DEFAULT_NAMESPACE
|
|
11
|
-
from cognite.neat._graph.extractors._base import BaseExtractor
|
|
12
|
-
from cognite.neat._shared import Triple
|
|
13
|
-
from cognite.neat._utils.rdf_ import as_neat_compliant_uri
|
|
14
|
-
from cognite.neat._utils.xml_ import get_children, iterate_tree
|
|
15
|
-
|
|
16
|
-
DEXPI = Namespace("http://sandbox.dexpi.org/rdl/")
|
|
17
|
-
QUDT = Namespace("https://qudt.org/vocab/unit/")
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class DexpiExtractor(BaseExtractor):
|
|
21
|
-
"""
|
|
22
|
-
DEXPI-XML extractor of RDF triples
|
|
23
|
-
|
|
24
|
-
Args:
|
|
25
|
-
root: XML root element of DEXPI file.
|
|
26
|
-
namespace: Optional custom namespace to use for extracted triples that define data
|
|
27
|
-
model instances. Defaults to DEFAULT_NAMESPACE.
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
def __init__(
|
|
31
|
-
self,
|
|
32
|
-
root: Element,
|
|
33
|
-
namespace: Namespace | None = None,
|
|
34
|
-
):
|
|
35
|
-
self.root = root
|
|
36
|
-
self.namespace = namespace or DEFAULT_NAMESPACE
|
|
37
|
-
|
|
38
|
-
@classmethod
|
|
39
|
-
def from_file(cls, filepath: str | Path, namespace: Namespace | None = None) -> Self:
|
|
40
|
-
return cls(ET.parse(filepath).getroot(), namespace)
|
|
41
|
-
|
|
42
|
-
@classmethod
|
|
43
|
-
def from_url(cls, url: str, namespace: Namespace | None = None) -> Self:
|
|
44
|
-
from io import BytesIO
|
|
45
|
-
|
|
46
|
-
import requests
|
|
47
|
-
|
|
48
|
-
response = requests.get(url)
|
|
49
|
-
response.raise_for_status()
|
|
50
|
-
return cls(ET.parse(BytesIO(response.content)).getroot(), namespace)
|
|
51
|
-
|
|
52
|
-
def extract(self) -> Iterable[Triple]:
|
|
53
|
-
"""Extracts RDF triples from DEXPI XML file."""
|
|
54
|
-
|
|
55
|
-
for element in iterate_tree(self.root):
|
|
56
|
-
yield from self._element2triples(element, self.namespace)
|
|
57
|
-
|
|
58
|
-
@classmethod
|
|
59
|
-
def _element2triples(cls, element: Element, namespace: Namespace) -> list[Triple]:
|
|
60
|
-
"""Converts an element to triples."""
|
|
61
|
-
triples: list[Triple] = []
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
"ComponentClass" in element.attrib
|
|
65
|
-
and element.attrib["ComponentClass"] != "Label"
|
|
66
|
-
and "ID" in element.attrib
|
|
67
|
-
):
|
|
68
|
-
id_ = namespace[element.attrib["ID"]]
|
|
69
|
-
|
|
70
|
-
if node_triples := cls._element2node_triples(id_, element):
|
|
71
|
-
triples.extend(node_triples)
|
|
72
|
-
|
|
73
|
-
if edge_triples := cls._element2edge_triples(id_, element, namespace):
|
|
74
|
-
triples.extend(edge_triples)
|
|
75
|
-
|
|
76
|
-
return triples
|
|
77
|
-
|
|
78
|
-
@classmethod
|
|
79
|
-
def _element2edge_triples(cls, id_: URIRef, element: Element, namespace: Namespace) -> list[Triple]:
|
|
80
|
-
triples: list[Triple] = []
|
|
81
|
-
|
|
82
|
-
# connection triples
|
|
83
|
-
if connections := get_children(element, "Connection"):
|
|
84
|
-
for connection in connections:
|
|
85
|
-
if "FromID" in connection.attrib and "ToID" in connection.attrib:
|
|
86
|
-
triples.append(
|
|
87
|
-
(
|
|
88
|
-
namespace[connection.attrib["FromID"]],
|
|
89
|
-
DEXPI.connection,
|
|
90
|
-
namespace[connection.attrib["ToID"]],
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
# association triples
|
|
95
|
-
if associations := get_children(element, "Association"):
|
|
96
|
-
for association in associations:
|
|
97
|
-
if "Type" in association.attrib and "ItemID" in association.attrib:
|
|
98
|
-
association_type = cls._to_uri_friendly_association_type(association)
|
|
99
|
-
|
|
100
|
-
triples.append(
|
|
101
|
-
(
|
|
102
|
-
id_,
|
|
103
|
-
DEXPI[f"association/{association_type}"],
|
|
104
|
-
namespace[association.attrib["ItemID"]],
|
|
105
|
-
)
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
# children-parent triples
|
|
109
|
-
for child in element:
|
|
110
|
-
if "ID" in child.attrib and child.tag != "Label":
|
|
111
|
-
camel_case_property = child.tag[0].lower() + child.tag[1:]
|
|
112
|
-
triples.append(
|
|
113
|
-
(
|
|
114
|
-
id_,
|
|
115
|
-
DEXPI[f"children/{camel_case_property}"],
|
|
116
|
-
namespace[child.attrib["ID"]],
|
|
117
|
-
)
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
return triples
|
|
121
|
-
|
|
122
|
-
@classmethod
|
|
123
|
-
def _to_uri_friendly_association_type(cls, association: Element) -> str:
|
|
124
|
-
association_type = "".join(
|
|
125
|
-
[word.capitalize() if i != 0 else word for i, word in enumerate(association.attrib["Type"].split(" "))]
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
return association_type
|
|
129
|
-
|
|
130
|
-
@classmethod
|
|
131
|
-
def _element2node_triples(cls, id_: URIRef, element: Element) -> list[Triple]:
|
|
132
|
-
"""Converts an XML element to triples."""
|
|
133
|
-
triples: list[Triple] = []
|
|
134
|
-
|
|
135
|
-
# setting these to None this is the order of getting the type
|
|
136
|
-
component_class: str | None = None
|
|
137
|
-
component_name: str | None = None
|
|
138
|
-
tag: str | None = None
|
|
139
|
-
|
|
140
|
-
# adding tag triple if exists
|
|
141
|
-
if tag := element.tag:
|
|
142
|
-
triples.append((id_, DEXPI.tag, Literal(str(tag))))
|
|
143
|
-
|
|
144
|
-
# adding attributes triples
|
|
145
|
-
if attributes := element.attrib:
|
|
146
|
-
if component_class := attributes.get("ComponentClass", None):
|
|
147
|
-
triples.append((id_, DEXPI.ComponentClass, Literal(component_class)))
|
|
148
|
-
if component_name := attributes.get("ComponentName", None):
|
|
149
|
-
triples.append((id_, DEXPI.ComponentName, Literal(component_name)))
|
|
150
|
-
if component_class_uri := attributes.get("ComponentClassURI", None):
|
|
151
|
-
triples.append((id_, DEXPI.ComponentClassURI, URIRef(component_class_uri)))
|
|
152
|
-
|
|
153
|
-
triples.append(
|
|
154
|
-
(
|
|
155
|
-
id_,
|
|
156
|
-
RDF.type,
|
|
157
|
-
as_neat_compliant_uri(DEFAULT_NAMESPACE[component_class or component_name or tag or "Unknown"]),
|
|
158
|
-
)
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
# add label triple
|
|
162
|
-
if label := cls._get_element_label(element):
|
|
163
|
-
triples.append((id_, RDFS.label, Literal(label)))
|
|
164
|
-
|
|
165
|
-
# add generic attributes triples
|
|
166
|
-
if generic_attributes := cls._get_element_generic_attributes(element):
|
|
167
|
-
for attribute, value_definitions in generic_attributes.items():
|
|
168
|
-
predicate = as_neat_compliant_uri(attribute)
|
|
169
|
-
for value_definition in value_definitions:
|
|
170
|
-
if literal := cls._value_definition2literal(value_definition):
|
|
171
|
-
triples.append((id_, predicate, literal))
|
|
172
|
-
|
|
173
|
-
return triples
|
|
174
|
-
|
|
175
|
-
@classmethod
|
|
176
|
-
def _value_definition2literal(cls, definition: dict, make_unit_datatype: bool = False) -> Literal | None:
|
|
177
|
-
if "Value" not in definition or "Format" not in definition:
|
|
178
|
-
return None
|
|
179
|
-
|
|
180
|
-
if "Units" in definition and "Value" in definition:
|
|
181
|
-
if make_unit_datatype and "UnitsURI" in definition:
|
|
182
|
-
return Literal(definition["Value"], datatype=URIRef(definition["UnitsURI"]))
|
|
183
|
-
|
|
184
|
-
else:
|
|
185
|
-
return Literal(definition["Value"], datatype=XSD.float)
|
|
186
|
-
|
|
187
|
-
# case: when language is present we create add language tag to the literal
|
|
188
|
-
elif "Language" in definition and "Value" in definition:
|
|
189
|
-
return Literal(definition["Value"], lang=definition["Language"])
|
|
190
|
-
|
|
191
|
-
# case: when ValueURI is present we use it instead of Value
|
|
192
|
-
# this would be candidate for ENUMs in CDF
|
|
193
|
-
elif "ValueURI" in definition:
|
|
194
|
-
return Literal(definition["ValueURI"], datatype=XSD[definition["Format"]])
|
|
195
|
-
|
|
196
|
-
# case: when Format is not string we make sure to add the datatype
|
|
197
|
-
elif definition["Format"].lower() != "string":
|
|
198
|
-
return Literal(definition["Value"], datatype=XSD[definition["Format"]])
|
|
199
|
-
|
|
200
|
-
# case: when Format is string we add the literal without datatype (easier to read triples, less noise)
|
|
201
|
-
else:
|
|
202
|
-
return Literal(definition["Value"])
|
|
203
|
-
|
|
204
|
-
@classmethod
|
|
205
|
-
def _get_element_label(cls, element: Element) -> str | None:
|
|
206
|
-
if children := get_children(element, "Label", no_children=1):
|
|
207
|
-
if grandchildren := get_children(children[0], "Text", no_children=1):
|
|
208
|
-
if "String" in grandchildren[0].attrib:
|
|
209
|
-
return grandchildren[0].attrib["String"]
|
|
210
|
-
|
|
211
|
-
# extension for schema version 3.3, where text is used to "label" without a <label> parent
|
|
212
|
-
elif children := get_children(element, "Text", no_children=1):
|
|
213
|
-
if "String" in children[0].attrib:
|
|
214
|
-
return children[0].attrib["String"]
|
|
215
|
-
|
|
216
|
-
return None
|
|
217
|
-
|
|
218
|
-
@classmethod
|
|
219
|
-
def _get_element_generic_attributes(cls, element: Element) -> dict:
|
|
220
|
-
# TODO: This requires more work as there are multiple groupings of GenericAttributes
|
|
221
|
-
|
|
222
|
-
attributes = defaultdict(list)
|
|
223
|
-
if children := get_children(element, "GenericAttributes", no_children=1):
|
|
224
|
-
if grandchildren := get_children(children[0], "GenericAttribute"):
|
|
225
|
-
for generic_attribute in grandchildren:
|
|
226
|
-
# extension for schema version 3.3, where "AttributeURI" is not included
|
|
227
|
-
if name := generic_attribute.attrib.get("Name", None):
|
|
228
|
-
attribute_uri = as_neat_compliant_uri(DEFAULT_NAMESPACE[name])
|
|
229
|
-
if attribute_uri not in attributes:
|
|
230
|
-
attributes[attribute_uri] = [generic_attribute.attrib]
|
|
231
|
-
else:
|
|
232
|
-
attributes[attribute_uri].append(generic_attribute.attrib)
|
|
233
|
-
|
|
234
|
-
return attributes
|