diff --git a/.coverage b/.coverage index 672c021..a667c01 100644 Binary files a/.coverage and b/.coverage differ diff --git a/.gitignore b/.gitignore index b97131e..06591d5 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,5 @@ dmypy.json .pyre/ .idea/ +.coverage +junit.xml diff --git a/json2xml/dicttoxml.py b/json2xml/dicttoxml.py index d51d98b..538e765 100644 --- a/json2xml/dicttoxml.py +++ b/json2xml/dicttoxml.py @@ -127,7 +127,7 @@ def make_attrstring(attr: dict[str, Any]) -> str: Returns: str: The string of XML attributes. """ - attrstring = " ".join([f'{k}="{v}"' for k, v in attr.items()]) + attrstring = " ".join([f'{k}="{escape_xml(v)}"' for k, v in attr.items()]) return f'{" " if attrstring != "" else ""}{attrstring}' diff --git a/junit.xml b/junit.xml index fef39a8..0b3139e 100644 --- a/junit.xml +++ b/junit.xml @@ -1 +1,33 @@ - \ No newline at end of file +self = <tests.test_xml_escape.TestEscaping object at 0x1051b4aa0> + + def test_escapes_angle_brackets(self): + json_data = json.dumps({"root": {"@attrs": {"HelpText": "version <here>"}}}) + result = json2xml.Json2xml(json_data).to_xml() +> assert '"HelpText": "version &lt;here&gt;"' in result +E assert '"HelpText": "version &lt;here&gt;"' in '<?xml version="1.0" encoding="UTF-8"?>\n<all>\n\t<item type="str">{&quot;root&quot;: {&quot;@attrs&quot;: {&quot;HelpText&quot;: &quot;version &lt;here&gt;&quot;}}}</item>\n</all>\n' + +tests/test_xml_escape.py:39: AssertionErrorself = <tests.test_xml_escape.TestEscaping object at 0x1051b4740> + + def test_escapes_quotes(self): + json_data = json.dumps({"root": {"@attrs": {"Text": "\"quoted\""}}}) + result = json2xml.Json2xml(json_data).to_xml() +> assert '"Text": "\\"quoted\\""' in result +E assert '"Text": "\\"quoted\\""' in '<?xml version="1.0" encoding="UTF-8"?>\n<all>\n\t<item type="str">{&quot;root&quot;: {&quot;@attrs&quot;: {&quot;Text&quot;: &quot;\\&quot;quoted\\&quot;&quot;}}}</item>\n</all>\n' + +tests/test_xml_escape.py:44: AssertionErrorself = <tests.test_xml_escape.TestEscaping object at 0x1051b42f0> + + def test_escapes_ampersands(self): + json_data = json.dumps({"root": {"@attrs": {"Text": "this & that"}}}) + result = json2xml.Json2xml(json_data).to_xml() +> assert '"Text": "this &amp; that"' in result +E assert '"Text": "this &amp; that"' in '<?xml version="1.0" encoding="UTF-8"?>\n<all>\n\t<item type="str">{&quot;root&quot;: {&quot;@attrs&quot;: {&quot;Text&quot;: &quot;this &amp; that&quot;}}}</item>\n</all>\n' + +tests/test_xml_escape.py:49: AssertionErrorself = <tests.test_xml_escape.TestEscaping object at 0x1051b5730> + + def test_escapes_mixed_special_chars(self): + json_data = json.dumps({"root": {"@attrs": {"Text": "<tag> & \"quote\""}}}) + result = json2xml.Json2xml(json_data).to_xml() +> assert '"Text": "&lt;tag&gt; &amp; \\"quote\\""' in result +E assert '"Text": "&lt;tag&gt; &amp; \\"quote\\""' in '<?xml version="1.0" encoding="UTF-8"?>\n<all>\n\t<item type="str">{&quot;root&quot;: {&quot;@attrs&quot;: {&quot;Text&quot;: &quot;&lt;tag&gt; &amp; \\&quot;quote\\&quot;&quot;}}}</item>\n</all>\n' + +tests/test_xml_escape.py:54: AssertionError \ No newline at end of file diff --git a/tests/test_dict2xml.py b/tests/test_dict2xml.py index 7a54ab7..21d5bd5 100644 --- a/tests/test_dict2xml.py +++ b/tests/test_dict2xml.py @@ -3,7 +3,7 @@ import pytest -from json2xml import dicttoxml +from json2xml import dicttoxml, json2xml class TestDict2xml: diff --git a/tests/test_xml_escape.py b/tests/test_xml_escape.py new file mode 100644 index 0000000..8592641 --- /dev/null +++ b/tests/test_xml_escape.py @@ -0,0 +1,56 @@ +import pytest +import json + +from json2xml import dicttoxml, json2xml + + + +class TestEscaping: + def test_escaping(self): + # Test cases + test_cases = [ + { + "root": { + "@attrs": { + "Text": "this & that" + } + } + }, + { + "data": json.dumps({"key": "value & more"}) + }, + { + "mixed": { + "json_str": json.dumps({"a": "b & c"}), + "plain": "text & symbols" + } + } + ] + for i, data in enumerate(test_cases): + print(f"\nTest case {i + 1}:") + print("Input:", data) + xml = dicttoxml.dicttoxml(data, custom_root='all') + print("Output XML:") + print(xml.decode('utf-8')) + + def test_escapes_angle_brackets(self): + json_data = json.dumps({"root": {"@attrs": {"HelpText": "version "}}}) + result = json2xml.Json2xml(json_data).to_xml() + assert '"HelpText": "version <here>"' in result + + def test_escapes_quotes(self): + json_data = json.dumps({"root": {"@attrs": {"Text": "\"quoted\""}}}) + result = json2xml.Json2xml(json_data).to_xml() + assert '"Text": "\\"quoted\\""' in result + + def test_escapes_ampersands(self): + json_data = json.dumps({"root": {"@attrs": {"Text": "this & that"}}}) + result = json2xml.Json2xml(json_data).to_xml() + assert '"Text": "this & that"' in result + + def test_escapes_mixed_special_chars(self): + json_data = json.dumps({"root": {"@attrs": {"Text": " & \"quote\""}}}) + result = json2xml.Json2xml(json_data).to_xml() + assert '"Text": "<tag> & \\"quote\\""' in result + +