Skip to content

Commit d9ab4c2

Browse files
Michael HallikMichael Hallik
authored andcommitted
Improve keyword doc and README
1 parent 61d265a commit d9ab4c2

File tree

4 files changed

+105
-62
lines changed

4 files changed

+105
-62
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ It provides structured and detailed reporting of XML parse errors (malformed XML
7272
- Customizable error attributes (`path`, `reason`, `message`, etc.)
7373
- Batch validation and per-file error tracking
7474
- Export collected errors to CSV (with optional file name timestamping).
75-
- And more.
75+
- And more (see below and the keyword documentation).
7676

7777
---
7878

@@ -205,6 +205,8 @@ In that fashion the keyword works through the entire set of files.
205205

206206
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.
207207

208+
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.
209+
208210
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).
209211

210212
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.

docs/XmlValidator.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# General.
22
[tool.poetry]
33
name = "robotframework-xmlvalidator"
4-
version = "1.0.0b3"
4+
version = "1.0.0b4"
55
description = "A Robot Framework test library for validating XML files against XSD schemas."
66
authors = ["Michael Hallik <[email protected]>"]
77
license = "Apache-2.0"

src/xmlvalidator/XmlValidator.py

Lines changed: 100 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
from typing import Any, Dict, List, Literal, Optional, Tuple
5151
# Third party library imports.
5252
from lxml import etree
53-
from robot.api import logger
53+
from robot.api import Failure, logger
5454
from robot.api.deco import keyword, library
5555
from xmlschema import XMLSchema
5656
# Local application imports.
@@ -243,6 +243,16 @@ class XmlValidator:
243243
passing ``xsd_path``) and/or when calling ``Validate Xml Files``
244244
with ``xsd_path``.
245245
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+
246256
**Basic usage examples**
247257
248258
For a comprehensive set of example test cases, please see the
@@ -298,65 +308,84 @@ class XmlValidator:
298308
299309
.. code:: console
300310
301-
[ WARN ] Schema 'schema.xsd' set.
302-
[ WARN ] Collecting error facets: ['path', 'reason'].
303-
[ WARN ] XML Validator ready for use!
311+
Schema 'schema.xsd' set.
312+
Collecting error facets: ['path', 'reason'].
313+
XML Validator ready for use!
304314
==============================================================================
305315
01 Advanced Validation:: Demo XML validation
306-
[ WARN ] Mapping XML files to schemata by namespace.
307-
[ WARN ] Validating 'valid_1.xml'.
308-
[ WARN ] XML is valid!
309-
[ WARN ] Validating 'valid_2.xml'.
310-
[ WARN ] XML is valid!
311-
[ WARN ] Validating 'valid_3.xml'.
312-
[ WARN ] XML is valid!
313-
[ WARN ] Validating 'xsd_violations_1.xml'.
314-
[ WARN ] Setting new schema file: C:\\Projects\\robotframework-xmlvalidator\\test\\_data\\integration\\TC_01\\schema1.xsd.
315-
[ WARN ] XML is invalid:
316-
[ WARN ] Error #0:
317-
[ WARN ] path: /Employee
318-
[ WARN ] reason: Unexpected child with tag '{http://example.com/schema1}FullName' at position 2. Tag '{http://example.com/schema1}Name' expected.
319-
[ WARN ] Error #1:
320-
[ WARN ] path: /Employee/Age
321-
[ WARN ] reason: invalid literal for int() with base 10: 'Twenty Five'
322-
[ WARN ] Error #2:
323-
[ WARN ] path: /Employee/ID
324-
[ WARN ] reason: invalid literal for int() with base 10: 'ABC'
325-
[ WARN ] Validating 'valid_.xml_4'.
326-
[ WARN ] XML is valid!
327-
[ WARN ] Validating 'valid_.xml_5'.
328-
[ WARN ] XML is valid!
329-
[ WARN ] Validating 'malformed_xml_1.xml'.
330-
[ WARN ] XML is invalid:
331-
[ WARN ] Error #0:
332-
[ 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)
333-
[ WARN ] Error #1:
334-
[ 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)
335-
[ WARN ] Validating 'xsd_violations_2.xml'.
336-
[ WARN ] Setting new schema file: C:\\Projects\\robotframework-xmlvalidator\\test\\_data\\integration\\TC_01\\schema2.xsd.
337-
[ WARN ] XML is invalid:
338-
[ WARN ] Error #0:
339-
[ WARN ] path: /Product/Price
340-
[ WARN ] reason: invalid value '99.99USD' for xs:decimal
341-
[ WARN ] Error #1:
342-
[ WARN ] path: /Product
343-
[ WARN ] reason: The content of element '{http://example.com/schema2}Product' is not complete. Tag '{http://example.com/schema2}Price' expected.
344-
[ WARN ] Validating 'valid_.xml_6'.
345-
[ WARN ] XML is valid!
346-
[ WARN ] Validating 'no_xsd_match_1.xml'.
347-
[ WARN ] XML is invalid:
348-
[ WARN ] Error #0:
349-
[ WARN ] reason: No matching XSD found for: no_xsd_match_1.xml.
350-
[ WARN ] Validating 'no_xsd_match_2.xml'.
351-
[ WARN ] XML is invalid:
352-
[ WARN ] Error #0:
353-
[ WARN ] reason: No matching XSD found for: no_xsd_match_2.xml.
354-
[ WARN ] Validation errors exported to 'C:\\test\\01_Advanced_Validation\\errors_2025-03-29_13-54-46-552150.csv'.
355-
[ WARN ] Total_files validated: 11.
356-
[ WARN ] Valid files: 6.
357-
[ WARN ] Invalid files: 5
358-
359-
The corresponding CSV output would look like:
316+
Mapping XML files to schemata by namespace.
317+
Validating 'valid_1.xml'.
318+
XML is valid!
319+
Validating 'valid_2.xml'.
320+
XML is valid!
321+
Validating 'valid_3.xml'.
322+
XML is valid!
323+
Validating 'xsd_violations_1.xml'.
324+
Setting new schema file: C:\\Projects\\robotframework-xmlvalidator\\test\\_data\\integration\\TC_01\\schema1.xsd.
325+
[ WARN ] XML is invalid:
326+
[ WARN ] Error #0:
327+
[ WARN ] path: /Employee
328+
[ WARN ] reason: Unexpected child with tag '{http://example.com/schema1}FullName' at position 2. Tag '{http://example.com/schema1}Name' expected.
329+
[ WARN ] Error #1:
330+
[ WARN ] path: /Employee/Age
331+
[ WARN ] reason: invalid literal for int() with base 10: 'Twenty Five'
332+
[ WARN ] Error #2:
333+
[ WARN ] path: /Employee/ID
334+
[ WARN ] reason: invalid literal for int() with base 10: 'ABC'
335+
Validating 'valid_.xml_4'.
336+
XML is valid!
337+
Validating 'valid_.xml_5'.
338+
XML is valid!
339+
Validating 'malformed_xml_1.xml'.
340+
[ WARN ] XML is invalid:
341+
[ WARN ] Error #0:
342+
[ 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)
343+
[ WARN ] Error #1:
344+
[ 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)
345+
Validating 'xsd_violations_2.xml'.
346+
Setting new schema file: C:\\Projects\\robotframework-xmlvalidator\\test\\_data\\integration\\TC_01\\schema2.xsd.
347+
[ WARN ] XML is invalid:
348+
[ WARN ] Error #0:
349+
[ WARN ] path: /Product/Price
350+
[ WARN ] reason: invalid value '99.99USD' for xs:decimal
351+
[ WARN ] Error #1:
352+
[ WARN ] path: /Product
353+
[ WARN ] reason: The content of element '{http://example.com/schema2}Product' is not complete. Tag '{http://example.com/schema2}Price' expected.
354+
Validating 'valid_.xml_6'.
355+
XML is valid!
356+
Validating 'no_xsd_match_1.xml'.
357+
[ WARN ] XML is invalid:
358+
[ WARN ] Error #0:
359+
[ WARN ] reason: No matching XSD found for: no_xsd_match_1.xml.
360+
Validating 'no_xsd_match_2.xml'.
361+
[ WARN ] XML is invalid:
362+
[ WARN ] Error #0:
363+
[ WARN ] reason: No matching XSD found for: no_xsd_match_2.xml.
364+
Validation errors exported to 'C:\\test\\01_Advanced_Validation\\errors_2025-03-29_13-54-46-552150.csv'.
365+
Total_files validated: 11.
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'.
379+
Total_files validated: 11.
380+
Valid files: 6.
381+
Invalid files: 5.
382+
01 Advanced Validation:: Demo XML validation | FAIL |
383+
21 errors have been detected.
384+
========================================================
385+
01 Advanced Validation:: Demo XML validation | FAIL |
386+
1 test, 0 passed, 1 failed
387+
388+
The corresponding CSV output would in both cases look like:
360389
361390
.. code:: text
362391
@@ -370,6 +399,7 @@ class XmlValidator:
370399
schema2_invalid_2.xml,/Product,The content of element '{http://example.com/schema2}Product' is not complete. Tag '{http://example.com/schema2}Price' expected.
371400
no_xsd_match_1.xml,,No matching XSD found for: no_xsd_match_1.xml.
372401
no_xsd_match_2.xml,,No matching XSD found for: no_xsd_match_2.xml.
402+
373403
"""
374404

375405
__version__ = '1.0.0'
@@ -1358,7 +1388,8 @@ def validate_xml_files( # pylint: disable=R0913:too-many-arguments disable=R0914
13581388
pre_parse: Optional[bool] = True,
13591389
write_to_csv: Optional[bool] = True,
13601390
timestamped: Optional[bool] = True,
1361-
reset_errors: bool = True
1391+
reset_errors: bool = True,
1392+
fail_on_errors: Optional[bool] = False
13621393
) -> Tuple[
13631394
List[ Dict[str, Any] ],
13641395
str | None
@@ -1483,6 +1514,12 @@ def validate_xml_files( # pylint: disable=R0913:too-many-arguments disable=R0914
14831514
Clears previously stored validation results before this run.
14841515
Defaults to True.
14851516
1517+
``fail_on_errors``
1518+
1519+
Fails a test cases if, after checking the entire batch of one or
1520+
XML files, one or more errors have been reported. Error
1521+
reporting and exporting will not change.
1522+
14861523
**Returns**
14871524
14881525
A tuple, holding:
@@ -1558,6 +1595,10 @@ def validate_xml_files( # pylint: disable=R0913:too-many-arguments disable=R0914
15581595
csv_path = None
15591596
# Log a summary of the test run.
15601597
self.validator_results.log_summary()
1598+
if fail_on_errors and self.validator_results.errors_by_file:
1599+
raise Failure(
1600+
f"{len(self.validator_results.errors_by_file)} errors have been detected."
1601+
)
15611602
return (
15621603
self.validator_results.errors_by_file,
15631604
csv_path if csv_path else None

0 commit comments

Comments
 (0)