[FIX] ir.ui.view: locate_node of a ns prefixed element
According to [1], "If your XPath expression uses namespace prefixes, you
must define them in a prefix mapping.". It makes sense because an xpath
to a prefixed tag is not able to uniquely locate the tag in the parent
view (it is possible to redefine the ns definition of a prefix, so you
could have multiple elements matching).
We chose to define the nsmap to locate the element in the parent view by
using the lxml internal form to qualify a node ({ns def}tagname). This
form is not compatible with etree.xpath but is with etree.ETXPath.
Fortunately, etree.ETXPath is compatible with the classic xpath
expressions so we'll use this one by default in `locate_node`.
A test has been introduced to showcase the problem.
http://lxml.de/xpathxslt.html#namespaces-and-prefixes: Namespaces and prefixes
This commit is contained in:
@@ -466,7 +466,7 @@ actual arch.
|
||||
:return: a node in the source matching the spec
|
||||
"""
|
||||
if spec.tag == 'xpath':
|
||||
nodes = arch.xpath(spec.get('expr'))
|
||||
nodes = etree.ETXPath(spec.get('expr'))(arch)
|
||||
return nodes[0] if nodes else None
|
||||
elif spec.tag == 'field':
|
||||
# Only compare the field name: a field can be only once in a given view
|
||||
|
||||
@@ -373,6 +373,52 @@ class TestQWebNS(TransactionCase):
|
||||
self.assertEquals(len(cac_lines), 2)
|
||||
self.assertEquals(result.count('Appel'), 2)
|
||||
|
||||
def test_render_static_xml_with_extension(self):
|
||||
""" Test the extension of a view by an xpath expression on a ns prefixed element.
|
||||
"""
|
||||
# primary view
|
||||
view1 = self.env['ir.ui.view'].create({
|
||||
'name': "dummy",
|
||||
'type': 'qweb',
|
||||
'arch': """
|
||||
<t t-name="base.dummy">
|
||||
<root>
|
||||
<h:table xmlns:h="http://www.example.org/table">
|
||||
<h:tr>
|
||||
<h:td xmlns:h="http://www.w3.org/TD/html4/">Apples</h:td>
|
||||
<h:td>Bananas</h:td>
|
||||
</h:tr>
|
||||
</h:table>
|
||||
</root>
|
||||
</t>
|
||||
"""
|
||||
})
|
||||
# extension patching the primary view
|
||||
view2 = self.env['ir.ui.view'].create({
|
||||
'name': "dummy_ext",
|
||||
'type': 'qweb',
|
||||
'inherit_id': view1.id,
|
||||
'arch': """
|
||||
<xpath expr="//{http://www.example.org/table}table/{http://www.example.org/table}tr">
|
||||
<h:td xmlns:h="http://www.example.org/table">Oranges</h:td>
|
||||
</xpath>
|
||||
"""
|
||||
})
|
||||
|
||||
expected_result = """
|
||||
<root>
|
||||
<h:table xmlns:h="http://www.example.org/table">
|
||||
<h:tr>
|
||||
<h:td xmlns:h="http://www.w3.org/TD/html4/">Apples</h:td>
|
||||
<h:td>Bananas</h:td>
|
||||
<h:td>Oranges</h:td>
|
||||
</h:tr>
|
||||
</h:table>
|
||||
</root>
|
||||
"""
|
||||
|
||||
self.assertEquals(dedent_and_strip(view1.with_context(check_view_ids=[view1.id, view2.id]).render()), dedent_and_strip(expected_result))
|
||||
|
||||
|
||||
from copy import deepcopy
|
||||
class FileSystemLoader(object):
|
||||
|
||||
Reference in New Issue
Block a user