Skip to content

Commit 9f329a9

Browse files
authored
Merge pull request #115 from strictdoc-project/stanislaw/develop
helpers/lxml: improve lxml_dump_node()
2 parents 6676f34 + 3a1aa12 commit 9f329a9

3 files changed

Lines changed: 69 additions & 20 deletions

File tree

reqif/helpers/lxml.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,23 @@
77

88

99
def lxml_dump_node(node):
10-
return etree.tostring(node, method="xml").decode("utf8")
10+
output = ""
11+
node_no_ns_tag = etree.QName(node).localname
12+
output += f"<{node_no_ns_tag}"
13+
for attribute, attribute_value in node.attrib.items():
14+
output += f' {attribute}="{lxml_escape_for_html(attribute_value)}"'
15+
if node.text is not None or len(node.getchildren()) > 0:
16+
output += ">"
17+
if len(node.nsmap) > 0:
18+
output += lxml_stringify_namespaced_children(node)
19+
else:
20+
output += lxml_stringify_children(node)
21+
output += f"</{node_no_ns_tag}>"
22+
else:
23+
output += "/>"
24+
if node.tail is not None:
25+
output += lxml_escape_for_html(node.tail)
26+
return output
1127

1228

1329
# This code is taken from Python 3.7. The addition is escaping of the tab
@@ -45,19 +61,24 @@ def lxml_escape_title(string: str) -> str:
4561
# FIXME: Would be great to find a better solution for this.
4662
def lxml_stringify_namespaced_children(node, namespace_tag=None) -> str:
4763
if namespace_tag is None:
48-
assert (
49-
len(node.nsmap) > 0
50-
), f"This method must be called on a namespaced tag:\n{lxml_dump_node(node)}" # noqa: E501
64+
assert len(node.nsmap) > 0, (
65+
f"This method must be called on a namespaced tag. "
66+
f"Tag: {node}, line: {node.sourceline}."
67+
)
5168
nskey = next(iter(node.nsmap.keys()))
5269
else:
5370
nskey = namespace_tag
5471

5572
def _lxml_stringify_reqif_ns_node(node):
5673
assert node is not None
57-
5874
output = ""
5975
node_no_ns_tag = etree.QName(node).localname
60-
output += f"<{nskey}:{node_no_ns_tag}"
76+
tag = (
77+
f"{nskey}:{node_no_ns_tag}"
78+
if node.tag[0] == "{" or namespace_tag is not None
79+
else node.tag
80+
)
81+
output += f"<{tag}"
6182
for attribute, attribute_value in node.attrib.items():
6283
output += f' {attribute}="{lxml_escape_for_html(attribute_value)}"'
6384
if node.text is not None or len(node.getchildren()) > 0:
@@ -66,7 +87,7 @@ def _lxml_stringify_reqif_ns_node(node):
6687
output += lxml_escape_for_html(node.text)
6788
for child in node.getchildren():
6889
output += _lxml_stringify_reqif_ns_node(child)
69-
output += f"</{nskey}:{node_no_ns_tag}>"
90+
output += f"</{tag}>"
7091
else:
7192
output += "/>"
7293

tests/unit/reqif/helpers/lxml/test_lxml.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
11
from lxml import etree
22

33
from reqif.helpers.lxml import (
4-
lxml_dump_node,
54
lxml_is_self_closed_tag,
65
lxml_stringify_namespaced_children,
76
)
87

98

10-
def test_01_dump_xml() -> None:
11-
spec_type_string = """\
12-
<PARENT>
13-
<CHILD>text</CHILD>
14-
</PARENT>\
15-
"""
16-
spec_type_xml = etree.fromstring(spec_type_string)
17-
dump = lxml_dump_node(spec_type_xml)
18-
19-
assert dump == spec_type_string
20-
21-
229
def test__02_stringify_namespaced_children__01_basic() -> None:
2310
expected_string = "\n<reqif-xhtml:div>--</reqif-xhtml:div>\n"
2411

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from lxml import etree
2+
3+
from reqif.helpers.lxml import (
4+
lxml_dump_node,
5+
)
6+
7+
8+
def test__01__basic() -> None:
9+
spec_type_string = """\
10+
<PARENT>
11+
<CHILD>text</CHILD>
12+
</PARENT>\
13+
"""
14+
spec_type_xml = etree.fromstring(spec_type_string)
15+
dump = lxml_dump_node(spec_type_xml)
16+
17+
assert dump == spec_type_string
18+
19+
20+
def test__02__xhtml() -> None:
21+
expected_string = """\
22+
<THE-VALUE>
23+
AA<reqif-xhtml:div>
24+
11<reqif-xhtml:span attr="FOO">--<div>123</div>--</reqif-xhtml:span>22
25+
</reqif-xhtml:div>BB
26+
</THE-VALUE>
27+
"""
28+
29+
spec_type_string = """\
30+
<THE-ROOT xmlns:reqif-xhtml="http://www.w3.org/1999/xhtml">\
31+
<THE-VALUE>
32+
AA<reqif-xhtml:div>
33+
11<reqif-xhtml:span attr="FOO">--<div>123</div>--</reqif-xhtml:span>22
34+
</reqif-xhtml:div>BB
35+
</THE-VALUE>
36+
</THE-ROOT>
37+
"""
38+
spec_type_xml = etree.fromstring(spec_type_string)
39+
string = lxml_dump_node(spec_type_xml.find("THE-VALUE"))
40+
41+
assert string == expected_string

0 commit comments

Comments
 (0)