elementpath 5.0.3__tar.gz → 5.0.4__tar.gz
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.
- {elementpath-5.0.3 → elementpath-5.0.4}/CHANGELOG.rst +5 -0
- {elementpath-5.0.3/elementpath.egg-info → elementpath-5.0.4}/PKG-INFO +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/conf.py +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/__init__.py +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/compare.py +8 -8
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/extras/pathnodes.py +24 -32
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/schema_proxy.py +4 -64
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/serialization.py +6 -6
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/tree_builders.py +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath1/_xpath1_functions.py +4 -4
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath1/_xpath1_operators.py +3 -3
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath2/_xpath2_functions.py +13 -13
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath30/_xpath30_functions.py +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath31/_xpath31_functions.py +2 -2
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath_context.py +7 -7
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath_nodes.py +194 -154
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath_tokens.py +4 -4
- {elementpath-5.0.3 → elementpath-5.0.4/elementpath.egg-info}/PKG-INFO +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/pyproject.toml +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_schema_proxy.py +143 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath_context.py +6 -6
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath_nodes.py +1 -1
- {elementpath-5.0.3 → elementpath-5.0.4}/LICENSE +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/MANIFEST.in +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/README.rst +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/Makefile +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/advanced.rst +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/index.rst +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/introduction.rst +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/make.bat +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/pratt_api.rst +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/requirements.txt +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/doc/xpath_api.rst +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/aliases.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/collations.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/atomic_types.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/binary.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/datetime.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/numeric.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/proxies.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/qname.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/string.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/untyped.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/datatypes/uri.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/decoder.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/etree.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/exceptions.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/extras/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/helpers.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/namespaces.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/protocols.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/py.typed +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/categories_fallback.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/character_classes.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/codepoints.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/patterns.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/unicode_blocks.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/unicode_categories.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/regex/unicode_subsets.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/sequence_types.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/tdop.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/validators/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/validators/analyze-string.xsd +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/validators/schema-for-json.xsd +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath1/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath1/_xpath1_axes.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath1/xpath1_parser.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath2/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath2/_xpath2_constructors.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath2/_xpath2_operators.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath2/xpath2_parser.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath3.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath30/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath30/_translation_maps.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath30/_xpath30_operators.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath30/xpath30_helpers.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath30/xpath30_parser.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath31/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath31/_xpath31_operators.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath31/xpath31_parser.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath/xpath_selectors.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath.egg-info/SOURCES.txt +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath.egg-info/dependency_links.txt +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath.egg-info/requires.txt +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/elementpath.egg-info/top_level.txt +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/requirements-dev.txt +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/scripts/generate_codepoints.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/setup.cfg +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/__init__.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/memory_profiling.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/mypy_tests/advanced.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/mypy_tests/protocols.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/mypy_tests/selectors.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/analyze-string.xsd +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/external_entity.xml +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/sample.xml +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/schema-for-json.xsd +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/unparsed_entity.xml +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/unused_external_entity.xml +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/unused_unparsed_entity.xml +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/resources/with_entity.xml +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/run_all_tests.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/run_typing_tests.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/run_w3c_tests.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_collations.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_compare.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_datatypes.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_decoder.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_etree.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_exceptions.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_helpers.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_namespaces.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_package.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_pathnodes.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_regex.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_schema_context.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_selectors.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_sequence_types.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_serialization.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_tdop_parser.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_tree_builders.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_validators.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath1_parser.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath2_constructors.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath2_functions.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath2_parser.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath30.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath31.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/test_xpath_tokens.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tests/xpath_test_class.py +0 -0
- {elementpath-5.0.3 → elementpath-5.0.4}/tox.ini +0 -0
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
CHANGELOG
|
|
3
3
|
*********
|
|
4
4
|
|
|
5
|
+
`v5.0.4`_ (2025-08-16)
|
|
6
|
+
======================
|
|
7
|
+
* Fix default/fixed values processing of schema annotated XML data (issue #94)
|
|
8
|
+
|
|
5
9
|
`v5.0.3`_ (2025-06-28)
|
|
6
10
|
======================
|
|
7
11
|
* Fix for XPath 1.0 processing of schema annotated XML data (issue #93)
|
|
@@ -518,3 +522,4 @@ CHANGELOG
|
|
|
518
522
|
.. _v5.0.1: https://github.com/sissaschool/elementpath/compare/v5.0.0...v5.0.1
|
|
519
523
|
.. _v5.0.2: https://github.com/sissaschool/elementpath/compare/v5.0.1...v5.0.2
|
|
520
524
|
.. _v5.0.3: https://github.com/sissaschool/elementpath/compare/v5.0.2...v5.0.3
|
|
525
|
+
.. _v5.0.4: https://github.com/sissaschool/elementpath/compare/v5.0.3...v5.0.4
|
|
@@ -83,7 +83,7 @@ def deep_equal(seq1: Iterable[Any],
|
|
|
83
83
|
return False
|
|
84
84
|
elif isinstance(value1, etree_node_types):
|
|
85
85
|
assert isinstance(value2, etree_node_types)
|
|
86
|
-
if not etree_deep_equal(value1.
|
|
86
|
+
if not etree_deep_equal(value1.value, value2.value):
|
|
87
87
|
return False
|
|
88
88
|
elif isinstance(value1, EtreeDocumentNode):
|
|
89
89
|
assert isinstance(value2, EtreeDocumentNode)
|
|
@@ -94,14 +94,14 @@ def deep_equal(seq1: Iterable[Any],
|
|
|
94
94
|
return False
|
|
95
95
|
elif isinstance(child1, etree_node_types):
|
|
96
96
|
assert isinstance(child2, etree_node_types)
|
|
97
|
-
if not etree_deep_equal(child1.
|
|
97
|
+
if not etree_deep_equal(child1.value, child2.value):
|
|
98
98
|
return False
|
|
99
99
|
elif isinstance(child1, TextNode):
|
|
100
100
|
assert isinstance(child2, TextNode)
|
|
101
|
-
if cm.ne(child1.
|
|
101
|
+
if cm.ne(child1.value, child2.value):
|
|
102
102
|
return False
|
|
103
103
|
|
|
104
|
-
elif cm.ne(value1.
|
|
104
|
+
elif cm.ne(value1.value, value2.value):
|
|
105
105
|
return False
|
|
106
106
|
elif isinstance(value1, TextAttributeNode):
|
|
107
107
|
if cm.ne(value1.name, value2.name):
|
|
@@ -257,7 +257,7 @@ def deep_compare(obj1: Any,
|
|
|
257
257
|
raise xpath_error('XPTY0004', msg, token=token)
|
|
258
258
|
elif isinstance(value1, etree_node_types):
|
|
259
259
|
assert isinstance(value2, etree_node_types)
|
|
260
|
-
result = etree_deep_compare(value1.
|
|
260
|
+
result = etree_deep_compare(value1.value, value2.value)
|
|
261
261
|
if result:
|
|
262
262
|
return result
|
|
263
263
|
elif isinstance(value1, EtreeDocumentNode):
|
|
@@ -272,19 +272,19 @@ def deep_compare(obj1: Any,
|
|
|
272
272
|
raise xpath_error('XPTY0004', msg, token=token)
|
|
273
273
|
elif isinstance(child1, etree_node_types):
|
|
274
274
|
assert isinstance(child2, etree_node_types)
|
|
275
|
-
result = etree_deep_compare(child1.
|
|
275
|
+
result = etree_deep_compare(child1.value, child2.value)
|
|
276
276
|
if result:
|
|
277
277
|
return result
|
|
278
278
|
elif isinstance(child1, TextNode):
|
|
279
279
|
assert isinstance(child2, TextNode)
|
|
280
280
|
result = cm.strcoll(
|
|
281
|
-
child1.
|
|
281
|
+
child1.value.strip(), child2.value.strip()
|
|
282
282
|
)
|
|
283
283
|
if result:
|
|
284
284
|
return result
|
|
285
285
|
elif isinstance(value1, TextNode):
|
|
286
286
|
assert isinstance(value2, TextNode)
|
|
287
|
-
result = cm.strcoll(value1.
|
|
287
|
+
result = cm.strcoll(value1.value, value2.value)
|
|
288
288
|
if result:
|
|
289
289
|
return result
|
|
290
290
|
elif isinstance(value1, TextAttributeNode):
|
|
@@ -24,7 +24,7 @@ from elementpath.datatypes import DateTime, AtomicType
|
|
|
24
24
|
|
|
25
25
|
class PathElementNode(ElementNode):
|
|
26
26
|
name: str
|
|
27
|
-
|
|
27
|
+
value: Path
|
|
28
28
|
xsd_element: Optional[XsdElementProtocol]
|
|
29
29
|
|
|
30
30
|
__slots__ = ('stat',)
|
|
@@ -53,7 +53,7 @@ class PathElementNode(ElementNode):
|
|
|
53
53
|
self.parent = parent
|
|
54
54
|
|
|
55
55
|
self.name = path.name
|
|
56
|
-
self.
|
|
56
|
+
self.value = path
|
|
57
57
|
self.stat = path.stat()
|
|
58
58
|
self.position = self.stat.st_ino
|
|
59
59
|
self.children = []
|
|
@@ -63,9 +63,9 @@ class PathElementNode(ElementNode):
|
|
|
63
63
|
|
|
64
64
|
@property
|
|
65
65
|
def content(self) -> Path:
|
|
66
|
-
return self.
|
|
66
|
+
return self.value
|
|
67
67
|
|
|
68
|
-
elem =
|
|
68
|
+
elem = content
|
|
69
69
|
|
|
70
70
|
@property
|
|
71
71
|
def attributes(self) -> list[AttributeNode]:
|
|
@@ -101,10 +101,10 @@ class PathElementNode(ElementNode):
|
|
|
101
101
|
|
|
102
102
|
@property
|
|
103
103
|
def string_value(self) -> str:
|
|
104
|
-
if self.
|
|
104
|
+
if self.value.is_dir():
|
|
105
105
|
return ''
|
|
106
|
-
if self.
|
|
107
|
-
return self.
|
|
106
|
+
if self.value.is_file():
|
|
107
|
+
return self.value.read_text()
|
|
108
108
|
else:
|
|
109
109
|
return ''
|
|
110
110
|
|
|
@@ -125,12 +125,12 @@ class PathElementNode(ElementNode):
|
|
|
125
125
|
return self.name == f'{{{default_namespace}}}{name}'
|
|
126
126
|
|
|
127
127
|
def get_document_node(self, replace: bool = True, as_parent: bool = True) -> 'DocumentNode':
|
|
128
|
-
return PathDocumentNode(Path(self.
|
|
128
|
+
return PathDocumentNode(Path(self.value.absolute().root))
|
|
129
129
|
|
|
130
130
|
def __iter__(self) -> Iterator[ChildNodeType]:
|
|
131
131
|
if not self.children:
|
|
132
|
-
if self.
|
|
133
|
-
for path in self.
|
|
132
|
+
if self.value.is_dir():
|
|
133
|
+
for path in self.value.iterdir():
|
|
134
134
|
if path in self.tree.elements:
|
|
135
135
|
self.children.append(self.tree.elements[path])
|
|
136
136
|
else:
|
|
@@ -150,7 +150,7 @@ class PathElementNode(ElementNode):
|
|
|
150
150
|
|
|
151
151
|
|
|
152
152
|
class PathDocumentNode(DocumentNode):
|
|
153
|
-
|
|
153
|
+
value: Path
|
|
154
154
|
|
|
155
155
|
__slots__ = ('stat',)
|
|
156
156
|
|
|
@@ -159,7 +159,7 @@ class PathDocumentNode(DocumentNode):
|
|
|
159
159
|
if not document.is_dir() or len(document.parts) > 1 or not document.is_absolute():
|
|
160
160
|
raise ValueError(f'{document} must be a root directory')
|
|
161
161
|
|
|
162
|
-
self.
|
|
162
|
+
self.value = document
|
|
163
163
|
self.name = None
|
|
164
164
|
self.parent = None
|
|
165
165
|
self.position = document.stat().st_ino
|
|
@@ -168,15 +168,15 @@ class PathDocumentNode(DocumentNode):
|
|
|
168
168
|
|
|
169
169
|
@property
|
|
170
170
|
def document(self) -> Path:
|
|
171
|
-
return self.
|
|
171
|
+
return self.value
|
|
172
172
|
|
|
173
173
|
@property
|
|
174
174
|
def string_value(self) -> str:
|
|
175
|
-
return self.
|
|
175
|
+
return self.value.read_text()
|
|
176
176
|
|
|
177
177
|
def __iter__(self) -> Iterator[ChildNodeType]:
|
|
178
178
|
if not self.children:
|
|
179
|
-
for path in self.
|
|
179
|
+
for path in self.value.iterdir():
|
|
180
180
|
if path in self.tree.elements:
|
|
181
181
|
self.children.append(self.tree.elements[path])
|
|
182
182
|
else:
|
|
@@ -187,7 +187,7 @@ class PathDocumentNode(DocumentNode):
|
|
|
187
187
|
|
|
188
188
|
class IntAttributeNode(AttributeNode):
|
|
189
189
|
name: str
|
|
190
|
-
|
|
190
|
+
value: int
|
|
191
191
|
parent: Optional['PathElementNode']
|
|
192
192
|
|
|
193
193
|
__slots__ = ()
|
|
@@ -198,22 +198,18 @@ class IntAttributeNode(AttributeNode):
|
|
|
198
198
|
parent: Optional['PathElementNode'] = None) -> None:
|
|
199
199
|
|
|
200
200
|
self.name = name
|
|
201
|
-
self.
|
|
201
|
+
self.value = value
|
|
202
202
|
self.parent = parent
|
|
203
203
|
self.position = parent.position if parent is not None else 1
|
|
204
204
|
self.xsd_type = None
|
|
205
205
|
|
|
206
|
-
@property
|
|
207
|
-
def value(self) -> int:
|
|
208
|
-
return self.obj
|
|
209
|
-
|
|
210
206
|
@property
|
|
211
207
|
def string_value(self) -> str:
|
|
212
|
-
return str(self.
|
|
208
|
+
return str(self.value)
|
|
213
209
|
|
|
214
210
|
@property
|
|
215
211
|
def iter_typed_values(self) -> Iterator[AtomicType]:
|
|
216
|
-
yield self.
|
|
212
|
+
yield self.value
|
|
217
213
|
|
|
218
214
|
@property
|
|
219
215
|
def type_name(self) -> Optional[str]:
|
|
@@ -224,12 +220,12 @@ class ModeAttributeNode(IntAttributeNode):
|
|
|
224
220
|
|
|
225
221
|
@property
|
|
226
222
|
def string_value(self) -> str:
|
|
227
|
-
return oct(self.
|
|
223
|
+
return oct(self.value)
|
|
228
224
|
|
|
229
225
|
|
|
230
226
|
class DatetimeAttributeNode(AttributeNode):
|
|
231
227
|
name: str
|
|
232
|
-
|
|
228
|
+
value: datetime
|
|
233
229
|
parent: Optional['PathElementNode']
|
|
234
230
|
|
|
235
231
|
__slots__ = ()
|
|
@@ -240,22 +236,18 @@ class DatetimeAttributeNode(AttributeNode):
|
|
|
240
236
|
parent: Optional['PathElementNode'] = None) -> None:
|
|
241
237
|
|
|
242
238
|
self.name = name
|
|
243
|
-
self.
|
|
239
|
+
self.value = value
|
|
244
240
|
self.parent = parent
|
|
245
241
|
self.position = parent.position if parent is not None else 1
|
|
246
242
|
self.xsd_type = None
|
|
247
243
|
|
|
248
|
-
@property
|
|
249
|
-
def value(self) -> datetime:
|
|
250
|
-
return self.obj
|
|
251
|
-
|
|
252
244
|
@property
|
|
253
245
|
def string_value(self) -> str:
|
|
254
|
-
return str(self.
|
|
246
|
+
return str(self.value)
|
|
255
247
|
|
|
256
248
|
@property
|
|
257
249
|
def iter_typed_values(self) -> Iterator[AtomicType]:
|
|
258
|
-
yield DateTime.fromdatetime(self.
|
|
250
|
+
yield DateTime.fromdatetime(self.value)
|
|
259
251
|
|
|
260
252
|
@property
|
|
261
253
|
def type_name(self) -> Optional[str]:
|
|
@@ -10,12 +10,11 @@
|
|
|
10
10
|
from abc import ABCMeta, abstractmethod
|
|
11
11
|
from collections.abc import Iterator
|
|
12
12
|
from functools import lru_cache
|
|
13
|
-
from typing import
|
|
13
|
+
from typing import Any, Optional, Union
|
|
14
14
|
|
|
15
15
|
from elementpath.exceptions import ElementPathTypeError
|
|
16
16
|
from elementpath.protocols import XsdTypeProtocol, XsdAttributeProtocol, \
|
|
17
|
-
XsdElementProtocol, XsdSchemaProtocol
|
|
18
|
-
from elementpath.namespaces import XSD_ANY_ATOMIC_TYPE
|
|
17
|
+
XsdElementProtocol, XsdSchemaProtocol
|
|
19
18
|
from elementpath.datatypes import AtomicType
|
|
20
19
|
from elementpath.etree import is_etree_element
|
|
21
20
|
from elementpath.xpath_context import XPathSchemaContext
|
|
@@ -148,16 +147,14 @@ class AbstractSchemaProxy(metaclass=ABCMeta):
|
|
|
148
147
|
Get the XSD global attribute from the schema's scope.
|
|
149
148
|
|
|
150
149
|
:param qname: the fully qualified name of the attribute to retrieve.
|
|
151
|
-
:returns: an object that represents an XSD type or `None`.
|
|
152
150
|
"""
|
|
153
151
|
return self._schema.maps.attributes.get(qname)
|
|
154
152
|
|
|
155
|
-
def get_element(self, qname: str) -> Optional[XsdElementProtocol]:
|
|
153
|
+
def get_element(self, qname: str,) -> Optional[XsdElementProtocol]:
|
|
156
154
|
"""
|
|
157
155
|
Get the XSD global element from the schema's scope.
|
|
158
156
|
|
|
159
|
-
:param qname: the fully qualified name of the
|
|
160
|
-
:returns: an object that represents an XSD type or `None`.
|
|
157
|
+
:param qname: the fully qualified name of the attribute to retrieve.
|
|
161
158
|
"""
|
|
162
159
|
return self._schema.maps.elements.get(qname)
|
|
163
160
|
|
|
@@ -171,63 +168,6 @@ class AbstractSchemaProxy(metaclass=ABCMeta):
|
|
|
171
168
|
"""
|
|
172
169
|
return self._schema.maps.substitution_groups.get(qname)
|
|
173
170
|
|
|
174
|
-
def get_attribute_type(self, name: str, parent_type: Optional[XsdTypeProtocol] = None) \
|
|
175
|
-
-> Optional[XsdTypeProtocol]:
|
|
176
|
-
"""
|
|
177
|
-
Get the XSD attribute type if the provided name is matching in the scope,
|
|
178
|
-
otherwise return None.
|
|
179
|
-
|
|
180
|
-
:param name: the name of the attribute to retrieve.
|
|
181
|
-
:param parent_type: an optional XSD type that represents the scope where matching \
|
|
182
|
-
the attribute name. If not provided, the scope is assumed to be the global scope.
|
|
183
|
-
"""
|
|
184
|
-
if parent_type is None:
|
|
185
|
-
try:
|
|
186
|
-
return self._schema.maps.attributes[name].type
|
|
187
|
-
except KeyError:
|
|
188
|
-
return None
|
|
189
|
-
elif hasattr(parent_type, 'attributes'):
|
|
190
|
-
attributes = cast(XsdAttributeGroupProtocol, parent_type.attributes)
|
|
191
|
-
if name in attributes:
|
|
192
|
-
return attributes[name].type
|
|
193
|
-
elif None in attributes and attributes[None].is_matching(name):
|
|
194
|
-
try:
|
|
195
|
-
return self._schema.maps.attributes[name].type
|
|
196
|
-
except KeyError:
|
|
197
|
-
return None
|
|
198
|
-
elif name.startswith('{http://www.w3.org/2001/XMLSchema-instance}'):
|
|
199
|
-
return self._schema.maps.types.get(XSD_ANY_ATOMIC_TYPE)
|
|
200
|
-
|
|
201
|
-
return None
|
|
202
|
-
|
|
203
|
-
def get_child_type(self, name: str, parent_type: Optional[XsdTypeProtocol] = None) \
|
|
204
|
-
-> Optional[XsdTypeProtocol]:
|
|
205
|
-
"""
|
|
206
|
-
Get the child XSD type if the provided name is matching in the scope,
|
|
207
|
-
otherwise return None.
|
|
208
|
-
|
|
209
|
-
:param name: the name of the child element to match.
|
|
210
|
-
:param parent_type: an optional XSD type that represents the scope where matching \
|
|
211
|
-
the child element name. If `None` or not provided the scope is the schema.
|
|
212
|
-
"""
|
|
213
|
-
if parent_type is None:
|
|
214
|
-
try:
|
|
215
|
-
return self._schema.maps.elements[name].type
|
|
216
|
-
except KeyError:
|
|
217
|
-
return None
|
|
218
|
-
elif (content := parent_type.model_group) is not None:
|
|
219
|
-
for xsd_element in content.iter_elements():
|
|
220
|
-
if xsd_element.is_matching(name):
|
|
221
|
-
if xsd_element.name == name:
|
|
222
|
-
return xsd_element.type
|
|
223
|
-
else:
|
|
224
|
-
# a wildcard or a substitute
|
|
225
|
-
try:
|
|
226
|
-
return self._schema.maps.elements[name].type
|
|
227
|
-
except KeyError:
|
|
228
|
-
return None
|
|
229
|
-
return None
|
|
230
|
-
|
|
231
171
|
@abstractmethod
|
|
232
172
|
def is_instance(self, obj: Any, type_qname: str) -> bool:
|
|
233
173
|
"""
|
|
@@ -139,7 +139,7 @@ def get_serialization_params(params: Union[None, ElementNode, XPathMap] = None,
|
|
|
139
139
|
kwargs[key] = value
|
|
140
140
|
|
|
141
141
|
elif isinstance(params, ElementNode):
|
|
142
|
-
root = cast(Union[EtreeElementProtocol, LxmlElementProtocol], params.
|
|
142
|
+
root = cast(Union[EtreeElementProtocol, LxmlElementProtocol], params.value)
|
|
143
143
|
if root.tag != SERIALIZATION_PARAMS:
|
|
144
144
|
msg = 'output:serialization-parameters tag expected'
|
|
145
145
|
raise xpath_error('XPTY0004', msg, token)
|
|
@@ -293,14 +293,14 @@ def serialize_to_xml(elements: Iterable[Any],
|
|
|
293
293
|
for item in iter_normalized(elements, item_separator):
|
|
294
294
|
if isinstance(item, ElementNode):
|
|
295
295
|
assert isinstance(item, EtreeElementNode)
|
|
296
|
-
elem = item.
|
|
296
|
+
elem = item.value
|
|
297
297
|
elif isinstance(item, (AttributeNode, NamespaceNode)):
|
|
298
298
|
raise xpath_error('SENR0001', token=token)
|
|
299
299
|
elif isinstance(item, TextNode):
|
|
300
300
|
if item.parent is not None and item.parent.name in cdata_section:
|
|
301
|
-
chunks.append(f'<![CDATA[{item.
|
|
301
|
+
chunks.append(f'<![CDATA[{item.value}]]>')
|
|
302
302
|
else:
|
|
303
|
-
chunks.append(item.
|
|
303
|
+
chunks.append(item.value)
|
|
304
304
|
continue
|
|
305
305
|
elif not isinstance(item, str):
|
|
306
306
|
raise xpath_error('SENR0001', token=token)
|
|
@@ -352,7 +352,7 @@ def serialize_to_json(elements: Iterable[Any],
|
|
|
352
352
|
return ''.join(self.default(child) for child in obj)
|
|
353
353
|
elif isinstance(obj, ElementNode):
|
|
354
354
|
assert isinstance(obj, EtreeElementNode)
|
|
355
|
-
elem = obj.
|
|
355
|
+
elem = obj.value
|
|
356
356
|
assert etree_module is not None
|
|
357
357
|
|
|
358
358
|
try:
|
|
@@ -368,7 +368,7 @@ def serialize_to_json(elements: Iterable[Any],
|
|
|
368
368
|
elif isinstance(obj, (AttributeNode, NamespaceNode)):
|
|
369
369
|
return f'{obj.name}="{obj.string_value}"'
|
|
370
370
|
elif isinstance(obj, TextNode):
|
|
371
|
-
return obj.
|
|
371
|
+
return obj.value
|
|
372
372
|
elif isinstance(obj, CommentNode):
|
|
373
373
|
return f'<!--{obj.string_value}-->'
|
|
374
374
|
else:
|
|
@@ -56,7 +56,7 @@ def get_node_tree(root: RootArgType,
|
|
|
56
56
|
return root.getroot()
|
|
57
57
|
elif fragment is False and \
|
|
58
58
|
isinstance(root, ElementNode) and \
|
|
59
|
-
is_etree_element_instance(root.
|
|
59
|
+
is_etree_element_instance(root.value):
|
|
60
60
|
return root.get_document_node()
|
|
61
61
|
|
|
62
62
|
return root
|
|
@@ -146,7 +146,7 @@ def select_id_function(self: XPathFunction, context: ContextType = None) \
|
|
|
146
146
|
|
|
147
147
|
if isinstance(item, (ElementNode, DocumentNode)):
|
|
148
148
|
for element in item.iter_descendants():
|
|
149
|
-
if isinstance(element, EtreeElementNode) and element.
|
|
149
|
+
if isinstance(element, EtreeElementNode) and element.value.get(XML_ID) == value:
|
|
150
150
|
yield element
|
|
151
151
|
|
|
152
152
|
|
|
@@ -380,11 +380,11 @@ def evaluate_lang_function(self: XPathFunction, context: ContextType = None) ->
|
|
|
380
380
|
return False
|
|
381
381
|
else:
|
|
382
382
|
try:
|
|
383
|
-
attr = context.item.
|
|
383
|
+
attr = context.item.value.attrib[XML_LANG]
|
|
384
384
|
except KeyError:
|
|
385
385
|
for e in context.iter_ancestors():
|
|
386
|
-
if isinstance(e, EtreeElementNode) and XML_LANG in e.
|
|
387
|
-
lang = e.
|
|
386
|
+
if isinstance(e, EtreeElementNode) and XML_LANG in e.value.attrib:
|
|
387
|
+
lang = e.value.attrib[XML_LANG]
|
|
388
388
|
if not isinstance(lang, str):
|
|
389
389
|
return False
|
|
390
390
|
break
|
|
@@ -673,7 +673,7 @@ def select_child_path(self: XPathToken, context: ContextType = None) \
|
|
|
673
673
|
elif result in items:
|
|
674
674
|
pass
|
|
675
675
|
elif isinstance(result, ElementNode):
|
|
676
|
-
if result.
|
|
676
|
+
if result.value not in items:
|
|
677
677
|
items.add(result)
|
|
678
678
|
yield result
|
|
679
679
|
else:
|
|
@@ -700,7 +700,7 @@ def select_descendant_path(self: XPathToken, context: ContextType = None) \
|
|
|
700
700
|
elif result in items:
|
|
701
701
|
pass
|
|
702
702
|
elif isinstance(result, ElementNode):
|
|
703
|
-
if result.
|
|
703
|
+
if result.value not in items:
|
|
704
704
|
items.add(result)
|
|
705
705
|
yield result
|
|
706
706
|
else:
|
|
@@ -723,7 +723,7 @@ def select_descendant_path(self: XPathToken, context: ContextType = None) \
|
|
|
723
723
|
elif result in items:
|
|
724
724
|
pass
|
|
725
725
|
elif isinstance(result, ElementNode):
|
|
726
|
-
if result.
|
|
726
|
+
if result.value not in items:
|
|
727
727
|
items.add(result)
|
|
728
728
|
else:
|
|
729
729
|
items.add(result)
|
|
@@ -155,7 +155,7 @@ def evaluate_namespace_uri_for_prefix_function(
|
|
|
155
155
|
if not isinstance(elem, EtreeElementNode):
|
|
156
156
|
return []
|
|
157
157
|
|
|
158
|
-
ns_uris = {get_namespace(e.tag) for e in elem.
|
|
158
|
+
ns_uris = {get_namespace(e.tag) for e in elem.value.iter() if not callable(e.tag)}
|
|
159
159
|
for p, uri in self.parser.namespaces.items():
|
|
160
160
|
if uri in ns_uris:
|
|
161
161
|
if p == prefix:
|
|
@@ -180,7 +180,7 @@ def select_in_scope_prefixes_function(self: XPathFunction, context: ContextType
|
|
|
180
180
|
if not isinstance(arg, ElementNode):
|
|
181
181
|
raise self.error('XPTY0004', 'argument %r is not an element node' % arg)
|
|
182
182
|
|
|
183
|
-
elem = arg.
|
|
183
|
+
elem = arg.value
|
|
184
184
|
if isinstance(context, XPathSchemaContext):
|
|
185
185
|
# For schema context returns prefixes of static namespaces
|
|
186
186
|
for pfx, uri in self.parser.namespaces.items():
|
|
@@ -1485,15 +1485,15 @@ def evaluate_lang_function(self: XPathFunction, context: ContextType = None) ->
|
|
|
1485
1485
|
raise self.error('XPTY0004')
|
|
1486
1486
|
elif isinstance(item, EtreeElementNode):
|
|
1487
1487
|
try:
|
|
1488
|
-
attr = item.
|
|
1488
|
+
attr = item.value.attrib[XML_LANG]
|
|
1489
1489
|
except KeyError:
|
|
1490
1490
|
if len(self) > 1 or context is None:
|
|
1491
1491
|
return False
|
|
1492
1492
|
|
|
1493
1493
|
for elem in context.iter_ancestors():
|
|
1494
1494
|
if isinstance(elem, EtreeElementNode):
|
|
1495
|
-
if XML_LANG in elem.
|
|
1496
|
-
lang = cast(str, elem.
|
|
1495
|
+
if XML_LANG in elem.value.attrib:
|
|
1496
|
+
lang = cast(str, elem.value.attrib[XML_LANG])
|
|
1497
1497
|
break
|
|
1498
1498
|
else:
|
|
1499
1499
|
return False
|
|
@@ -1551,8 +1551,8 @@ def select_id_function(self: XPathFunction, context: ContextType = None) -> Iter
|
|
|
1551
1551
|
if not isinstance(element, EtreeElementNode):
|
|
1552
1552
|
continue
|
|
1553
1553
|
|
|
1554
|
-
if element.
|
|
1555
|
-
idrefs.remove(element.
|
|
1554
|
+
if element.value.text in idrefs and element.is_id:
|
|
1555
|
+
idrefs.remove(element.value.text)
|
|
1556
1556
|
if self.symbol == 'id':
|
|
1557
1557
|
yield element
|
|
1558
1558
|
else:
|
|
@@ -1561,11 +1561,11 @@ def select_id_function(self: XPathFunction, context: ContextType = None) -> Iter
|
|
|
1561
1561
|
yield parent
|
|
1562
1562
|
else:
|
|
1563
1563
|
for attr in element.attributes:
|
|
1564
|
-
if not isinstance(attr.
|
|
1564
|
+
if not isinstance(attr.value, str):
|
|
1565
1565
|
continue
|
|
1566
1566
|
|
|
1567
|
-
if attr.
|
|
1568
|
-
idrefs.remove(attr.
|
|
1567
|
+
if attr.value in idrefs and attr.is_id:
|
|
1568
|
+
idrefs.remove(attr.value)
|
|
1569
1569
|
yield element
|
|
1570
1570
|
|
|
1571
1571
|
|
|
@@ -1588,7 +1588,7 @@ def select_idref_function(self: XPathFunction, context: ContextType = None) \
|
|
|
1588
1588
|
if not isinstance(element, EtreeElementNode):
|
|
1589
1589
|
continue
|
|
1590
1590
|
|
|
1591
|
-
text = element.
|
|
1591
|
+
text = element.value.text
|
|
1592
1592
|
if text and is_idrefs(text) and \
|
|
1593
1593
|
any(v in text.split() for x in ids for v in x.split()):
|
|
1594
1594
|
yield element
|
|
@@ -1596,8 +1596,8 @@ def select_idref_function(self: XPathFunction, context: ContextType = None) \
|
|
|
1596
1596
|
|
|
1597
1597
|
if element.attributes:
|
|
1598
1598
|
for attr in element.attributes: # pragma: no cover
|
|
1599
|
-
if attr.name != XML_ID and isinstance(attr.
|
|
1600
|
-
any(v in attr.
|
|
1599
|
+
if attr.name != XML_ID and isinstance(attr.value, str) and \
|
|
1600
|
+
any(v in attr.value.split() for x in ids for v in x.split()):
|
|
1601
1601
|
yield element
|
|
1602
1602
|
break
|
|
1603
1603
|
|
|
@@ -1107,7 +1107,7 @@ def evaluate_has_children_function(self: XPathFunction, context: ContextType = N
|
|
|
1107
1107
|
raise self.error('XPTY0004', 'argument must be a node')
|
|
1108
1108
|
|
|
1109
1109
|
return isinstance(item, DocumentNode) or \
|
|
1110
|
-
isinstance(item, EtreeElementNode) and (len(item.
|
|
1110
|
+
isinstance(item, EtreeElementNode) and (len(item.value) > 0 or item.value.text is not None)
|
|
1111
1111
|
|
|
1112
1112
|
|
|
1113
1113
|
@method(function('innermost', nargs=1, sequence_types=('node()*', 'node()*')))
|
|
@@ -1241,10 +1241,10 @@ def evaluate_xml_to_json_function(self: XPathFunction, context: ContextType = No
|
|
|
1241
1241
|
return ','.join(chunks)
|
|
1242
1242
|
|
|
1243
1243
|
if isinstance(input_node, DocumentNode):
|
|
1244
|
-
return elem_to_json(child.
|
|
1244
|
+
return elem_to_json(child.value for child in input_node
|
|
1245
1245
|
if isinstance(child, EtreeElementNode))
|
|
1246
1246
|
elif isinstance(input_node, EtreeElementNode):
|
|
1247
|
-
return elem_to_json((input_node.
|
|
1247
|
+
return elem_to_json((input_node.value,))
|
|
1248
1248
|
else:
|
|
1249
1249
|
raise self.error('FOJS0006')
|
|
1250
1250
|
|
|
@@ -154,7 +154,7 @@ class XPathContext:
|
|
|
154
154
|
self.document = self.root
|
|
155
155
|
elif fragment is None and \
|
|
156
156
|
isinstance(self.root, ElementNode) and \
|
|
157
|
-
is_etree_element_instance(self.root.
|
|
157
|
+
is_etree_element_instance(self.root.value):
|
|
158
158
|
# Creates a dummy document that will be not included in results
|
|
159
159
|
self.document = self.root.get_document_node(as_parent=False)
|
|
160
160
|
else:
|
|
@@ -201,9 +201,9 @@ class XPathContext:
|
|
|
201
201
|
|
|
202
202
|
def __repr__(self) -> str:
|
|
203
203
|
if self.root is not None:
|
|
204
|
-
return f'{self.__class__.__name__}(root={self.root.
|
|
204
|
+
return f'{self.__class__.__name__}(root={self.root.value})'
|
|
205
205
|
elif isinstance(self.item, XPathNode):
|
|
206
|
-
return f'{self.__class__.__name__}(item={self.item.
|
|
206
|
+
return f'{self.__class__.__name__}(item={self.item.value})'
|
|
207
207
|
else:
|
|
208
208
|
return f'{self.__class__.__name__}(item={self.item!r})'
|
|
209
209
|
|
|
@@ -223,10 +223,10 @@ class XPathContext:
|
|
|
223
223
|
@cached_property
|
|
224
224
|
def etree(self) -> ModuleType:
|
|
225
225
|
if isinstance(self.root, (DocumentNode, ElementNode)):
|
|
226
|
-
module_name = self.root.
|
|
226
|
+
module_name = self.root.value.__class__.__module__
|
|
227
227
|
elif isinstance(self.item, (DocumentNode, ElementNode, CommentNode,
|
|
228
228
|
ProcessingInstructionNode)):
|
|
229
|
-
module_name = self.item.
|
|
229
|
+
module_name = self.item.value.__class__.__module__
|
|
230
230
|
else:
|
|
231
231
|
module_name = 'xml.etree.ElementTree'
|
|
232
232
|
|
|
@@ -300,12 +300,12 @@ class XPathContext:
|
|
|
300
300
|
if isinstance(item, (XPathNode, AnyAtomicType)):
|
|
301
301
|
return item
|
|
302
302
|
elif is_etree_document(item):
|
|
303
|
-
if self.root is not None and item is self.root.
|
|
303
|
+
if self.root is not None and item is self.root.value:
|
|
304
304
|
return self.root
|
|
305
305
|
|
|
306
306
|
if self.documents:
|
|
307
307
|
for doc in self.documents.values():
|
|
308
|
-
if doc is not None and item is doc.
|
|
308
|
+
if doc is not None and item is doc.value:
|
|
309
309
|
return doc
|
|
310
310
|
|
|
311
311
|
elif is_etree_element(item):
|