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

Declare prefix used in xpath expression

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