Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/attr escape #224

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .coverage
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,5 @@ dmypy.json
.pyre/

.idea/
.coverage
junit.xml
2 changes: 1 addition & 1 deletion json2xml/dicttoxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}'


Expand Down
34 changes: 33 additions & 1 deletion junit.xml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/test_dict2xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from json2xml import dicttoxml
from json2xml import dicttoxml, json2xml

Check notice

Code scanning / CodeQL

Unused import Note test

Import of 'json2xml' is not used.


class TestDict2xml:
Expand Down
56 changes: 56 additions & 0 deletions tests/test_xml_escape.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import pytest

Check notice

Code scanning / CodeQL

Unused import Note test

Import of 'pytest' is not used.
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'))
Comment on lines +29 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Avoid loops in tests. (no-loop-in-tests)

ExplanationAvoid complex code, like loops, in test functions.

Google's software engineering guidelines says:
"Clear tests are trivially correct upon inspection"
To reach that avoid complex code in tests:

  • loops
  • conditionals

Some ways to fix this:

  • Use parametrized tests to get rid of the loop.
  • Move the complex logic into helpers.
  • Move the complex part into pytest fixtures.

Complexity is most often introduced in the form of logic. Logic is defined via the imperative parts of programming languages such as operators, loops, and conditionals. When a piece of code contains logic, you need to do a bit of mental computation to determine its result instead of just reading it off of the screen. It doesn't take much logic to make a test more difficult to reason about.

Software Engineering at Google / Don't Put Logic in Tests


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

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 &amp; that"' in result

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


Loading