Commit 27a9bcf3 authored by Nicolas Delaby's avatar Nicolas Delaby

Declare prefix used in xpath expression

parent a4b49f23
......@@ -67,7 +67,7 @@ class ERP5Diff:
# Declarative interfaces
zope.interface.implements(IERP5Diff,)
__version__ = 0.6
__version__ = 0.7
def __init__(self):
"""
......@@ -133,12 +133,15 @@ class ERP5Diff:
index = attr_name.index('}')
local_name = attr_name[index+1:]
namespace_uri = attr_name[1:index]
prefix = [t[0] for t in element.nsmap.iteritems() if t[1] == namespace_uri][0]
if namespace_uri == 'http://www.w3.org/XML/1998/namespace':
prefix = 'xml'
else:
prefix = [t[0] for t in element.nsmap.iteritems() if t[1] == namespace_uri][0]
return '%s:%s' % (prefix, local_name,), namespace_uri
else:
return attr_name, None
def _xupdateAppendAttributes(self, attr_dict, path):
def _xupdateAppendAttributes(self, attr_dict, path, nsmap=None):
"""
Append attrib to the element at 'path'.
"""
......@@ -149,7 +152,7 @@ class ERP5Diff:
key_list.sort()
for name in key_list:
val = attr_dict[name]
attr_element = etree.Element('{%s}attribute' % self._ns, nsmap=root.nsmap)
attr_element = etree.Element('{%s}attribute' % self._ns, nsmap=nsmap)
name, namespace_uri = name
attr_element.attrib['name'] = name
if namespace_uri:
......@@ -158,41 +161,41 @@ class ERP5Diff:
append_element.append(attr_element)
root.append(append_element)
def _xupdateRemoveAttribute(self, name, path):
def _xupdateRemoveAttribute(self, name, path, nsmap=None):
"""
Remove an attribute from the element at 'path'.
"""
root = self._getResultRoot()
remove_element = etree.Element('{%s}remove' % self._ns, nsmap=root.nsmap)
remove_element = etree.Element('{%s}remove' % self._ns, nsmap=nsmap)
remove_element.attrib['select'] = self._concatPath(path, 'attribute::' + name[0])
root.append(remove_element)
def _xupdateUpdateAttribute(self, name, val, path):
def _xupdateUpdateAttribute(self, name, val, path, nsmap=None):
"""
Update the value of an attribute of the element at 'path'.
"""
root = self._getResultRoot()
update_element = etree.Element('{%s}update' % self._ns, nsmap=root.nsmap)
update_element = etree.Element('{%s}update' % self._ns, nsmap=nsmap)
update_element.attrib['select'] = self._concatPath(path, 'attribute::' + name[0])
update_element.text = val
root.append(update_element)
def _xupdateRenameElement(self, name, path):
def _xupdateRenameElement(self, name, path, nsmap=None):
"""
Rename an existing element at 'path'.
"""
root = self._getResultRoot()
rename_element = etree.Element('{%s}rename' % self._ns, nsmap=root.nsmap)
rename_element = etree.Element('{%s}rename' % self._ns, nsmap=nsmap)
rename_element.attrib['select'] = path
rename_element.text = name
root.append(rename_element)
def _xupdateUpdateElement(self, element, path):
def _xupdateUpdateElement(self, element, path, nsmap=None):
"""
Update the contents of an element at 'path' to that of 'element'.
"""
root = self._getResultRoot()
update_element = etree.Element('{%s}update' % self._ns, nsmap=root.nsmap)
update_element = etree.Element('{%s}update' % self._ns, nsmap=nsmap)
update_element.attrib['select'] = path
if self._hasChildren(element):
for child in element:
......@@ -202,16 +205,16 @@ class ERP5Diff:
update_element.text = element.text
root.append(update_element)
def _xupdateRemoveElement(self, path):
def _xupdateRemoveElement(self, path, nsmap=None):
"""
Remove an element at 'path'.
"""
root = self._getResultRoot()
remove_element = etree.Element('{%s}remove' % self._ns, nsmap=root.nsmap)
remove_element = etree.Element('{%s}remove' % self._ns, nsmap=nsmap)
remove_element.attrib['select'] = path
root.append(remove_element)
def _xupdateAppendElements(self, element_list, path):
def _xupdateAppendElements(self, element_list, path, nsmap=None):
"""
Append elements to the element at 'path'.
xupdate:append
......@@ -227,22 +230,22 @@ class ERP5Diff:
for element in element_list:
relative_next = element.getnext()
relative_previous = element.getprevious()
if element.getprevious() in element_list:
if relative_previous in element_list:
#reuse same container as preceding
append_element = last_append_element
elif relative_next is not None and relative_next not in element_list:
append_element = etree.SubElement(root, '{%s}insert-before' % self._ns, nsmap=root.nsmap)
append_element = etree.SubElement(root, '{%s}insert-before' % self._ns, nsmap=nsmap)
path_list = self._makeRelativePathList([relative_next])
next_sibling_path = self._concatPath(path, path_list[0])
append_element.attrib['select'] = next_sibling_path
elif relative_previous is not None and relative_previous not in element_list:
append_element = etree.SubElement(root, '{%s}insert-after' % self._ns, nsmap=root.nsmap)
append_element = etree.SubElement(root, '{%s}insert-after' % self._ns, nsmap=nsmap)
path_list = self._makeRelativePathList([relative_previous])
preceding_sibling_path = self._concatPath(path, path_list[0])
append_element.attrib['select'] = preceding_sibling_path
else:
#xupdate:append by default
append_element = etree.SubElement(root, '{%s}append' % self._ns, nsmap=root.nsmap)
append_element = etree.SubElement(root, '{%s}append' % self._ns, nsmap=nsmap)
if parent_element.index(element) == 0:
child = 'first()'
elif parent_element.index(element) == (len_total_child_list -1):
......@@ -258,7 +261,7 @@ class ERP5Diff:
child_element.attrib['namespace'] = namespace_uri
attr_map = element.attrib
for name, value in attr_map.items():
attr_element = etree.SubElement(child_element, '{%s}attribute' % self._ns, nsmap=root.nsmap)
attr_element = etree.SubElement(child_element, '{%s}attribute' % self._ns, nsmap=child_element.nsmap)
name, namespace_uri = self._getQName(element, name)
attr_element.attrib['name'] = name
if namespace_uri:
......@@ -318,19 +321,19 @@ class ERP5Diff:
if name1 in dict2:
if val1 != dict2[name1]:
# The value is different.
self._xupdateUpdateAttribute(name1, dict2[name1], path)
self._xupdateUpdateAttribute(name1, dict2[name1], path, nsmap=element.nsmap)
# Mark this attribute.
dict2[name1] = None
else:
# This attribute is removed.
self._xupdateRemoveAttribute(name1, path)
self._xupdateRemoveAttribute(name1, path, nsmap=element.nsmap)
d = {}
for name2, val2 in dict2.iteritems():
if val2 is not None:
# This attribute is added.
d[name2] = val2
if d != {}:
self._xupdateAppendAttributes(d, path)
self._xupdateAppendAttributes(d, path, nsmap=element.nsmap)
def _checkEmptiness(self, element):
"""
......@@ -453,7 +456,7 @@ class ERP5Diff:
elif old_is_empty or new_is_empty:
# Perhaps they are very different.
self._p("One of them is empty, so just update all the contents.")
self._xupdateUpdateElement(new_element, path)
self._xupdateUpdateElement(new_element, path, nsmap=new_element.nsmap)
else:
# Second, determine if text should be ignored.
old_ignore_text = self._checkIgnoreText(old_element)
......@@ -462,7 +465,7 @@ class ERP5Diff:
if old_ignore_text != new_ignore_text:
# This means that the semantics of this element is quite different.
self._p("One of them has only text and the other does not, so just update all the contents.")
self._xupdateUpdateElement(new_element, path)
self._xupdateUpdateElement(new_element, path, nsmap=new_element.nsmap)
elif not old_ignore_text:
# The contents are only text.
self._p("Both have only text.")
......@@ -491,7 +494,7 @@ class ERP5Diff:
break
else:
# There is no matching node. So this element must be removed.
self._xupdateRemoveElement(child_path)
self._xupdateRemoveElement(child_path, old_node.nsmap)
if new_len > new_start:
# There are remaining nodes in the new children.
self._xupdateAppendElements(new_list[new_start:new_len], path)
......@@ -508,7 +511,7 @@ class ERP5Diff:
try:
if self._result is not None:
self._result = None
self._result = etree.Element('{%s}modifications' % self._ns, nsmap={'xupdate':self._ns})
self._result = etree.Element('{%s}modifications' % self._ns, nsmap={'xupdate': self._ns})
self._result.set('version', '1.0')
if self._testElements(old_root_element, new_root_element):
qname = old_root_element.xpath('name()')
......@@ -517,7 +520,9 @@ class ERP5Diff:
else:
# These XML documents seem to be completely different...
if old_root_element.tag != new_root_element.tag:
self._xupdateRenameElement(new_root_element.xpath('name()'), '/%s' % old_root_element.xpath('name()'))
nsmap = old_root_element.nsmap
nsmap.update(new_root_element.nsmap)
self._xupdateRenameElement(new_root_element.xpath('name()'), '/%s' % old_root_element.xpath('name()'), nsmap)
qname = new_root_element.xpath('name()')
self._testAttributes(old_root_element, new_root_element, '/%s' % qname)
self._compareChildNodes(old_root_element, new_root_element, '/%s' % qname)
......
......@@ -723,11 +723,11 @@ does not work as bellow example. This is a known bug.
>>> erp5diff.compare(old_xml, new_xml)
>>> erp5diff.output()
<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:remove select="/erp5/object[2]/prefixbis:title"/>
<xupdate:remove xmlns:prefixbis="http://any_uri_bis" select="/erp5/object[2]/prefixbis:title"/>
<xupdate:append select="/erp5/object[2]" child="first()">
<xupdate:element name="prefix:title" namespace="http://any_uri"><xupdate:attribute name="prefix:myattr" namespace="http://any_uri">anyvalue</xupdate:attribute>B</xupdate:element>
</xupdate:append>
<xupdate:remove select="/erp5/object[3]/againanotherprefix:title"/>
<xupdate:remove xmlns:againanotherprefix="http://any_uri" select="/erp5/object[3]/againanotherprefix:title"/>
<xupdate:append select="/erp5/object[3]" child="first()">
<xupdate:element name="title">A</xupdate:element>
</xupdate:append>
......@@ -762,7 +762,7 @@ does not work as bellow example. This is a known bug.
>>> erp5diff.compare(old_xml, new_xml)
>>> erp5diff.output()
<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:update select="/erp5/object/title/attribute::prefix:attr">B</xupdate:update>
<xupdate:update xmlns:prefix="http://any_uri" select="/erp5/object/title/attribute::prefix:attr">B</xupdate:update>
</xupdate:modifications>
25. Modify nodes with Qualified Names at root level
......@@ -784,10 +784,12 @@ does not work as bellow example. This is a known bug.
>>> erp5diff.compare(old_xml, new_xml)
>>> erp5diff.output()
<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:rename select="/erp5:erp5">aaa:erp5</xupdate:rename>
<xupdate:remove select="/aaa:erp5/attribute::a"/>
<xupdate:update select="/aaa:erp5/object/title/attribute::prefix:attr">B</xupdate:update>
<xupdate:rename xmlns:aaa="http://www.erp5.org/namspaces/aaa" xmlns:erp5="http://www.erp5.org/namspaces/erp5_object" select="/erp5:erp5">aaa:erp5</xupdate:rename>
<xupdate:remove xmlns:aaa="http://www.erp5.org/namspaces/aaa" select="/aaa:erp5/attribute::a"/>
<xupdate:update xmlns:prefix="http://any_uri" xmlns:aaa="http://www.erp5.org/namspaces/aaa" select="/aaa:erp5/object/title/attribute::prefix:attr">B</xupdate:update>
</xupdate:modifications>
- 2003-12-04, Yoshinori OKUJI <yo@nexedi.com>
- 2009-09-15, Tatuya Kamada <tatuya@nexedi.com>
- 2009-01-12, Nicolas Delaby <nicolas@nexedi.com>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment