robotframework-xmlvalidator 1.0.0__py3-none-any.whl → 2.0.0__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.
- {robotframework_xmlvalidator-1.0.0.dist-info → robotframework_xmlvalidator-2.0.0.dist-info}/METADATA +198 -36
- robotframework_xmlvalidator-2.0.0.dist-info/RECORD +8 -0
- xmlvalidator/XmlValidator.py +225 -148
- xmlvalidator/__init__.py +1 -1
- xmlvalidator/xml_validator_results.py +3 -3
- xmlvalidator/xml_validator_utils.py +4 -5
- robotframework_xmlvalidator-1.0.0.dist-info/RECORD +0 -8
- {robotframework_xmlvalidator-1.0.0.dist-info → robotframework_xmlvalidator-2.0.0.dist-info}/LICENSE +0 -0
- {robotframework_xmlvalidator-1.0.0.dist-info → robotframework_xmlvalidator-2.0.0.dist-info}/WHEEL +0 -0
{robotframework_xmlvalidator-1.0.0.dist-info → robotframework_xmlvalidator-2.0.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: robotframework-xmlvalidator
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: A Robot Framework test library for validating XML files against XSD schemas
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: robotframework,xml,xsd,validation,test-library,test,testing,test-automation
|
|
@@ -25,9 +25,14 @@ Project-URL: Homepage, https://github.com/MichaelHallik/robotframework-xmlvalida
|
|
|
25
25
|
Project-URL: Repository, https://github.com/MichaelHallik/robotframework-xmlvalidator
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
[](https://github.com/MichaelHallik/robotframework-xmlvalidator/actions/workflows/test.yml)
|
|
28
|
+
| Version | License | Tests |
|
|
29
|
+
|---------|---------|-------|
|
|
30
|
+
| [](https://pypi.org/project/robotframework-xmlvalidator/) | [](LICENSE) | [](https://github.com/MichaelHallik/robotframework-xmlvalidator/actions/workflows/test.yml) |
|
|
31
|
+
|
|
32
|
+
| Downloads | Update Badge |
|
|
33
|
+
|-----------|---------------|
|
|
34
|
+
| [](https://pepy.tech/project/robotframework-xmlvalidator) | [](https://github.com/MichaelHallik/robotframework-xmlvalidator/actions/workflows/update_pepy_badge.yml) |
|
|
35
|
+
|
|
31
36
|
|
|
32
37
|
<details>
|
|
33
38
|
<summary><strong>📚 Table of Contents</strong></summary>
|
|
@@ -46,14 +51,26 @@ Description-Content-Type: text/markdown
|
|
|
46
51
|
- [Examples](#examples)
|
|
47
52
|
- [Using a preloaded schema](#using-a-preloaded-schema)
|
|
48
53
|
- [Defer schema loading to the test case(s)](#defer-schema-loading-to-the-test-cases)
|
|
49
|
-
- [Importing with preloaded XSD that requires a
|
|
50
|
-
- [Importing with custom
|
|
54
|
+
- [Importing with preloaded XSD that requires a `base_url`](#importing-with-preloaded-xsd-that-requires-a-base_url)
|
|
55
|
+
- [Importing with custom `error_facets`](#importing-with-custom-error_facets)
|
|
56
|
+
- [Importing with \`fail\_on\_errors=True](#importing-with-fail_on_errorstrue)
|
|
51
57
|
- [Further examples](#further-examples)
|
|
52
58
|
- [Using the library](#using-the-library)
|
|
53
59
|
- [Keyword overview](#keyword-overview)
|
|
60
|
+
- [Error collection](#error-collection)
|
|
61
|
+
- [Batch mode](#batch-mode)
|
|
62
|
+
- [Single file mode](#single-file-mode)
|
|
63
|
+
- [Test case status - fail\_on\_error](#test-case-status---fail_on_error)
|
|
64
|
+
- [Dyanmic XSD resolution](#dyanmic-xsd-resolution)
|
|
65
|
+
- [Error collection](#error-collection-1)
|
|
66
|
+
- [XSD Schema violations.](#xsd-schema-violations)
|
|
67
|
+
- [Malformed XML](#malformed-xml)
|
|
68
|
+
- [File-level issues](#file-level-issues)
|
|
69
|
+
- [Final note on error collection](#final-note-on-error-collection)
|
|
54
70
|
- [Keyword documentation](#keyword-documentation)
|
|
55
71
|
- [Keyword example usage](#keyword-example-usage)
|
|
56
72
|
- [A few basic examples](#a-few-basic-examples)
|
|
73
|
+
- [Demo test suite file as examples](#demo-test-suite-file-as-examples)
|
|
57
74
|
- [Integration tests as examples](#integration-tests-as-examples)
|
|
58
75
|
- [Example console output](#example-console-output)
|
|
59
76
|
- [Example CSV output](#example-csv-output)
|
|
@@ -75,6 +92,8 @@ Description-Content-Type: text/markdown
|
|
|
75
92
|
- [Continuous Integration \& GitHub templates](#continuous-integration--github-templates)
|
|
76
93
|
- [Class architecture (Simplified)](#class-architecture-simplified)
|
|
77
94
|
- [Project Structure](#project-structure)
|
|
95
|
+
- [Changelog](#changelog)
|
|
96
|
+
- [Roadmap](#roadmap)
|
|
78
97
|
- [License](#license)
|
|
79
98
|
- [Author](#author)
|
|
80
99
|
|
|
@@ -99,7 +118,7 @@ It provides structured and detailed reporting of XML parse errors (malformed XML
|
|
|
99
118
|
- Customizable error attributes (`path`, `reason`, `message`, etc.)
|
|
100
119
|
- Batch validation and per-file error tracking
|
|
101
120
|
- Export collected errors to CSV (with optional file name timestamping).
|
|
102
|
-
- And more
|
|
121
|
+
- And more.
|
|
103
122
|
|
|
104
123
|
---
|
|
105
124
|
|
|
@@ -147,11 +166,12 @@ See the [Robot Framework Library Scope docs](https://robotframework.org/robotfra
|
|
|
147
166
|
|
|
148
167
|
### Library arguments
|
|
149
168
|
|
|
150
|
-
| Argument
|
|
151
|
-
|
|
152
|
-
| `xsd_path`
|
|
153
|
-
| `base_url`
|
|
154
|
-
| `error_facets`
|
|
169
|
+
| Argument | Type | Required? | Description | Default |
|
|
170
|
+
|-----------------|-------------|-----------|------------------------------------------------------------------------------------------------------------------------|-----------------|
|
|
171
|
+
| `xsd_path` | `str` | No | Path to an XSD file/folder to preload during initialization. In case of a folder, the folder must hold one file only. | None |
|
|
172
|
+
| `base_url` | `str` | No | Base path used to resolve includes/imports within the provided XSD schema. | None |
|
|
173
|
+
| `error_facets` | `list[str]` | No | The attributes of validation errors to collect and report (e.g., `path`, `reason`) | [path, reason] |
|
|
174
|
+
| `fail_on_error` | `bool` | No | Whether to fail the test case if one or more XML validation errors are found. Can be overridden per keyword call. | True |
|
|
155
175
|
|
|
156
176
|
### Examples
|
|
157
177
|
|
|
@@ -168,7 +188,7 @@ Library xmlvalidator xsd_path=path/to/schema.xsd
|
|
|
168
188
|
Library xmlvalidator
|
|
169
189
|
```
|
|
170
190
|
|
|
171
|
-
#### Importing with preloaded XSD that requires a base_url
|
|
191
|
+
#### Importing with preloaded XSD that requires a `base_url`
|
|
172
192
|
|
|
173
193
|
```robotframework
|
|
174
194
|
Library xmlvalidator xsd_path=path/to/schema_with_include.xsd
|
|
@@ -177,7 +197,7 @@ Library xmlvalidator xsd_path=path/to/schema_with_include.xsd
|
|
|
177
197
|
|
|
178
198
|
Use `base_url` when your XSD uses `<xs:include>` or `<xs:import>` with relative paths.
|
|
179
199
|
|
|
180
|
-
#### Importing with custom error_facets
|
|
200
|
+
#### Importing with custom `error_facets`
|
|
181
201
|
|
|
182
202
|
Use the `error_facets` argument to control which attributes of detected errors will be collected and reported.
|
|
183
203
|
|
|
@@ -196,6 +216,21 @@ Library xmlvalidator xsd_path=schemas/schema.xsd
|
|
|
196
216
|
... error_facets=value, namespaces
|
|
197
217
|
```
|
|
198
218
|
|
|
219
|
+
#### Importing with `fail_on_errors=True
|
|
220
|
+
|
|
221
|
+
The fail_on_errors argument controls whether a test case should fail if XML validation errors are detected.
|
|
222
|
+
|
|
223
|
+
It defaults to True.
|
|
224
|
+
|
|
225
|
+
The library's batch validation behavior remains unchanged. That is, `fail_on_errors=True` does *not* short-circuit the validation process in any way.
|
|
226
|
+
|
|
227
|
+
Set `fail_on_errors=False` to log validation issues without failing the test. This is useful for:
|
|
228
|
+
|
|
229
|
+
- Non-blocking checks in dashboards or QA reports.
|
|
230
|
+
- Legacy or transitional systems where some invalid files are expected.
|
|
231
|
+
- Schema discovery or diagnostics, where conformance isn’t yet enforced.
|
|
232
|
+
- Soft rollout of stricter validation rules, allowing time to adapt.
|
|
233
|
+
|
|
199
234
|
#### Further examples
|
|
200
235
|
|
|
201
236
|
See also the [library initialization Robot test file](test/integration/01_library_initialization.robot).
|
|
@@ -206,43 +241,154 @@ See also the [library initialization Robot test file](test/integration/01_librar
|
|
|
206
241
|
|
|
207
242
|
### Keyword overview
|
|
208
243
|
|
|
209
|
-
|
|
210
|
-
|
|
244
|
+
Thi section merely provides a short summary of the library's capabilities.
|
|
245
|
+
|
|
246
|
+
For more details, please see the [keyword documentation](https://michaelhallik.github.io/robotframework-xmlvalidator/XmlValidator.html).
|
|
247
|
+
|
|
248
|
+
| Keyword | Description |
|
|
249
|
+
|--------------------------|---------------------------------------------------------------------|
|
|
211
250
|
| `Validate Xml Files` | Validate one or more XML files against one or more XSD schema files |
|
|
212
|
-
| `Reset Schema` | Clear the currently loaded XSD schema
|
|
213
|
-
| `Reset Errors` | Clear the set of collected errors
|
|
214
|
-
| `Get Schema` | Get the current schema name or object
|
|
215
|
-
| `Log Schema` | Log the currently loaded schema
|
|
216
|
-
| `Get Error Facets` | Returns a list of the currently active error facets
|
|
217
|
-
| `Reset Error Facets` | Reset the error facets to default (`path`, `reason`)
|
|
251
|
+
| `Reset Schema` | Clear the currently loaded XSD schema |
|
|
252
|
+
| `Reset Errors` | Clear the set of collected errors |
|
|
253
|
+
| `Get Schema` | Get the current schema name or object |
|
|
254
|
+
| `Log Schema` | Log the currently loaded schema |
|
|
255
|
+
| `Get Error Facets` | Returns a list of the currently active error facets |
|
|
256
|
+
| `Reset Error Facets` | Reset the error facets to default (`path`, `reason`) |
|
|
218
257
|
|
|
219
258
|
The main keyword is `Validate Xml Files`. The other keywords are convenience/helper functions, e.g. 'Reset Error Facets'.
|
|
220
259
|
|
|
260
|
+
#### Error collection
|
|
261
|
+
|
|
221
262
|
The `Validate Xml Files` validates one or more XML files against one or more XSD schema files and collects and reports all encountered errors.
|
|
222
263
|
|
|
223
|
-
The type of error that the keyword can detect is not limited to XSD violations, but may also pertain to malformed XML files
|
|
264
|
+
The type of error that the keyword can detect is not limited to XSD violations, but may also pertain to malformed XML files, empty files, unmatched XML files (no XSD match found), etc.
|
|
224
265
|
|
|
225
266
|
Errors that result from malformed XML files or from XSD violations support detailed error reporting. Using the `error_facets` argument you may specify the details the keyword should collect and report about captured errors.
|
|
226
267
|
|
|
227
|
-
|
|
268
|
+
#### Batch mode
|
|
269
|
+
|
|
270
|
+
The `Validate Xml Files` keyword always validates the entire set of passed XML files.
|
|
228
271
|
|
|
229
|
-
That is, when it encounters an error in a file, it does not fail. Rather, it collects the error details (as determined by the `error_facets` arg) and then continues validating the current file as well as any subsequent file(s).
|
|
272
|
+
That is, when it encounters an error in a file, it does not fail and stop execution. Rather, it collects the error details (as determined by the `error_facets` arg) and then continues validating the current file as well as any subsequent file(s).
|
|
230
273
|
|
|
231
274
|
In that fashion the keyword works through the entire set of files.
|
|
232
275
|
|
|
233
|
-
|
|
276
|
+
Once *all* files are processed it will log a summary of the test run and then proceed to report all collected errors in the console, in the RF log and, optionally, in the form of a CSV file.
|
|
234
277
|
|
|
235
|
-
|
|
278
|
+
For example:
|
|
279
|
+
- If you validate fifteen XML files and five of them contain schema violations or other errors, all files will still be processed.
|
|
280
|
+
- Errors are simply collected throughout the run and reported collectively, only after the final file has been (fully) processed.
|
|
281
|
+
- The test case will fail (assuming `fail_on_errors=True`) only after all files have been checked, ensuring comprehensive diagnostics.
|
|
236
282
|
|
|
237
|
-
|
|
283
|
+
#### Single file mode
|
|
238
284
|
|
|
239
285
|
Of course, you may also refer to specific XML/XSD files (instead of to folders). In that case, no matching will be attempted, but the keyword will simply try to validate the specified XML file against the specified XSD file.
|
|
240
286
|
|
|
241
|
-
|
|
287
|
+
Actually, almost anything goes:
|
|
288
|
+
|
|
289
|
+
- one folder with: one or more XML files and one or more XSD files
|
|
290
|
+
- one folder with one or more XML files and another folder with one or more XSD files
|
|
291
|
+
- one folder with one or more XML files and a single XSD file
|
|
292
|
+
- a single XML file and a sigle XSD file
|
|
293
|
+
|
|
294
|
+
#### Test case status - fail_on_error
|
|
295
|
+
|
|
296
|
+
A test case that has resulted in the collection of one or more errors (of whatever type) will receive a status of FAIL. You can use the ``fail_on_errors`` (bool) argument to change this default behaviour. When set to `False`, the test cases's status will always be PASS, regardless whether errors were collected or not.
|
|
297
|
+
|
|
298
|
+
#### Dyanmic XSD resolution
|
|
299
|
+
|
|
300
|
+
The keyword further supports the dynamic matching (i.e. pairing) of XML and XSD files, using either a 'by filename' or a 'by namespace' strategy. That means you can simply pass the paths to a folder containing XML files and to a folder containing XSD files and the keyword will determine which XSD schema file to use for each XML file. If the XML and XSD files reside in the same folder, you only have to pass one folder path. When no matching XSD schema could be identified for an XML file, this will be integrated into the mentioned summary and error reporting (the keyword will not fail).
|
|
301
|
+
|
|
302
|
+
### Error collection
|
|
303
|
+
|
|
304
|
+
Errors that are collected and reported can be categorized as follows:
|
|
305
|
+
|
|
306
|
+
#### XSD Schema violations.
|
|
307
|
+
|
|
308
|
+
- Missing or extra elements that violate cardinality rules, e.g.:
|
|
309
|
+
- Verifies that all mandatory elements (minOccurs > 0) are present in the XML.
|
|
310
|
+
- Ensures that optional elements (minOccurs = 0) do not exceed their maximum allowed occurrences (maxOccurs).
|
|
311
|
+
|
|
312
|
+
- Sequence and order violations:
|
|
313
|
+
- Validates the order of child elements within a parent element if the schema specifies a sequence model (`<xsd:sequence>`).
|
|
314
|
+
- Detects elements that are out of order or missing in a sequence.
|
|
315
|
+
|
|
316
|
+
- Datatype violations:
|
|
317
|
+
- Ensures that element and attribute values conform to their specified datatypes (e.g., xs:string, xs:integer, xs:dateTime).
|
|
318
|
+
- Identifies invalid formats, such as incorrect date or time formats for xs:date and xs:dateTime.
|
|
319
|
+
|
|
320
|
+
- Pattern and enumeration violations:
|
|
321
|
+
- Checks that values conform to patterns defined using `<xsd:pattern>`.
|
|
322
|
+
- Ensures that values fall within allowed enumerations specified in the schema.
|
|
323
|
+
|
|
324
|
+
- Attribute validation:
|
|
325
|
+
- Verifies that required attributes are present.
|
|
326
|
+
- Ensures that attribute values adhere to their declared datatypes and constraints.
|
|
327
|
+
|
|
328
|
+
- Namespace compliance:
|
|
329
|
+
- Validates that elements and attributes belong to the correct namespaces as defined in the schema.
|
|
330
|
+
- Detects namespace mismatches or missing namespace declarations.
|
|
331
|
+
|
|
332
|
+
- Group model violations:
|
|
333
|
+
- Validates conformance with `<xsd:choice>` and `<xsd:all>` group models, ensuring correct usage of child elements as per the schema.
|
|
334
|
+
|
|
335
|
+
- Referential constraints:
|
|
336
|
+
- Checks for violations in `<xsd:key>`, `<xsd:keyref>`, and `<xsd:unique>` constraints.
|
|
337
|
+
|
|
338
|
+
- Document structure and completeness:
|
|
339
|
+
- Ensures that the XML document adheres to the hierarchical structure defined by the schema.
|
|
340
|
+
- Detects incomplete or improperly nested elements.
|
|
341
|
+
|
|
342
|
+
- General schema violations:
|
|
343
|
+
- Detects schema-level issues, such as invalid imports or includes, during schema compilation if they affect validation.
|
|
344
|
+
|
|
345
|
+
#### Malformed XML
|
|
346
|
+
|
|
347
|
+
Malformed XML errors arise from issues that prevent the XML file from being parsed at all, before schema validation can even occur. These errors typically reflect syntactic problems in the structure or encoding of the XML content.
|
|
348
|
+
|
|
349
|
+
Typical cases include:
|
|
350
|
+
|
|
351
|
+
- Mismatched tags
|
|
352
|
+
- Opening and closing tags do not match.
|
|
353
|
+
- Example: `<Title>My Book</title>`
|
|
354
|
+
|
|
355
|
+
- Unclosed elements
|
|
356
|
+
- Elements are left unclosed or self-closing syntax is incorrect.
|
|
357
|
+
- Example: `<Price>12.99`
|
|
358
|
+
|
|
359
|
+
- Premature end-of-file
|
|
360
|
+
- The file ends abruptly before all tags are closed, often due to truncation or corruption.
|
|
361
|
+
- Example: `<Product><ID>123`
|
|
362
|
+
|
|
363
|
+
- Invalid characters or encoding
|
|
364
|
+
- The XML includes characters that are not valid in the declared encoding or in XML itself.
|
|
365
|
+
- Example: Control characters or non-UTF-8 bytes.
|
|
366
|
+
|
|
367
|
+
- Misused namespaces
|
|
368
|
+
- Prefixes declared but not bound, or invalid namespace URIs used.
|
|
369
|
+
|
|
370
|
+
- Declaration errors
|
|
371
|
+
- Malformed or duplicate `<?xml ... ?>` declarations.
|
|
372
|
+
|
|
373
|
+
#### File-level issues
|
|
374
|
+
|
|
375
|
+
General errors that do not pertain to syntax or schema issues:
|
|
376
|
+
|
|
377
|
+
| Error Type | Description |
|
|
378
|
+
|--------------|-------------------------------------------|
|
|
379
|
+
| Missing File | The specified XML file could not be found |
|
|
380
|
+
| Empty File | The file exists but is completely empty |
|
|
381
|
+
| Wrong Format | The file is not `.xml` or `.xsd` |
|
|
382
|
+
|
|
383
|
+
#### Final note on error collection
|
|
384
|
+
|
|
385
|
+
On account of the purpose of this library, all encountered errors (regardless the involved types) are collected and reported. The validator analyzes all files, collects encountered errors (if any) and, finally, reports the results of the run in the console and in the Robot Framework log.
|
|
386
|
+
|
|
387
|
+
Every test case in which one or more errors have been collected, will receive status FAIL unless `fail_on_errors=True` (see earlier explanations).
|
|
242
388
|
|
|
243
389
|
### Keyword documentation
|
|
244
390
|
|
|
245
|
-
See [keyword
|
|
391
|
+
See the [keyword documentation](https://michaelhallik.github.io/robotframework-xmlvalidator/XmlValidator.html).
|
|
246
392
|
|
|
247
393
|
The keyword documentation provides detailed descriptions of all functionalities, features and the various ways in which the library and its keywords can be employed.
|
|
248
394
|
|
|
@@ -287,6 +433,10 @@ Validate Folder With Multiple Schemas By File Name
|
|
|
287
433
|
Validate Xml Files ${FOLDER_MULTIPLE_XML_XSD_FN} xsd_search_strategy=by_file_name
|
|
288
434
|
```
|
|
289
435
|
|
|
436
|
+
#### Demo test suite file as examples
|
|
437
|
+
|
|
438
|
+
See the [demo test suite](test/demo/demo.robot) for a demo test suite that demonstrates the most important features of the library in a concise fashion.
|
|
439
|
+
|
|
290
440
|
#### Integration tests as examples
|
|
291
441
|
|
|
292
442
|
Note that the [integration test](test/integration) folder contains seven Robot Framework test suite files.
|
|
@@ -403,7 +553,7 @@ These are the facets (or attributes) that can be collected and reported for each
|
|
|
403
553
|
| `severity` | The severity level of the error (not always present). |
|
|
404
554
|
| `args` | The arguments passed to the error message formatting.
|
|
405
555
|
|
|
406
|
-
Use the `error_facets`
|
|
556
|
+
Use the `error_facets` argument to set which error details to collect.
|
|
407
557
|
|
|
408
558
|
For each error that is encountered, the selected error facet(s) will be collected and reported.
|
|
409
559
|
|
|
@@ -413,7 +563,7 @@ You can customize which error facet(s) should be collected, by passing a list of
|
|
|
413
563
|
|
|
414
564
|
Error facets passed during library initialization will be overruled by error facets that are passed at the test case level, when calling the `Validate Xml Files` keyword.
|
|
415
565
|
|
|
416
|
-
The values you can pass through the `error_facets` argument are based on the attributes of the error objects as returned by the XMLSchema.iter_errors() method, that is provided by the xmlschema library and the
|
|
566
|
+
The values you can pass through the `error_facets` argument are based on the attributes of the error objects as returned by the XMLSchema.iter_errors() method, that is provided by the xmlschema library and the xmlvalidator library leverages. Said method yields instances of xmlschema.validators.exceptions.XMLSchemaValidationError (or its subclasses), each representing a specific validation issue encountered in an XML file. These error objects expose various attributes that describe the nature, location, and cause of the problem.
|
|
417
567
|
|
|
418
568
|
The table lists the most commonly available attributes, though additional fields may be available depending on the type of validation error.
|
|
419
569
|
|
|
@@ -427,7 +577,7 @@ The table lists the most commonly available attributes, though additional fields
|
|
|
427
577
|
| [CHANGELOG](CHANGELOG.md) | User / Dev | Version history, features |
|
|
428
578
|
| [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) | Dev | Community guidelines |
|
|
429
579
|
| [CONTRIBUTING](CONTRIBUTING.md) | Dev | Contribute |
|
|
430
|
-
| [Mermaid diagram of GitHub Actions](github_actions.md) | Dev | CI, GitHub Actions |
|
|
580
|
+
| [Mermaid diagram of GitHub Actions](docs/images/github_actions.md) | Dev | CI, GitHub Actions |
|
|
431
581
|
| [License](LICENSE) | All | Legal usage terms |
|
|
432
582
|
| [Make file](Makefile) | Dev | Automation, commands |
|
|
433
583
|
| [Project Structure](project_structure.txt) | Dev | Project layout |
|
|
@@ -450,7 +600,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
|
450
600
|
|
|
451
601
|
The overall process:
|
|
452
602
|
|
|
453
|
-

|
|
454
604
|
|
|
455
605
|
This project uses Poetry for dependency and packaging management.
|
|
456
606
|
|
|
@@ -475,7 +625,7 @@ poetry install
|
|
|
475
625
|
poetry shell
|
|
476
626
|
```
|
|
477
627
|
|
|
478
|
-
Or, if you use a different virt
|
|
628
|
+
Or, if you use a different virt environment, activate that.
|
|
479
629
|
|
|
480
630
|
### Running tests
|
|
481
631
|
|
|
@@ -535,7 +685,7 @@ GitHub Actions CI is defined under [github/workflows/](.github/workflows/), in p
|
|
|
535
685
|
|
|
536
686
|
The test workflow:
|
|
537
687
|
|
|
538
|
-

|
|
539
689
|
|
|
540
690
|
In [.github/](.github/) you’ll also find the various contribution templates:
|
|
541
691
|
|
|
@@ -675,6 +825,18 @@ requirements.txt # Requirements file for users (pip)
|
|
|
675
825
|
|
|
676
826
|
---
|
|
677
827
|
|
|
828
|
+
## Changelog
|
|
829
|
+
|
|
830
|
+
For a list of changes across versions, including recent behavioral changes in validation logic, see the [CHANGELOG](https://github.com/MichaelHallik/robotframework-xmlvalidator/blob/main/CHANGELOG.md).
|
|
831
|
+
|
|
832
|
+
---
|
|
833
|
+
|
|
834
|
+
## Roadmap
|
|
835
|
+
|
|
836
|
+
See the [project roadmap](ROADMAP.md) for upcoming features and ideas.
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
678
840
|
## License
|
|
679
841
|
|
|
680
842
|
Licensed under the Apache License 2.0. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
xmlvalidator/__init__.py,sha256=xsEr0B8N7ex4bh5xyYPoxUP3nYofoEI2ANT94jrOlCk,2293
|
|
2
|
+
xmlvalidator/xml_validator_results.py,sha256=JDkoGLO91HE7Ar1HXWLj7Olc0VtLZH_e43JAPPrWykA,13124
|
|
3
|
+
xmlvalidator/xml_validator_utils.py,sha256=VPSwcLVziuR9erj-jYRqvHKP-jrFf1bcrgshxcSqXKA,17807
|
|
4
|
+
xmlvalidator/XmlValidator.py,sha256=a3vZVGIKXyNKD7UQk8AOrHKvRu1-sQSiyquo-0eiDbc,75204
|
|
5
|
+
robotframework_xmlvalidator-2.0.0.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
6
|
+
robotframework_xmlvalidator-2.0.0.dist-info/METADATA,sha256=5dJCEUl5Kmp41hI_2Qby-yX1UZFZcQD4oyJWKapijY0,38768
|
|
7
|
+
robotframework_xmlvalidator-2.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
8
|
+
robotframework_xmlvalidator-2.0.0.dist-info/RECORD,,
|
xmlvalidator/XmlValidator.py
CHANGED
|
@@ -40,9 +40,9 @@ or executed as a Python module via a direct call.
|
|
|
40
40
|
"""
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
# pylint: disable=C0103:invalid-name
|
|
44
|
-
# pylint: disable=C0302:too-many-lines
|
|
45
|
-
# pylint: disable=C0301:line-too-long
|
|
43
|
+
# pylint: disable=C0103:invalid-name # On account of the module name, that is not snake-cased (required by Robot Framework).
|
|
44
|
+
# pylint: disable=C0302:too-many-lines # On account of the extensive docstrings and annotations.
|
|
45
|
+
# pylint: disable=C0301:line-too-long # On account of tables in docstrings.
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
# Standard library imports.
|
|
@@ -82,9 +82,9 @@ class XmlValidator:
|
|
|
82
82
|
The other keywords are convenience/helper functions, e.g. ``Reset
|
|
83
83
|
Error Facets``.
|
|
84
84
|
|
|
85
|
-
The ``Validate Xml Files`` validates one or more XML files against
|
|
86
|
-
or more XSD schema files and collects and reports all
|
|
87
|
-
errors.
|
|
85
|
+
The ``Validate Xml Files`` validates one or more XML files against
|
|
86
|
+
one or more XSD schema files and collects and reports all
|
|
87
|
+
encountered errors.
|
|
88
88
|
|
|
89
89
|
The type of error that the keyword can detect is not limited to XSD
|
|
90
90
|
violations, but may also pertain to malformed XML files (e.g. parse
|
|
@@ -92,16 +92,16 @@ class XmlValidator:
|
|
|
92
92
|
others.
|
|
93
93
|
|
|
94
94
|
Errors that result from malformed XML files or from XSD violations
|
|
95
|
-
support detailed error reporting. Using the ``error_facets``
|
|
96
|
-
you may specify the details the keyword should collect and
|
|
97
|
-
about captured errors.
|
|
95
|
+
support detailed error reporting. Using the ``error_facets``
|
|
96
|
+
argument you may specify the details the keyword should collect and
|
|
97
|
+
report about captured errors.
|
|
98
98
|
|
|
99
99
|
When operating in batch mode, the ``Validate Xml Files`` keyword
|
|
100
100
|
always validates the entire set of passed XML files. That is, when
|
|
101
|
-
it encounters an error in a file, it does not simply fail.
|
|
102
|
-
it collects the error details (as determined by the
|
|
103
|
-
arg) and then continues validating the current file as
|
|
104
|
-
subsequent file(s).
|
|
101
|
+
it encounters an error in a file, it does not simply then fail.
|
|
102
|
+
Rather, it collects the error details (as determined by the
|
|
103
|
+
error_facets arg) and then continues validating the current file as
|
|
104
|
+
well as any subsequent file(s).
|
|
105
105
|
|
|
106
106
|
In that fashion the keyword works through the entire set of files.
|
|
107
107
|
|
|
@@ -158,12 +158,14 @@ class XmlValidator:
|
|
|
158
158
|
- Namespace errors.
|
|
159
159
|
- Etc.
|
|
160
160
|
|
|
161
|
-
- Captures malformed XML.
|
|
161
|
+
- Captures malformed XML (e.g. missing closing tag, encoding
|
|
162
|
+
issues).
|
|
162
163
|
- Handles edge cases like empty files or XML files that could not be
|
|
163
164
|
matched to an XSD schema file.
|
|
164
|
-
- Does not fail on errors, but collects encountered
|
|
165
|
-
files and reports them in a structured format in the
|
|
166
|
-
RF log.
|
|
165
|
+
- Does not immediately fail on errors, but collects encountered all
|
|
166
|
+
errors in all files and reports them in a structured format in the
|
|
167
|
+
console and RF log. Only *then* fails (assuming one or more
|
|
168
|
+
errors have been collected).
|
|
167
169
|
- Supports specifying the details that should be collected for
|
|
168
170
|
encountered errors.
|
|
169
171
|
- Optionally exports the error report to a CSV file, providing the
|
|
@@ -236,23 +238,13 @@ class XmlValidator:
|
|
|
236
238
|
Enables resolution of schema imports/includes via a custom base URL,
|
|
237
239
|
via the ``base_url`` arg.
|
|
238
240
|
|
|
239
|
-
Use ``base_url`` when your XSD uses
|
|
240
|
-
relative paths.
|
|
241
|
+
Use ``base_url`` when your XSD uses ``<xs:include>`` or ``<xs:import>``
|
|
242
|
+
with relative paths.
|
|
241
243
|
|
|
242
244
|
You can pass ``base_url`` with the library import (together with
|
|
243
245
|
passing ``xsd_path``) and/or when calling ``Validate Xml Files``
|
|
244
246
|
with ``xsd_path``.
|
|
245
247
|
|
|
246
|
-
** Optional test case fail **
|
|
247
|
-
|
|
248
|
-
The ``Validate Xml Files`` keyword collects one or more errors for
|
|
249
|
-
one or more XML files. As mentioned earlier, the keyword is designed
|
|
250
|
-
so as to not fail upon encountering errors.
|
|
251
|
-
|
|
252
|
-
However, in case you want your test case to fail when one or more
|
|
253
|
-
errors have been detected, you can use the ``fail_on_errors`` (bool)
|
|
254
|
-
argument to make it so. It defaults to ${False}.
|
|
255
|
-
|
|
256
248
|
**Basic usage examples**
|
|
257
249
|
|
|
258
250
|
For a comprehensive set of example test cases, please see the
|
|
@@ -266,6 +258,18 @@ class XmlValidator:
|
|
|
266
258
|
It further contains a detailed instruction on
|
|
267
259
|
`how to run Robot Framework tests <https://github.com/MichaelHallik/robotframework-xmlvalidator/blob/main/test/_doc/integration/README.md>`_.
|
|
268
260
|
|
|
261
|
+
Finally, the repo also contains a `demo test suite file <https://github.com/MichaelHallik/robotframework-xmlvalidator/blob/main/test/demo/demo.robot>`_ containing
|
|
262
|
+
eight self-contained test cases to demonstrates the following features:
|
|
263
|
+
|
|
264
|
+
- Single and batch XML validation
|
|
265
|
+
- Schema matching by filename and namespace
|
|
266
|
+
- Custom error facets
|
|
267
|
+
- Malformed XML handling
|
|
268
|
+
- XSD includes/imports
|
|
269
|
+
- CSV export
|
|
270
|
+
|
|
271
|
+
A test suite file may look like the following:
|
|
272
|
+
|
|
269
273
|
.. code:: robotframework
|
|
270
274
|
|
|
271
275
|
*** Settings ***
|
|
@@ -361,21 +365,8 @@ class XmlValidator:
|
|
|
361
365
|
[ WARN ] XML is invalid:
|
|
362
366
|
[ WARN ] Error #0:
|
|
363
367
|
[ WARN ] reason: No matching XSD found for: no_xsd_match_2.xml.
|
|
364
|
-
Validation errors exported to
|
|
365
|
-
|
|
366
|
-
Valid files: 6.
|
|
367
|
-
Invalid files: 5
|
|
368
|
-
01 Advanced Validation:: Demo XML validation | PASS |
|
|
369
|
-
21 errors have been detected.
|
|
370
|
-
========================================================
|
|
371
|
-
01 Advanced Validation:: Demo XML validation | PASS |
|
|
372
|
-
1 test, 1 passed, 0 failed
|
|
373
|
-
|
|
374
|
-
In case ``fail_on_errors`` is True, the console output will look like this:
|
|
375
|
-
|
|
376
|
-
.. code:: console
|
|
377
|
-
|
|
378
|
-
Validation errors exported to 'C:\\test\\01_Advanced_Validation\\errors_2025-03-29_13-54-46-552150.csv'.
|
|
368
|
+
Validation errors exported to:
|
|
369
|
+
'C:\\test\\01_Advanced_Validation\\errors_2025-03-29_13-54-46-552150.csv'.
|
|
379
370
|
Total_files validated: 11.
|
|
380
371
|
Valid files: 6.
|
|
381
372
|
Invalid files: 5.
|
|
@@ -384,8 +375,8 @@ class XmlValidator:
|
|
|
384
375
|
========================================================
|
|
385
376
|
01 Advanced Validation:: Demo XML validation | FAIL |
|
|
386
377
|
1 test, 0 passed, 1 failed
|
|
387
|
-
|
|
388
|
-
The corresponding CSV output
|
|
378
|
+
|
|
379
|
+
The corresponding CSV output will look like:
|
|
389
380
|
|
|
390
381
|
.. code:: text
|
|
391
382
|
|
|
@@ -402,16 +393,17 @@ class XmlValidator:
|
|
|
402
393
|
|
|
403
394
|
"""
|
|
404
395
|
|
|
405
|
-
__version__ = '
|
|
396
|
+
__version__ = '2.0.0'
|
|
406
397
|
ROBOT_LIBRARY_DOC_FORMAT = 'reST'
|
|
407
398
|
nr_instances = 0
|
|
408
399
|
|
|
409
400
|
def __init__(
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
401
|
+
self,
|
|
402
|
+
xsd_path: str | Path | None = None,
|
|
403
|
+
base_url: str | None = None,
|
|
404
|
+
error_facets: List[str] | None = None,
|
|
405
|
+
fail_on_errors: bool = True
|
|
406
|
+
) -> None:
|
|
415
407
|
"""
|
|
416
408
|
**Library Scope**
|
|
417
409
|
|
|
@@ -421,16 +413,19 @@ class XmlValidator:
|
|
|
421
413
|
|
|
422
414
|
**Library Arguments**
|
|
423
415
|
|
|
424
|
-
|
|
425
|
-
| Argument
|
|
426
|
-
|
|
427
|
-
| xsd_path
|
|
428
|
-
|
|
|
429
|
-
|
|
430
|
-
| base_url
|
|
431
|
-
|
|
432
|
-
| error_facets
|
|
433
|
-
|
|
416
|
+
+---------------+-------------+----------+---------------------------------------------------------------------------------------------+----------------+
|
|
417
|
+
| Argument | Type | Required | Description | Default |
|
|
418
|
+
+===============+=============+==========+=============================================================================================+================+
|
|
419
|
+
| xsd_path | str | No | Path to an XSD file or folder to preload during initialization. | None |
|
|
420
|
+
| | | | In case of a folder, the folder must hold one file only. | |
|
|
421
|
+
+---------------+-------------+----------+---------------------------------------------------------------------------------------------+----------------+
|
|
422
|
+
| base_url | str | No | Base path used to resolve includes/imports within the provided XSD schema. | None |
|
|
423
|
+
+---------------+-------------+----------+---------------------------------------------------------------------------------------------+----------------+
|
|
424
|
+
| error_facets | list of str | No | The attributes of validation errors to collect and report. E.g. ``path``, ``reason``. | [path, reason] |
|
|
425
|
+
+---------------+-------------+----------+---------------------------------------------------------------------------------------------+----------------+
|
|
426
|
+
| fail_on_error | bool | No | Whether to fail the test case if one or more XML validation errors are found. | True |
|
|
427
|
+
| | | | Can be overridden per keyword call. | |
|
|
428
|
+
+---------------+-------------+----------+---------------------------------------------------------------------------------------------+----------------+
|
|
434
429
|
|
|
435
430
|
All arguments are optional.
|
|
436
431
|
|
|
@@ -485,6 +480,30 @@ class XmlValidator:
|
|
|
485
480
|
|
|
486
481
|
See the introduction for more details on the purpose and usage
|
|
487
482
|
of error facets.
|
|
483
|
+
|
|
484
|
+
``fail_on_error``
|
|
485
|
+
|
|
486
|
+
The ``fail_on_errors`` argument controls whether a test case
|
|
487
|
+
should fail if one or more XML validation errors are detected.
|
|
488
|
+
It defaults to True. A test case that has resulted in the
|
|
489
|
+
collection of one or more errors (of whatever type) will then
|
|
490
|
+
receive a status of FAIL.
|
|
491
|
+
|
|
492
|
+
You can use the ``fail_on_errors`` argument to change this
|
|
493
|
+
default behaviour. When set to False, a test cases's status will
|
|
494
|
+
always be PASS, regardless whether errors were collected or not.
|
|
495
|
+
|
|
496
|
+
This may be useful for:
|
|
497
|
+
|
|
498
|
+
- Non-blocking checks in dashboards or QA reports.
|
|
499
|
+
- Legacy or transitional systems where some invalid files are expected.
|
|
500
|
+
- Schema discovery or diagnostics, where conformance isn’t yet enforced.
|
|
501
|
+
- Soft rollout of stricter validation rules, allowing time to adapt.
|
|
502
|
+
|
|
503
|
+
Note that with ``fail_on_error=True`` the library's batch
|
|
504
|
+
validation behavior remains unchanged by the latter. That is,
|
|
505
|
+
fail_on_errors=True does not short-circuit the validation
|
|
506
|
+
process in any way.
|
|
488
507
|
|
|
489
508
|
**Examples**
|
|
490
509
|
|
|
@@ -530,6 +549,8 @@ class XmlValidator:
|
|
|
530
549
|
For more examples see the project's
|
|
531
550
|
`Robot Framework integration test suite <https://github.com/MichaelHallik/robotframework-xmlvalidator/blob/main/test/integration/01_library_initialization.robot>`_.
|
|
532
551
|
|
|
552
|
+
And also the `demo test suite file <https://github.com/MichaelHallik/robotframework-xmlvalidator/blob/main/test/demo/demo.robot>`_.
|
|
553
|
+
|
|
533
554
|
**Raises**
|
|
534
555
|
|
|
535
556
|
+---------------+--------------------------------------------------------------+
|
|
@@ -549,62 +570,38 @@ class XmlValidator:
|
|
|
549
570
|
self.validator_utils = ValidatorUtils()
|
|
550
571
|
self.validator_results = ValidatorResultRecorder()
|
|
551
572
|
# Initialize the xsd schema from the xsd_path, if provided.
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
self.validator_utils.get_file_paths(
|
|
556
|
-
xsd_path, 'xsd'
|
|
557
|
-
)
|
|
558
|
-
)
|
|
559
|
-
# We need (a path to) a single xsd file.
|
|
560
|
-
if not is_single_xsd_file:
|
|
561
|
-
raise ValueError(f"Got multiple xsd files: {xsd_file_path}.")
|
|
562
|
-
# Handle incorrect file extension.
|
|
563
|
-
if xsd_file_path[0].suffix != '.xsd':
|
|
564
|
-
# Raise a load error.
|
|
565
|
-
raise SystemError(
|
|
566
|
-
f"ValueError: {xsd_file_path[0]} is not an XSD file."
|
|
567
|
-
)
|
|
568
|
-
# Try to load the provided XSD file.
|
|
569
|
-
result = self._load_schema(xsd_file_path[0], base_url )
|
|
570
|
-
if result.success:
|
|
571
|
-
# Set the loaded XSD file as default schema.
|
|
572
|
-
self.schema = result.value
|
|
573
|
-
logger.info(
|
|
574
|
-
f"Schema '{self.schema.name}' set.", # type: ignore
|
|
575
|
-
also_console=True)
|
|
576
|
-
else:
|
|
577
|
-
# Or report the load error.
|
|
578
|
-
raise SystemError(f"Loading of schema failed: {result.error}")
|
|
579
|
-
# Or inform the user on what to do.
|
|
580
|
-
else:
|
|
581
|
-
logger.info(
|
|
582
|
-
"No XSD schema set: provide schema(s) during keyword calls.",
|
|
583
|
-
also_console=True
|
|
584
|
-
)
|
|
585
|
-
# And flag the schema attr as None.
|
|
586
|
-
self.schema = None
|
|
573
|
+
self.schema = self._try_load_initial_schema(
|
|
574
|
+
xsd_path=xsd_path, base_url=base_url
|
|
575
|
+
)
|
|
587
576
|
# Set the error facets to collect for failed XML validations.
|
|
588
577
|
self.error_facets = error_facets if error_facets else [
|
|
589
578
|
'path', 'reason'
|
|
590
|
-
|
|
579
|
+
]
|
|
591
580
|
logger.info(
|
|
592
581
|
f"Collecting error facets: {self.error_facets}.",
|
|
593
582
|
also_console=True
|
|
594
|
-
|
|
583
|
+
)
|
|
584
|
+
# Set the validation strictness.
|
|
585
|
+
self.fail_on_errors = fail_on_errors
|
|
586
|
+
logger.info(
|
|
587
|
+
f"Fail on errors: {self.fail_on_errors}.", also_console=True
|
|
588
|
+
)
|
|
589
|
+
# Report readiness.
|
|
595
590
|
logger.info("XML Validator ready for use!", also_console=True)
|
|
596
591
|
self.nr_instances += 1
|
|
597
|
-
logger.info(
|
|
592
|
+
logger.info(
|
|
593
|
+
f'Number of library instances: {self.nr_instances}.'
|
|
594
|
+
)
|
|
598
595
|
|
|
599
596
|
def _determine_validations(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
597
|
+
self,
|
|
598
|
+
xml_paths: List[Path],
|
|
599
|
+
xsd_path: Optional[str|Path] = None,
|
|
600
|
+
xsd_search_strategy: Optional[
|
|
604
601
|
Literal['by_namespace', 'by_file_name']
|
|
605
602
|
] = None,
|
|
606
|
-
|
|
607
|
-
|
|
603
|
+
base_url: Optional[str] = None
|
|
604
|
+
) -> Dict[Path, Path | None]:
|
|
608
605
|
"""
|
|
609
606
|
Constructs a mapping between XML files and the XSD schemas to
|
|
610
607
|
use for their validation.
|
|
@@ -744,10 +741,10 @@ class XmlValidator:
|
|
|
744
741
|
return validations
|
|
745
742
|
|
|
746
743
|
def _ensure_schema(
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
744
|
+
self,
|
|
745
|
+
xsd_path: Optional[Path] = None,
|
|
746
|
+
base_url: Optional[str] = None
|
|
747
|
+
) -> ValidatorResult:
|
|
751
748
|
"""
|
|
752
749
|
Ensures that a schema is available for validation.
|
|
753
750
|
|
|
@@ -815,29 +812,26 @@ class XmlValidator:
|
|
|
815
812
|
"No schema: provide an XSD path during keyword call(s)."
|
|
816
813
|
)
|
|
817
814
|
if self.schema and not xsd_path :
|
|
818
|
-
logger.info(
|
|
819
|
-
|
|
820
|
-
|
|
815
|
+
# logger.info(
|
|
816
|
+
# f'No new schema set: keeping existing schema {self.schema}.'
|
|
817
|
+
# )
|
|
821
818
|
return ValidatorResult(success=True, value=self.schema)
|
|
822
819
|
if not self.schema and xsd_path:
|
|
823
820
|
logger.info(f'Setting schema file: {xsd_path}.', also_console=True)
|
|
824
821
|
if self.schema and xsd_path:
|
|
825
822
|
logger.info(
|
|
826
|
-
f'
|
|
823
|
+
f'\tUsing schema: {xsd_path}.',
|
|
827
824
|
also_console=True
|
|
828
825
|
)
|
|
829
826
|
return self._load_schema(xsd_path, base_url) # pyright: ignore
|
|
830
827
|
|
|
831
828
|
def _find_schemas(
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
] = 'by_namespace',
|
|
839
|
-
base_url: Optional[str] = None
|
|
840
|
-
) -> Dict[ Path, Path | None ]:
|
|
829
|
+
self,
|
|
830
|
+
xml_file_paths: List[Path],
|
|
831
|
+
xsd_file_paths: List[Path],
|
|
832
|
+
search_by: Literal['by_namespace', 'by_file_name'] = 'by_namespace',
|
|
833
|
+
base_url: Optional[str] = None
|
|
834
|
+
) -> Dict[ Path, Path | None ]:
|
|
841
835
|
"""
|
|
842
836
|
Finds matching XSD schemas for XML files using the specified
|
|
843
837
|
search strategy.
|
|
@@ -929,13 +923,13 @@ class XmlValidator:
|
|
|
929
923
|
# Catch and handle any exception.
|
|
930
924
|
except Exception as err: # pylint: disable=W0718:broad-exception-caught
|
|
931
925
|
# Inform the user.
|
|
932
|
-
logger.
|
|
926
|
+
logger.info('\t\tProcessing XML file failed.')
|
|
933
927
|
# Collect the error to be mapped to the xml file.
|
|
934
928
|
validations[xml_file_path] = err
|
|
935
929
|
continue
|
|
936
930
|
# Test each XSD file for a matching namespace.
|
|
937
931
|
for xsd_file_path in xsd_file_paths:
|
|
938
|
-
logger.info(f"
|
|
932
|
+
logger.info(f"\t\tTesting schema: {xsd_file_path}.")
|
|
939
933
|
# Load the schema.
|
|
940
934
|
result = self._load_schema(
|
|
941
935
|
xsd_file_path, base_url=base_url
|
|
@@ -963,7 +957,7 @@ class XmlValidator:
|
|
|
963
957
|
logger.info(f"\t\t\tTesting file name: {xsd_file_path}.")
|
|
964
958
|
# Compare the XSD/XML file names.
|
|
965
959
|
if xsd_file_path.stem == xml_file_path.stem:
|
|
966
|
-
logger.info("\t\
|
|
960
|
+
logger.info("\t\tFound match.")
|
|
967
961
|
# Assign current XSD path in case of a match & break.
|
|
968
962
|
validations[xml_file_path] = xsd_file_path
|
|
969
963
|
break
|
|
@@ -975,17 +969,17 @@ class XmlValidator:
|
|
|
975
969
|
raise ValueError(f"Unsupported search strategy: {search_by}.")
|
|
976
970
|
# If no match has been found.
|
|
977
971
|
if not validations[xml_file_path]:
|
|
978
|
-
logger.info(f"
|
|
972
|
+
logger.info(f"\t\tNo valid XSD found for {xml_file_path}.")
|
|
979
973
|
validations[xml_file_path] = FileNotFoundError(
|
|
980
974
|
f'No matching XSD found for: {xml_file_path.stem}.'
|
|
981
975
|
)
|
|
982
976
|
return validations
|
|
983
977
|
|
|
984
978
|
def _load_schema(
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
979
|
+
self,
|
|
980
|
+
xsd_path: Path,
|
|
981
|
+
base_url: Optional[str] = None
|
|
982
|
+
) -> ValidatorResult:
|
|
989
983
|
"""
|
|
990
984
|
This method is responsible for initializing a schema object,
|
|
991
985
|
using the `xmlschema` library.
|
|
@@ -1036,17 +1030,96 @@ class XmlValidator:
|
|
|
1036
1030
|
success=False, error={"XMLSchemaValidationError": e}
|
|
1037
1031
|
)
|
|
1038
1032
|
|
|
1039
|
-
def
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1033
|
+
def _try_load_initial_schema(
|
|
1034
|
+
self,
|
|
1035
|
+
xsd_path: Optional[str|Path] = None,
|
|
1036
|
+
base_url: Optional[str] = None
|
|
1037
|
+
) -> None:
|
|
1038
|
+
"""
|
|
1039
|
+
Attempts to resolve, validate, and load a single XSD schema from
|
|
1040
|
+
the provided path.
|
|
1041
|
+
|
|
1042
|
+
This method is invoked during library initialization (i.e.,
|
|
1043
|
+
within `__init__`) when an optional `xsd_path` is provided. If a
|
|
1044
|
+
path is provided, this method expects the path to resolve to
|
|
1045
|
+
exactly one valid`.xsd` file. If successful, the compiled schema
|
|
1046
|
+
is returned and stored in `self.schema`.
|
|
1047
|
+
|
|
1048
|
+
If the path points to a directory, the method searches for a
|
|
1049
|
+
single `.xsd` file inside it. If multiple matching files are
|
|
1050
|
+
found, or if the file extension is incorrect, an error is
|
|
1051
|
+
raised.
|
|
1052
|
+
|
|
1053
|
+
This method is not intended to be used interactively — it is a
|
|
1054
|
+
one-time helper to support declarative schema configuration
|
|
1055
|
+
during import of the test library.
|
|
1056
|
+
|
|
1057
|
+
Args:
|
|
1058
|
+
|
|
1059
|
+
- xsd_path (str):
|
|
1060
|
+
Path to a `.xsd` file or to a directory containing exactly one
|
|
1061
|
+
`.xsd` file.
|
|
1062
|
+
- base_url (Optional[str]):
|
|
1063
|
+
Optional base URL used when parsing the schema, typically to
|
|
1064
|
+
resolve includes.
|
|
1065
|
+
|
|
1066
|
+
Raises:
|
|
1067
|
+
|
|
1068
|
+
- ValueError:
|
|
1069
|
+
If multiple `.xsd` files are found in the provided directory.
|
|
1070
|
+
- SystemError:
|
|
1071
|
+
If the resolved file does not have a `.xsd` extension or the
|
|
1072
|
+
schema fails to load.
|
|
1073
|
+
"""
|
|
1074
|
+
if xsd_path:
|
|
1075
|
+
# Try to get a single xsd file from the provided xsd_path.
|
|
1076
|
+
xsd_file_path, is_single_xsd_file = (
|
|
1077
|
+
self.validator_utils.get_file_paths(
|
|
1078
|
+
xsd_path, 'xsd'
|
|
1079
|
+
)
|
|
1080
|
+
)
|
|
1081
|
+
# We need (a path to) a single xsd file.
|
|
1082
|
+
if not is_single_xsd_file:
|
|
1083
|
+
raise ValueError(
|
|
1084
|
+
f"Got multiple xsd files: {xsd_file_path}."
|
|
1085
|
+
)
|
|
1086
|
+
# Handle incorrect file extension.
|
|
1087
|
+
if xsd_file_path[0].suffix != '.xsd':
|
|
1088
|
+
# Raise a load error.
|
|
1089
|
+
raise SystemError(
|
|
1090
|
+
f"ValueError: {xsd_file_path[0]} is not an XSD file."
|
|
1091
|
+
)
|
|
1092
|
+
# Try to load the provided XSD file.
|
|
1093
|
+
result = self._load_schema(xsd_file_path[0], base_url )
|
|
1094
|
+
if result.success:
|
|
1095
|
+
# Set the loaded XSD file as default schema.
|
|
1096
|
+
logger.info(
|
|
1097
|
+
f"Schema '{self.schema.name}' set.", # type: ignore
|
|
1098
|
+
also_console=True)
|
|
1099
|
+
return result.value
|
|
1100
|
+
# Or report the load error.
|
|
1101
|
+
raise SystemError(
|
|
1102
|
+
f"Loading of schema failed: {result.error}"
|
|
1103
|
+
)
|
|
1104
|
+
# Or inform the user on what to do.
|
|
1105
|
+
logger.info(
|
|
1106
|
+
"No XSD schema set: provide schema(s) during keyword calls.",
|
|
1107
|
+
also_console=True
|
|
1108
|
+
)
|
|
1109
|
+
# And explicitly flag the schema attr as None.
|
|
1110
|
+
return None
|
|
1111
|
+
|
|
1112
|
+
def _validate_xml( # pylint: disable=R0913:too-many-arguments disable=R0917:too-many-positional-arguments
|
|
1113
|
+
self,
|
|
1114
|
+
xml_file_path: Path,
|
|
1115
|
+
xsd_file_path: Optional[Path] = None,
|
|
1116
|
+
base_url: Optional[str] = None,
|
|
1117
|
+
error_facets: Optional[ List[str] ] = None,
|
|
1118
|
+
pre_parse: Optional[bool] = True
|
|
1119
|
+
) -> Tuple[
|
|
1120
|
+
bool,
|
|
1121
|
+
Optional[List[dict[str, Any]]]
|
|
1122
|
+
]:
|
|
1050
1123
|
"""
|
|
1051
1124
|
Validates an XML file against the currently loaded or provided
|
|
1052
1125
|
XSD schema.
|
|
@@ -1193,7 +1266,7 @@ class XmlValidator:
|
|
|
1193
1266
|
"""
|
|
1194
1267
|
# Log informative.
|
|
1195
1268
|
logger.info(
|
|
1196
|
-
f"Validating '{xml_file_path.
|
|
1269
|
+
f"Validating '{xml_file_path.name}", also_console=True
|
|
1197
1270
|
)
|
|
1198
1271
|
# Check upstream XSD matching led to an err pertaining to the XML.
|
|
1199
1272
|
if isinstance(xsd_file_path, BaseException):
|
|
@@ -1211,7 +1284,7 @@ class XmlValidator:
|
|
|
1211
1284
|
)
|
|
1212
1285
|
if not sanity_check_result.success:
|
|
1213
1286
|
# Abort validation if one or more sanity checks failed.
|
|
1214
|
-
logger.warn("File(s) failed basic sanity check.")
|
|
1287
|
+
# logger.warn("File(s) failed basic sanity check.")
|
|
1215
1288
|
return False, sanity_check_result.error
|
|
1216
1289
|
# Ensure a valid schema is loaded.
|
|
1217
1290
|
loading_result = self._ensure_schema(
|
|
@@ -1259,9 +1332,7 @@ class XmlValidator:
|
|
|
1259
1332
|
return self.error_facets
|
|
1260
1333
|
|
|
1261
1334
|
@keyword
|
|
1262
|
-
def get_schema(
|
|
1263
|
-
self,
|
|
1264
|
-
return_schema_name: bool = True
|
|
1335
|
+
def get_schema(self,return_schema_name: bool = True
|
|
1265
1336
|
) -> Optional[str|XMLSchema]:
|
|
1266
1337
|
"""
|
|
1267
1338
|
.. raw:: html
|
|
@@ -1389,7 +1460,7 @@ class XmlValidator:
|
|
|
1389
1460
|
write_to_csv: Optional[bool] = True,
|
|
1390
1461
|
timestamped: Optional[bool] = True,
|
|
1391
1462
|
reset_errors: bool = True,
|
|
1392
|
-
fail_on_errors: Optional[bool] =
|
|
1463
|
+
fail_on_errors: Optional[bool] = None
|
|
1393
1464
|
) -> Tuple[
|
|
1394
1465
|
List[ Dict[str, Any] ],
|
|
1395
1466
|
str | None
|
|
@@ -1552,6 +1623,12 @@ class XmlValidator:
|
|
|
1552
1623
|
# Reset attributes, if requested.
|
|
1553
1624
|
if reset_errors:
|
|
1554
1625
|
self.validator_results.reset()
|
|
1626
|
+
# Determine the validation strictness.
|
|
1627
|
+
fail_on_errors = (
|
|
1628
|
+
fail_on_errors \
|
|
1629
|
+
if fail_on_errors is not None \
|
|
1630
|
+
else self.fail_on_errors
|
|
1631
|
+
)
|
|
1555
1632
|
# Determine and resolve/normalize the XML file path(s).
|
|
1556
1633
|
xml_file_paths, is_single_xml_file = (
|
|
1557
1634
|
self.validator_utils.get_file_paths(
|
xmlvalidator/__init__.py
CHANGED
|
@@ -55,6 +55,6 @@ try:
|
|
|
55
55
|
__version__ = version("robotframework-xmlvalidator")
|
|
56
56
|
except PackageNotFoundError:
|
|
57
57
|
# Fall back when package not installed (default version for development).
|
|
58
|
-
__version__ = "0.0
|
|
58
|
+
__version__ = "2.0.0"
|
|
59
59
|
import warnings
|
|
60
60
|
warnings.warn("Package metadata not found, using fallback version.")
|
|
@@ -75,7 +75,7 @@ class ValidatorResultRecorder:
|
|
|
75
75
|
and export validation results.
|
|
76
76
|
"""
|
|
77
77
|
|
|
78
|
-
__version__ = '
|
|
78
|
+
__version__ = '2.0.0'
|
|
79
79
|
|
|
80
80
|
errors_by_file: List[Dict[str, Any]] = field(default_factory=list)
|
|
81
81
|
validation_summary: Dict[str, List[str]] = field(
|
|
@@ -331,7 +331,7 @@ class ValidatorResultRecorder:
|
|
|
331
331
|
try:
|
|
332
332
|
df.to_csv(output_csv_path, index=False)
|
|
333
333
|
logger.info(
|
|
334
|
-
f"Validation errors exported to '{output_csv_path}'.",
|
|
334
|
+
f"Validation errors exported to: \n\t'{output_csv_path}'.",
|
|
335
335
|
also_console=True
|
|
336
336
|
)
|
|
337
337
|
except IOError as e:
|
|
@@ -364,7 +364,7 @@ class ValidatorResult: # pylint: disable=R0903:too-few-public-methods
|
|
|
364
364
|
Error information if the operation failed.
|
|
365
365
|
"""
|
|
366
366
|
|
|
367
|
-
__version__ = '
|
|
367
|
+
__version__ = '1.0.1'
|
|
368
368
|
|
|
369
369
|
def __init__(
|
|
370
370
|
self,
|
|
@@ -43,7 +43,6 @@ from pathlib import Path
|
|
|
43
43
|
from typing import List, Optional, Tuple, Union, TYPE_CHECKING
|
|
44
44
|
# Third party library imports.
|
|
45
45
|
from lxml import etree
|
|
46
|
-
from robot.api import logger
|
|
47
46
|
# Local application imports.
|
|
48
47
|
from .xml_validator_results import ValidatorResult
|
|
49
48
|
if TYPE_CHECKING:
|
|
@@ -67,7 +66,7 @@ class ValidatorUtils:
|
|
|
67
66
|
All methods are static and the class maintains no internal state.
|
|
68
67
|
"""
|
|
69
68
|
|
|
70
|
-
__version__ = '
|
|
69
|
+
__version__ = '2.0.0'
|
|
71
70
|
|
|
72
71
|
@staticmethod
|
|
73
72
|
def _resolve_path(path: str | Path) -> Path:
|
|
@@ -472,9 +471,9 @@ class ValidatorUtils:
|
|
|
472
471
|
if isinstance(value, tuple):
|
|
473
472
|
value = f"Line {value[0]}, Column {value[1]}."
|
|
474
473
|
error_details[facet] = value
|
|
475
|
-
logger.warn(
|
|
476
|
-
|
|
477
|
-
|
|
474
|
+
# logger.warn(
|
|
475
|
+
# f"Facet '{facet}' is not an attribute of error type'{type(e).__name__}'."
|
|
476
|
+
# )
|
|
478
477
|
# Add the error type to the error details
|
|
479
478
|
error_details['Error type'] = type(e).__name__
|
|
480
479
|
# Append the error to the return list.
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
xmlvalidator/__init__.py,sha256=5kxSsQ1XkpyeYSdcZvZlnSpnbRPiyd1w3hb8l-G0BtQ,2293
|
|
2
|
-
xmlvalidator/xml_validator_results.py,sha256=r2QvkNoFRkEYcS_J8yMDjX4pwqyYJAFmSvbMkqEnLkY,13119
|
|
3
|
-
xmlvalidator/xml_validator_utils.py,sha256=jjZ7hwSmEpNQTP_fxECqIMriyvr5xr0RWibakpnEPmo,17830
|
|
4
|
-
xmlvalidator/XmlValidator.py,sha256=9kAzacpQixC5hIs_LZIl5oSr96Ze4pVwh_m4bMJUMVs,71829
|
|
5
|
-
robotframework_xmlvalidator-1.0.0.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
6
|
-
robotframework_xmlvalidator-1.0.0.dist-info/METADATA,sha256=xWZDdS0cmZSf-ZFTWaRdhsxsmffxCiq3db_W6rrY0XM,30798
|
|
7
|
-
robotframework_xmlvalidator-1.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
8
|
-
robotframework_xmlvalidator-1.0.0.dist-info/RECORD,,
|
{robotframework_xmlvalidator-1.0.0.dist-info → robotframework_xmlvalidator-2.0.0.dist-info}/LICENSE
RENAMED
|
File without changes
|
{robotframework_xmlvalidator-1.0.0.dist-info → robotframework_xmlvalidator-2.0.0.dist-info}/WHEEL
RENAMED
|
File without changes
|