[FIX] base: use html method from lxml

Prior to this change the convert tool did could mangle
the value of html fields when importing static data.

This is because html does not support 'self-closing'
except for HTML5 where it is allowed on void elements (such as img).

Browsers will assume that they are opening tags, left unclosed.
<span/> becomes <span>
They will then try to repair them with variying degrees of success.

Example where it fails:
`<t><t/></t><t><t/></t>`
should become
`<t><t></t></t><t><t></t></t>`
but it becomes
`<t><t></t><t><t></t></t>`

i.e. instead of closing the 'self-closing' tag immediately,
it puts everything inside a single t node

More concretely:
```
<t t-if>
  <t t-out />
</t>
<t t-else>
  <t t-out/>
</t>
```
becomes
```
<t t-if>
  <t t-out></t>
  <t t-else>
     <t t-out></t>
  </t>
</t>
```
which is invalid

-------------------------
The fix is simply to tell lxml that we want to print the xml nodes
as HTML nodes. This will make sure the output is compliant with
the standard and keep the semantic clear for the browser.

The issue does not appear before 16.2, as jquery used to fix it
for us until an update here 9c41ee5091ac06ac3ca71aeac607195c70061e4a

task-3162320

X-original-commit: 8ff2e1018264972107f19755ecda352d78dfa829
Part-of: odoo/odoo#118710
This commit is contained in:
Renaud Thiry
2023-04-17 11:47:11 +02:00
parent 5c146ec219
commit f7e5fd7aab
2 changed files with 21 additions and 3 deletions
+20 -2
View File
@@ -265,6 +265,24 @@ class TestEvalXML(common.TransactionCase):
def test_xml(self):
pass
@unittest.skip("not tested")
def test_html(self):
pass
self.assertEqual(
self.eval_xml(Field(ET.fromstring(
"""<parent>
<t t-if="True">
<t t-out="'text'"/>
</t>
<t t-else="">
<t t-out="'text2'"></t>
</t>
</parent>"""), type="html")),
"""<parent>
<t t-if="True">
<t t-out="'text'"></t>
</t>
<t t-else="">
<t t-out="'text2'"></t>
</t>
</parent>""",
"Evaluating an HTML field should give empty nodes instead of self-closing tags"
)
+1 -1
View File
@@ -142,7 +142,7 @@ def _eval_xml(self, node, env):
return '<?xml version="1.0"?>\n'\
+_process("".join(etree.tostring(n, encoding='unicode') for n in node))
if t == 'html':
return _process("".join(etree.tostring(n, encoding='unicode') for n in node))
return _process("".join(etree.tostring(n, method='html', encoding='unicode') for n in node))
data = node.text
if node.get('file'):