robotframework-xmlvalidator 1.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.
@@ -0,0 +1,686 @@
1
+ Metadata-Version: 2.3
2
+ Name: robotframework-xmlvalidator
3
+ Version: 1.0.0
4
+ Summary: A Robot Framework test library for validating XML files against XSD schemas
5
+ License: Apache-2.0
6
+ Keywords: robotframework,xml,xsd,validation,test-library,test,testing,test-automation
7
+ Author: Michael Hallik
8
+ Author-email: hallik.michael@gmail.com
9
+ Requires-Python: >=3.10
10
+ Classifier: Framework :: Robot Framework
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Topic :: Software Development :: Testing
19
+ Requires-Dist: lxml (>=5.1.0,<6.0.0)
20
+ Requires-Dist: pandas (>=2.2.0,<3.0.0)
21
+ Requires-Dist: robotframework (>=7.0.0,<8.0.0)
22
+ Requires-Dist: xmlschema (>=3.4.3,<4.0.0)
23
+ Project-URL: Documentation, https://github.com/MichaelHallik/robotframework-xmlvalidator#readme
24
+ Project-URL: Homepage, https://github.com/MichaelHallik/robotframework-xmlvalidator
25
+ Project-URL: Repository, https://github.com/MichaelHallik/robotframework-xmlvalidator
26
+ Description-Content-Type: text/markdown
27
+
28
+ [![PyPI version](https://img.shields.io/pypi/v/robotframework-xmlvalidator.svg)](https://pypi.org/project/robotframework-xmlvalidator/)
29
+ [![License](https://img.shields.io/pypi/l/robotframework-xmlvalidator)](LICENSE)
30
+ [![Tests](https://github.com/MichaelHallik/robotframework-xmlvalidator/actions/workflows/test.yml/badge.svg)](https://github.com/MichaelHallik/robotframework-xmlvalidator/actions/workflows/test.yml)
31
+
32
+ <details>
33
+ <summary><strong>📚 Table of Contents</strong></summary>
34
+
35
+ - [robotframework-xmlvalidator](#robotframework-xmlvalidator)
36
+ - [Introduction](#introduction)
37
+ - [Features](#features)
38
+ - [Installing the library](#installing-the-library)
39
+ - [Install from PyPI](#install-from-pypi)
40
+ - [Install from GitHub](#install-from-github)
41
+ - [Install using poetry](#install-using-poetry)
42
+ - [Dependencies](#dependencies)
43
+ - [Importing the library](#importing-the-library)
44
+ - [Library scope](#library-scope)
45
+ - [Library arguments](#library-arguments)
46
+ - [Examples](#examples)
47
+ - [Using a preloaded schema](#using-a-preloaded-schema)
48
+ - [Defer schema loading to the test case(s)](#defer-schema-loading-to-the-test-cases)
49
+ - [Importing with preloaded XSD that requires a base\_url](#importing-with-preloaded-xsd-that-requires-a-base_url)
50
+ - [Importing with custom error\_facets](#importing-with-custom-error_facets)
51
+ - [Further examples](#further-examples)
52
+ - [Using the library](#using-the-library)
53
+ - [Keyword overview](#keyword-overview)
54
+ - [Keyword documentation](#keyword-documentation)
55
+ - [Keyword example usage](#keyword-example-usage)
56
+ - [A few basic examples](#a-few-basic-examples)
57
+ - [Integration tests as examples](#integration-tests-as-examples)
58
+ - [Example console output](#example-console-output)
59
+ - [Example CSV output](#example-csv-output)
60
+ - [Utilizing error facets](#utilizing-error-facets)
61
+ - [Useful docs](#useful-docs)
62
+ - [Contributing](#contributing)
63
+ - [Introduction](#introduction-1)
64
+ - [Environment setup](#environment-setup)
65
+ - [Clone the repo and navigate into it:](#clone-the-repo-and-navigate-into-it)
66
+ - [Install using Poetry:](#install-using-poetry-1)
67
+ - [Activate the virtual environment:](#activate-the-virtual-environment)
68
+ - [Running tests](#running-tests)
69
+ - [Unit tests (pytest)](#unit-tests-pytest)
70
+ - [Integration tests (Robot Framework)](#integration-tests-robot-framework)
71
+ - [Code quality checks](#code-quality-checks)
72
+ - [Linting](#linting)
73
+ - [Typing](#typing)
74
+ - [Running all tests and checks](#running-all-tests-and-checks)
75
+ - [Continuous Integration \& GitHub templates](#continuous-integration--github-templates)
76
+ - [Class architecture (Simplified)](#class-architecture-simplified)
77
+ - [Project Structure](#project-structure)
78
+ - [License](#license)
79
+ - [Author](#author)
80
+
81
+ </details>
82
+
83
+ # robotframework-xmlvalidator
84
+
85
+ ## Introduction
86
+
87
+ A [Robot Framework](https://robotframework.org/) test library for validating XML files against XSD schemas.
88
+
89
+ This library leverages the power of the [`xmlschema`](https://pypi.org/project/xmlschema/) library and is designed for both single-file and batch XML validation workflows.
90
+
91
+ It provides structured and detailed reporting of XML parse errors (malformed XML content) and XSD violations, schema auto-detection and CSV exports of collected errors.
92
+
93
+ ---
94
+
95
+ ## Features
96
+
97
+ - Validate one or more XML files against one or more XSD schemas.
98
+ - Dynamic schema resolution (matching strategies: `by_namespace`, `by_file_name`).
99
+ - Customizable error attributes (`path`, `reason`, `message`, etc.)
100
+ - Batch validation and per-file error tracking
101
+ - Export collected errors to CSV (with optional file name timestamping).
102
+ - And more (see below and the keyword documentation).
103
+
104
+ ---
105
+
106
+ ## Installing the library
107
+
108
+ Requires Python 3.10+.
109
+
110
+ ### Install from PyPI
111
+
112
+ ```bash
113
+ pip install robotframework-xmlvalidator
114
+ ```
115
+
116
+ ### Install from GitHub
117
+
118
+ ```bash
119
+ pip install git+https://github.com/MichaelHallik/robotframework-xmlvalidator.git
120
+ ```
121
+
122
+ ### Install using poetry
123
+
124
+ If you use [poetry](https://python-poetry.org/), you can also clone and then run:
125
+
126
+ ```bash
127
+ poetry install --without dev
128
+ ```
129
+
130
+ ### Dependencies
131
+
132
+ See [requirements.txt](requirements.txt) for runtime dependencies.
133
+
134
+ See [requirements-dev.txt](requirements-dev.txt) for development dependencies.
135
+
136
+ See [pyproject.toml](pyproject.toml) for full dependency declarations and build configuration.
137
+
138
+ ---
139
+
140
+ ## Importing the library
141
+
142
+ ### Library scope
143
+
144
+ The XmlValidator library has `GLOBAL` scope
145
+
146
+ See the [Robot Framework Library Scope docs](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#library-scope) for more details.
147
+
148
+ ### Library arguments
149
+
150
+ | Argument | Type | Required? | Description |
151
+ |----------------|-------------|-----------|------------------------------------------------------------------------------------|
152
+ | `xsd_path` | `str` | No | Path to an XSD file or folder to preload during initialization. In case of a folder, the folder must hold one file only. |
153
+ | `base_url` | `str` | No | Base path used to resolve includes/imports within the provided XSD schema. |
154
+ | `error_facets` | `list[str]` | No | The attributes of validation errors to collect and report (e.g., `path`, `reason`) |
155
+
156
+ ### Examples
157
+
158
+ #### Using a preloaded schema
159
+
160
+ ```robotframework
161
+ *** Settings ***
162
+ Library xmlvalidator xsd_path=path/to/schema.xsd
163
+ ```
164
+
165
+ #### Defer schema loading to the test case(s)
166
+
167
+ ```robotframework
168
+ Library xmlvalidator
169
+ ```
170
+
171
+ #### Importing with preloaded XSD that requires a base_url
172
+
173
+ ```robotframework
174
+ Library xmlvalidator xsd_path=path/to/schema_with_include.xsd
175
+ ... base_url=path/to/include_schemas
176
+ ```
177
+
178
+ Use `base_url` when your XSD uses `<xs:include>` or `<xs:import>` with relative paths.
179
+
180
+ #### Importing with custom error_facets
181
+
182
+ Use the `error_facets` argument to control which attributes of detected errors will be collected and reported.
183
+
184
+ E.g. the element locator (XPath), error message, involved namespace and/or the XSD validator that failed.
185
+
186
+ Error facets can also be set on the test case level, when calling the relevant keyword.
187
+
188
+ ```robotframework
189
+ Library xmlvalidator error_facets=path, message, validator
190
+ ```
191
+
192
+ You can also combine this with a preloaded schema and/or a base_url:
193
+
194
+ ```robotframework
195
+ Library xmlvalidator xsd_path=schemas/schema.xsd
196
+ ... error_facets=value, namespaces
197
+ ```
198
+
199
+ #### Further examples
200
+
201
+ See also the [library initialization Robot test file](test/integration/01_library_initialization.robot).
202
+
203
+ ---
204
+
205
+ ## Using the library
206
+
207
+ ### Keyword overview
208
+
209
+ | Keyword | Description |
210
+ |--------------------------|-------------|
211
+ | `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`) |
218
+
219
+ The main keyword is `Validate Xml Files`. The other keywords are convenience/helper functions, e.g. 'Reset Error Facets'.
220
+
221
+ 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
+
223
+ The type of error that the keyword can detect is not limited to XSD violations, but may also pertain to malformed XML files (e.g. parse errors), empty files, unmatched XML files (no XSD match found), etc.
224
+
225
+ 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
+
227
+ When operating in batch mode, the `Validate Xml Files` keyword always validates the entire set of passed XML files.
228
+
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).
230
+
231
+ In that fashion the keyword works through the entire set of files.
232
+
233
+ When having finished checking the last file, 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
+
235
+ However, in case you want your test case to fail when one or more errors have been detected, you can use the ``fail_on_errors`` (bool) argument to make it so. It defaults to False. When setting it to True, then the keyword will still check each XML file (and collect possible errors), but after it has thus processed the batch, it will fail if one or more errors will have been detected.
236
+
237
+ 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).
238
+
239
+ 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
+
241
+ See for more details the keyword documentation.
242
+
243
+ ### Keyword documentation
244
+
245
+ See [keyword documention](docs/XmlValidator.html).
246
+
247
+ 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
+
249
+ ### Keyword example usage
250
+
251
+ #### A few basic examples
252
+
253
+ ```robotframework
254
+ *** Settings ***
255
+ Library XmlValidator xsd_path=path/to/default/schema.xsd
256
+
257
+ *** Variables ***
258
+ ${SINGLE_XML_FILE} path/to/file1.xml
259
+ ${FOLDER_MULTIPLE_XML} path/to/xml_folder_1
260
+ ${FOLDER_MULTIPLE_XML_ALT} path/to/xml_folder_2
261
+ ${FOLDER_MULTIPLE_XML_NS} path/to/xml_folder_3
262
+ ${FOLDER_MULTIPLE_XML_XSD_FN} path/to/xml_folder_4
263
+ ${SINGLE_XSD_FILE} path/to/alt_schema.xsd
264
+ ${FOLDER_MULTIPLE_XSD} path/to/xsd_schemas/
265
+
266
+ *** Test Cases ***
267
+
268
+ Validate Single XML File With Default Schema
269
+ [Documentation] Validates a single XML file using the default schema
270
+ Validate Xml Files ${SINGLE_XML_FILE}
271
+
272
+ Validate Folder Of XML Files With Default Schema
273
+ [Documentation] Validates all XML files in a folder using the default schema
274
+ Validate Xml Files ${FOLDER_MULTIPLE_XML}
275
+
276
+ Validate Folder With Explicit Schema Override
277
+ [Documentation] Validates XML files using a different, explicitly provided schema
278
+ Validate Xml Files ${FOLDER_MULTIPLE_XML_ALT} ${SINGLE_XSD_FILE}
279
+
280
+ Validate Folder With Multiple Schemas By Namespace
281
+ [Documentation] Resolves matching schema for each XML file based on namespace
282
+ Validate Xml Files ${FOLDER_MULTIPLE_XML_NS}
283
+ ... ${FOLDER_MULTIPLE_XSD} xsd_search_strategy=by_namespace
284
+
285
+ Validate Folder With Multiple Schemas By File Name
286
+ [Documentation] Resolves schema based on matching file name patterns (no schema path passed)
287
+ Validate Xml Files ${FOLDER_MULTIPLE_XML_XSD_FN} xsd_search_strategy=by_file_name
288
+ ```
289
+
290
+ #### Integration tests as examples
291
+
292
+ Note that the [integration test](test/integration) folder contains seven Robot Framework test suite files.
293
+
294
+ Since the integration tests have all been implemented as Robot Framework test cases, they may also serve to illustrate the usage of the library and the keywords.
295
+
296
+ Integration tests documentation:
297
+
298
+ - [Overview of all test cases](test/_doc/integration/overview.html)
299
+ - [Instructions on how to execute the tests locally](test/_doc/integration/README.md)
300
+
301
+ The test suite files focus on various topics:
302
+
303
+ - [helper keywords test file](test/integration/00_helper_keywords.robot)
304
+ - [library initialization test file](test/integration/01_library_initialization.robot)
305
+ - [basic validations test file](test/integration/02_basic_validation.robot)
306
+ - [error handling test file](test/integration/03_error_handling.robot)
307
+ - [schema resolution test file](test/integration/04_schema_resolution.robot)
308
+ - [first advanced validations test file](test/integration/05_advanced_validation_1.robot)
309
+ - [second advanced validations test file](test/integration/06_advanced_validation_2.robot)
310
+
311
+ ### Example console output
312
+
313
+ ```text
314
+ Schema 'schema.xsd' set.
315
+ Collecting error facets: ['path', 'reason'].
316
+ XML Validator ready for use!
317
+ ==============================================================================
318
+ 01 Advanced Validation:: Demo XML validation
319
+ Mapping XML files to schemata by namespace.
320
+ Validating 'valid_1.xml'.
321
+ XML is valid!
322
+ Validating 'valid_2.xml'.
323
+ XML is valid!
324
+ Validating 'valid_3.xml'.
325
+ XML is valid!
326
+ Validating 'xsd_violations_1.xml'.
327
+ Setting new schema file: C:\Projects\robotframework-xmlvalidator\test\_data\integration\TC_01\schema1.xsd.
328
+ [ WARN ] XML is invalid:
329
+ [ WARN ] Error #0:
330
+ [ WARN ] path: /Employee
331
+ [ WARN ] reason: Unexpected child with tag '{http://example.com/schema1}FullName' at position 2. Tag '{http://example.com/schema1}Name' expected.
332
+ [ WARN ] Error #1:
333
+ [ WARN ] path: /Employee/Age
334
+ [ WARN ] reason: invalid literal for int() with base 10: 'Twenty Five'
335
+ [ WARN ] Error #2:
336
+ [ WARN ] path: /Employee/ID
337
+ [ WARN ] reason: invalid literal for int() with base 10: 'ABC'
338
+ Validating 'valid_.xml_4'.
339
+ XML is valid!
340
+ Validating 'valid_.xml_5'.
341
+ XML is valid!
342
+ Validating 'malformed_xml_1.xml'.
343
+ [ WARN ] XML is invalid:
344
+ [ WARN ] Error #0:
345
+ [ WARN ] reason: Premature end of data in tag Name line 1, line 1, column 37 (file:/C:/Projects/robotframework-xmlvalidator/test/_data/integration/TC_01/malformed_xml_1.xml, line 1)
346
+ [ WARN ] Error #1:
347
+ [ WARN ] reason: Opening and ending tag mismatch: ProductID line 1 and Product, line 1, column 31 (file:/C:/Projects/robotframework-xmlvalidator/test/_data/integration/TC_01/malformed_xml_1.xml, line 1)
348
+ Validating 'xsd_violations_2.xml'.
349
+ Setting new schema file: C:\Projects\robotframework-xmlvalidator\test\_data\integration\TC_01\schema2.xsd.
350
+ [ WARN ] XML is invalid:
351
+ [ WARN ] Error #0:
352
+ [ WARN ] path: /Product/Price
353
+ [ WARN ] reason: invalid value '99.99USD' for xs:decimal
354
+ [ WARN ] Error #1:
355
+ [ WARN ] path: /Product
356
+ [ WARN ] reason: The content of element '{http://example.com/schema2}Product' is not complete. Tag '{http://example.com/schema2}Price' expected.
357
+ Validating 'valid_.xml_6'.
358
+ XML is valid!
359
+ Validating 'no_xsd_match_1.xml'.
360
+ [ WARN ] XML is invalid:
361
+ [ WARN ] Error #0:
362
+ [ WARN ] reason: No matching XSD found for: no_xsd_match_1.xml.
363
+ Validating 'no_xsd_match_2.xml'.
364
+ [ WARN ] XML is invalid:
365
+ [ WARN ] Error #0:
366
+ [ WARN ] reason: No matching XSD found for: no_xsd_match_2.xml.
367
+ Validation errors exported to 'C:\test\01_Advanced_Validation\errors_2025-03-29_13-54-46-552150.csv'.
368
+ Total_files validated: 11.
369
+ Valid files: 6.
370
+ Invalid files: 5
371
+ ```
372
+
373
+ ### Example CSV output
374
+
375
+ ```text
376
+ file_name,path,reason
377
+ xsd_violations_1.xml,/Employee/ID,invalid literal for int() with base 10: 'ABC'
378
+ xsd_violations_1.xml,/Employee/Age,invalid literal for int() with base 10: 'Twenty Five'
379
+ xsd_violations_1.xml,/Employee,Unexpected child with tag '{http://example.com/schema1}FullName' at position 2. Tag '{http://example.com/schema1}Name' expected.
380
+ malformed_xml_1.xml,,"Premature end of data in tag Name line 1, line 1, column 37 (file:/C:/Projects/robotframework-xmlvalidator/test/_data/integration/TC_01/schema1_malformed_2.xml, line 1)"
381
+ malformed_xml_1.xml,,"Opening and ending tag mismatch: ProductID line 1 and Product, line 1, column 31 (file:/C:/Projects/robotframework-xmlvalidator/test/_data/integration/TC_01/schema2_malformed_3.xml, line 1)"
382
+ schema2_invalid_1.xml,/Product/Price,invalid value '99.99USD' for xs:decimal
383
+ schema2_invalid_2.xml,/Product,The content of element '{http://example.com/schema2}Product' is not complete. Tag '{http://example.com/schema2}Price' expected.
384
+ no_xsd_match_1.xml,,No matching XSD found for: no_xsd_match_1.xml.
385
+ no_xsd_match_2.xml,,No matching XSD found for: no_xsd_match_2.xml.
386
+ ```
387
+
388
+ ### Utilizing error facets
389
+
390
+ These are the facets (or attributes) that can be collected and reported for each encountered error:
391
+
392
+ | Facet | Description |
393
+ |---------------|-----------------------------------------------------------------------------|
394
+ | `message` | A human-readable message describing the validation error. |
395
+ | `path` | The XPath location of the error in the XML document. |
396
+ | `domain` | The domain of the error (e.g., `"validation"`). |
397
+ | `reason` | The reason for the error, often linked to XSD constraint violations. |
398
+ | `validator` | The XSD component (e.g., element, attribute, type) that failed validation. |
399
+ | `schema_path` | The XPath location of the error in the XSD schema. |
400
+ | `namespaces` | The namespaces involved in the error (if applicable). |
401
+ | `elem` | The XML element that caused the error (`ElementTree.Element`). |
402
+ | `value` | The invalid value that triggered the error. |
403
+ | `severity` | The severity level of the error (not always present). |
404
+ | `args` | The arguments passed to the error message formatting.
405
+
406
+ Use the `error_facets` arg to set which error details to collect.
407
+
408
+ For each error that is encountered, the selected error facet(s) will be collected and reported.
409
+
410
+ You can customize which error facet(s) should be collected, by passing a list of one or more error facets:
411
+ - when importing the library
412
+ - when calling the `Validate Xml Files` keyword
413
+
414
+ 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
+
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 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
+
418
+ The table lists the most commonly available attributes, though additional fields may be available depending on the type of validation error.
419
+
420
+ ---
421
+
422
+ ## Useful docs
423
+
424
+ | Document Link | Audience | Topics |
425
+ |---------------|----------|--------|
426
+ | [Keyword doc](docs/XmlValidator.html) | User | Keyword reference |
427
+ | [CHANGELOG](CHANGELOG.md) | User / Dev | Version history, features |
428
+ | [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) | Dev | Community guidelines |
429
+ | [CONTRIBUTING](CONTRIBUTING.md) | Dev | Contribute |
430
+ | [Mermaid diagram of GitHub Actions](github_actions.md) | Dev | CI, GitHub Actions |
431
+ | [License](LICENSE) | All | Legal usage terms |
432
+ | [Make file](Makefile) | Dev | Automation, commands |
433
+ | [Project Structure](project_structure.txt) | Dev | Project layout |
434
+ | [Dependencies - pyproject.toml](pyproject.toml) | Dev | Build config, dependencies |
435
+ | [pyright configuration](pyrightconfig.json) | Dev | Static typing |
436
+ | [requirements.txt](requirements.txt) | User / Dev | Runtime dependencies |
437
+ | [requirements-dev.txt](requirements-dev.txt) | Dev | Dev/test tooling |
438
+ | [How to - Running the integration tests](test/_doc/integration/README.md) | User / Dev | Testing (integration) |
439
+ | [Overview of all integration tests](test/_doc/integration/overview.html) | User / Dev | Test documentation |
440
+ | [How to - Running the unit tests](test/_doc/unit/README.md) | Dev | Testing (unit) |
441
+ | [Overview of all unit tests](test/_doc/integration/overview.html) | Dev | Test documentation |
442
+
443
+ ---
444
+
445
+ ## Contributing
446
+
447
+ ### Introduction
448
+
449
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
450
+
451
+ The overall process:
452
+
453
+ ![Contributing to the project](./docs/images/contributing.JPG)
454
+
455
+ This project uses Poetry for dependency and packaging management.
456
+
457
+ ### Environment setup
458
+
459
+ #### Clone the repo and navigate into it:
460
+
461
+ ```
462
+ git clone https://github.com/MichaelHallik/robotframework-xmlvalidator.git
463
+ cd robotframework-xmlvalidator
464
+ ```
465
+
466
+ #### Install using Poetry:
467
+
468
+ ```
469
+ poetry install
470
+ ```
471
+
472
+ #### Activate the virtual environment:
473
+
474
+ ```
475
+ poetry shell
476
+ ```
477
+
478
+ Or, if you use a different virt env, activate that.
479
+
480
+ ### Running tests
481
+
482
+ Use standard Python commands, poetry or the provided [Make file](Makefile).
483
+
484
+ #### Unit tests (pytest)
485
+
486
+ ```
487
+ pytest test/unit/
488
+ poetry run pytest test/unit/
489
+ make test
490
+ ```
491
+
492
+ #### Integration tests (Robot Framework)
493
+
494
+ ```
495
+ robot -d ./Results test/integration
496
+ poetry run robot -d ./Results test/integration
497
+ make robot
498
+ ```
499
+
500
+ ### Code quality checks
501
+
502
+ Use standard Python commands, poetry or the provided [Make file](Makefile).
503
+
504
+ #### Linting
505
+
506
+ ```
507
+ pylint src/ --exit-zero
508
+ poetry run pylint src/ --exit-zero
509
+ make lint
510
+ ```
511
+
512
+ #### Typing
513
+
514
+ ```
515
+ pyright --project pyrightconfig.json || exit 0
516
+ poetry run pyright --project pyrightconfig.json || exit 0
517
+ make type
518
+ ```
519
+
520
+ ### Running all tests and checks
521
+
522
+ Use the provided [Make file](Makefile).
523
+ ```
524
+ make check
525
+ ```
526
+
527
+ ### Continuous Integration & GitHub templates
528
+
529
+ This project uses **GitHub Actions** for automated testing and linting.
530
+
531
+ GitHub Actions CI is defined under [github/workflows/](.github/workflows/), in particular:
532
+
533
+ - [test.yml](.github/workflows/test.yml): Runs unit and integration tests.
534
+ - [lint.yml](.github/workflows/lint.yml): Enforces coding standards using linting tools (pylint, pyright, black).
535
+
536
+ The test workflow:
537
+
538
+ ![Test workflow diagram](./docs/images/test_workflow.JPG)
539
+
540
+ In [.github/](.github/) you’ll also find the various contribution templates:
541
+
542
+ - [Bug reports](.github/ISSUE_TEMPLATE/bug_report.md)
543
+ - [Feature requests](.github/ISSUE_TEMPLATE/feature_request.md)
544
+ - [Pull request instructions](.github/PULL_REQUEST_TEMPLATE.md)
545
+
546
+ ---
547
+
548
+ ## Class architecture (Simplified)
549
+
550
+ ```mermaid
551
+ classDiagram
552
+ class XmlValidator {
553
+ +__init__(xsd_path: Optional[str|Path]=None, base_url: Optional[str]=None, error_facets: Optional[List[str]]=None)
554
+ +get_error_facets() List[str]
555
+ +get_schema(return_name: bool=True) Optional[str|XMLSchema]
556
+ +log_schema(log_name: bool=True)
557
+ +reset_error_facets()
558
+ +reset_errors()
559
+ +reset_schema()
560
+ +validate_xml_files(xml_path: str|Path, xsd_path: Optional[str|Path]=None, xsd_search_strategy: Optional[Literal['by_namespace', 'by_file_name']]=None, base_url: Optional[str]=None, error_facets: Optional[List[str]]=None, pre_parse: Optional[bool]=True, write_to_csv: Optional[bool]=True, timestamped: Optional[bool]=True, reset_errors: bool=True) Tuple[List[Dict[str, Any]], str | None]
561
+ -_determine_validations(xml_paths: List[Path], xsd_path: Optional[str | Path]=None, xsd_search_strategy: Optional[Literal['by_namespace', 'by_file_name']]=None, base_url: Optional[str]=None) Dict[Path, Path | None]
562
+ -_ensure_schema(xsd_path: Optional[Path]=None, base_url: Optional[str]=None) ValidatorResult
563
+ -_find_schemas(xml_file_paths: List[Path], xsd_file_paths: List[Path], search_by: Literal['by_namespace', 'by_file_name']='by_namespace', base_url: Optional[str]=None) Dict[Path, Path | None]
564
+ -_load_schema(xsd_path: Path, base_url: Optional[str]=None) ValidatorResult
565
+ -_validate_xml(xml_file_path: Path, xsd_file_path: Optional[Path]=None, base_url: Optional[str]=None, error_facets: Optional[List[str]]=None, pre_parse: Optional[bool]=True) Tuple[bool, Optional[List[Dict[str, Any]]]]
566
+ }
567
+
568
+ class ValidatorResultRecorder {
569
+ +__init__()
570
+ +add_file_errors(file_path: Path, error_details: List[Dict[str, Any]] | Dict[str, Any] | None)
571
+ +add_invalid_file(file_path: Path)
572
+ +add_valid_file(file_path: Path)
573
+ +log_file_errors(errors: List[Dict[str, Any]])
574
+ +log_summary()
575
+ +reset()
576
+ +write_errors_to_csv(errors: List[Dict[str, Any]], output_path: Path, include_timestamp: bool=False, file_name_column: str=None) str
577
+ }
578
+
579
+ class ValidatorResult {
580
+ +__init__(success: bool, value: Optional[Any]=None, error: Optional[Any]=None)
581
+ +__repr__() str
582
+ }
583
+
584
+ class ValidatorUtils {
585
+ +extract_xml_namespaces(xml_root: etree.ElementBase, return_dict: Optional[bool]=False, include_nested: Optional[bool]=False) Union[set[str], dict[str | None, str]]
586
+ +get_file_paths(file_path: str | Path, file_type: str) Tuple[List[Path], bool]
587
+ +match_namespace_to_schema(xsd_schema: XMLSchema, xml_namespaces: set[str]) bool
588
+ +sanity_check_files(file_paths: List[Path], base_url: Optional[str]=None, error_facets: Optional[List[str]]=None, parse_files: Optional[bool]=False) ValidatorResult
589
+ }
590
+
591
+ XmlValidator --> ValidatorResult
592
+ XmlValidator --> ValidatorResultRecorder
593
+ XmlValidator --> ValidatorUtils
594
+ ```
595
+
596
+ ---
597
+
598
+ ---
599
+
600
+ ## Project Structure
601
+
602
+ ```
603
+ .github/ # GitHub config and workflow automation
604
+ ├── ISSUE_TEMPLATE/
605
+ │ ├── bug_report.md
606
+ │ └── feature_request.md
607
+ ├── workflows/
608
+ │ ├── lint.yml
609
+ │ └── test.yml
610
+ └── PULL_REQUEST_TEMPLATE.md
611
+ docs/ # Robot Framework keyword documentation
612
+ ├── XmlValidator.html
613
+ src/ # Source code root
614
+ └── xmlvalidator/
615
+ ├── __init__.py
616
+ ├── XmlValidator.py # Main Robot Framework library
617
+ ├── xml_validator_results.py
618
+ └── xml_validator_utils.py
619
+
620
+ test/ # Tests and supporting files
621
+ ├── _data/ # Test data: schemas and XMLs
622
+ │ ├── integration/
623
+ │ │ ├── TC_02/
624
+ │ │ │ └── 02_test_schema.xsd
625
+ │ │ ├── TC_03/
626
+ │ │ │ ├── 03_included_schema.xsd
627
+ │ │ │ └── 03_test_schema_with_include.xsd
628
+ │ │ └── ...
629
+ │ │ └── TC_32/
630
+ │ │ ├── complex_schema.xsd
631
+ │ │ ├── invalid.xml
632
+ │ │ └── valid.xml
633
+ │ └── unit/
634
+ │ ├── test.xml
635
+ │ └── test.xsd
636
+ ├── _doc/ # Documentation for tests
637
+ │ ├── integration/
638
+ │ │ ├── overview.html
639
+ │ │ └── README.md
640
+ │ └── unit/
641
+ │ ├── overview.html
642
+ │ └── README.md
643
+ ├── integration/ # Robot Framework integration tests
644
+ │ ├── 00_helper_keywords.robot
645
+ │ ├── 01_library_initialization.robot
646
+ │ ├── 02_basic_validation.robot
647
+ │ ├── 03_error_handling.robot
648
+ │ ├── 04_schema_resolution.robot
649
+ │ ├── 05_advanced_validation_1.robot
650
+ │ ├── 06_advanced_validation_2.robot
651
+ │ ├── validation_keywords.py
652
+ │ └── validation_keywords.resource
653
+ ├── unit/ # Unit tests (pytest)
654
+ │ ├── test_xml_validator_results.py
655
+ │ ├── test_xml_validator_utils.py
656
+ │ └── test_xmlvalidator.py
657
+ └── conftest.py # Pytest configuration
658
+
659
+ .gitignore # Git ignored files config
660
+ CHANGELOG.md # Changelog of releases
661
+ CODE_OF_CONDUCT.md # Contributor behavior expectations
662
+ CONTRIBUTING.md # How to contribute to the project
663
+ github_actions.md # Mermaid diagram of workflows
664
+ LICENSE # Project license (Apache 2.0)
665
+ Makefile # Automation tasks
666
+ poetry.lock # Poetry-generated lock file
667
+ project_meta.txt # Some basic code metrics for the project source
668
+ project_structure.txt # Reference copy of project structure
669
+ pyproject.toml # Build system and dependency configuration
670
+ pyrightconfig.json # Pyright type checking config
671
+ README.md # Project overview and instructions
672
+ requirements-dev.txt # Requirements file for devs (pip)
673
+ requirements.txt # Requirements file for users (pip)
674
+ ```
675
+
676
+ ---
677
+
678
+ ## License
679
+
680
+ Licensed under the Apache License 2.0. See [LICENSE](LICENSE).
681
+
682
+ ---
683
+
684
+ ## Author
685
+
686
+ [Michael Hallik](https://www.linkedin.com/in/michaelhallik/)