From ab293d325cc6a714686454bf129c71c3d27a8146 Mon Sep 17 00:00:00 2001 From: Nicolas Delaby <nicolas@nexedi.com> Date: Thu, 8 Oct 2009 14:37:18 +0000 Subject: [PATCH] Remove default namespace of syncml streams and declare a specific prefix. This avoid conflict between SyncML Stream and carried Data in xml w/o prefix. Carried data must never belong to SyncML namespace even for NonQualified XML. before: <SyncML xmlns="SYNCML:SYNCML1.2"> ...<object portal_type="Person" id="1"> ... </object> </SyncML> after: <syncml:SyncML xmlns:syncml="SYNCML:SYNCML1.2"> ...<object portal_type="Person" id="1"> ... </object> </syncml:SyncML> git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@29478 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5SyncML/Conduit/ERP5Conduit.py | 16 +- .../ERP5SyncML/PublicationSynchronization.py | 17 +- .../ERP5SyncML/SubscriptionSynchronization.py | 23 +- product/ERP5SyncML/SyncCode.py | 4 +- product/ERP5SyncML/SynchronizationTool.py | 3 +- product/ERP5SyncML/XMLSyncUtils.py | 235 +++++++++--------- 6 files changed, 150 insertions(+), 148 deletions(-) diff --git a/product/ERP5SyncML/Conduit/ERP5Conduit.py b/product/ERP5SyncML/Conduit/ERP5Conduit.py index 3041d99970..348bef73cd 100644 --- a/product/ERP5SyncML/Conduit/ERP5Conduit.py +++ b/product/ERP5SyncML/Conduit/ERP5Conduit.py @@ -641,7 +641,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): if subnode.xpath('local-name()') == property: return self.convertXmlValue(subnode) return None - + def replaceIdFromXML(self, xml, new_id): """ return a xml with id replace by a new id @@ -652,16 +652,12 @@ class ERP5Conduit(XMLSyncUtilsMixin): #copy of xml object for modification from copy import deepcopy xml_copy = deepcopy(xml) - if xml.nsmap is None or xml.nsmap == {}: - object_element = xml_copy.find(self.xml_object_tag) - if object_element is None and xml_copy.tag == self.xml_object_tag: - object_element = xml_copy - id_element = object_element.find('id') + if xml_copy.tag == self.xml_object_tag: + object_element = xml_copy else: - object_element = xml_copy.xpath('//syncml:object', - namespaces={'syncml':xml_copy.nsmap[xml_copy.prefix]})[0] - id_element = object_element.xpath('//syncml:id', - namespaces={'syncml':xml_copy.nsmap[xml_copy.prefix]})[0] + object_element = xml_copy.xpath('//object')[0] + #XXXElement id will be removed from asXML + id_element = object_element.xpath('./id')[0] object_element.attrib['id'] = new_id id_element.text = new_id return etree.tostring(xml_copy) diff --git a/product/ERP5SyncML/PublicationSynchronization.py b/product/ERP5SyncML/PublicationSynchronization.py index 8f773029bb..412362e2eb 100644 --- a/product/ERP5SyncML/PublicationSynchronization.py +++ b/product/ERP5SyncML/PublicationSynchronization.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- ############################################################################## # # Copyright (c) 2003 Nexedi SARL and Contributors. All Rights Reserved. @@ -39,8 +40,11 @@ from AccessControl.SecurityManagement import newSecurityManager import commands from DateTime import DateTime from zLOG import LOG, DEBUG, INFO, WARNING -from lxml.etree import Element, SubElement from lxml import etree +from lxml.builder import ElementMaker +from SyncCode import SYNCML_NAMESPACE +nsmap = {'syncml' : SYNCML_NAMESPACE} +E = ElementMaker(namespace=SYNCML_NAMESPACE, nsmap=nsmap) class PublicationSynchronization(XMLSyncUtils): """ @@ -78,18 +82,17 @@ class PublicationSynchronization(XMLSyncUtils): subscriber.setSourceURI(self.getTargetURI(xml_client)) subscriber.setTargetURI(self.getSourceURI(xml_client)) - cmd_id = 1 # specifies a SyncML message-unique command identifier - + cmd_id = 1 # specifies a SyncML message-unique command identifier #create element 'SyncML' with a default namespace - nsmap = {None : self.XHTML_NAMESPACE} - xml = Element('SyncML',nsmap=nsmap) + xml = E.SyncML() # syncml header xml.append(self.SyncMLHeader(subscriber.getSessionId(), subscriber.getMessageId(), subscriber.getSubscriptionUrl(), publication.getPublicationUrl())) # syncml body - sync_body = SubElement(xml, 'SyncBody') + sync_body = E.SyncBody() + xml.append(sync_body) #at the begining, the code is initialised at UNAUTHORIZED auth_code = self.UNAUTHORIZED @@ -197,7 +200,7 @@ class PublicationSynchronization(XMLSyncUtils): has been started from the server (forbiden)" # a synchronisation is always starded from a client and can't be from # a server ! - sync_body.append(Element('Final')) + sync_body.append(E.Final()) xml_string = etree.tostring(xml, encoding='utf-8', pretty_print=True) if publication.getSyncContentType() == self.CONTENT_TYPE['SYNCML_WBXML']: xml_string = self.xml2wbxml(xml_string) diff --git a/product/ERP5SyncML/SubscriptionSynchronization.py b/product/ERP5SyncML/SubscriptionSynchronization.py index d4dc933298..2d87fd2d7b 100644 --- a/product/ERP5SyncML/SubscriptionSynchronization.py +++ b/product/ERP5SyncML/SubscriptionSynchronization.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- ############################################################################## # # Copyright (c) 2003 Nexedi SARL and Contributors. All Rights Reserved. @@ -35,8 +36,11 @@ from Conduit.ERP5Conduit import ERP5Conduit from AccessControl import getSecurityManager from DateTime import DateTime from zLOG import LOG, DEBUG, INFO -from lxml.etree import Element, SubElement from lxml import etree +from lxml.builder import ElementMaker +from SyncCode import SYNCML_NAMESPACE +nsmap = {'syncml' : SYNCML_NAMESPACE} +E = ElementMaker(namespace=SYNCML_NAMESPACE, nsmap=nsmap) class SubscriptionSynchronization(XMLSyncUtils): @@ -54,17 +58,16 @@ class SubscriptionSynchronization(XMLSyncUtils): subscription.setZopeUser(user) subscription.setAuthenticated(True) - #create element 'SyncML' with a default namespace - nsmap = {None : self.XHTML_NAMESPACE} - xml = Element('SyncML',nsmap=nsmap) + #create element 'SyncML' + xml = E.SyncML() # syncml header xml.append(self.SyncMLHeader(subscription.incrementSessionId(), subscription.incrementMessageId(), subscription.getPublicationUrl(), subscription.getSubscriptionUrl(), source_name=subscription.getLogin())) # syncml body - sync_body = SubElement(xml, 'SyncBody') - + sync_body = E.SyncBody() + xml.append(sync_body) # We have to set every object as NOT_SYNCHRONIZED subscription.startSynchronization() @@ -96,8 +99,7 @@ class SubscriptionSynchronization(XMLSyncUtils): """ cmd_id = 1 # specifies a SyncML message-unique command identifier #create element 'SyncML' with a default namespace - nsmap = {None : self.XHTML_NAMESPACE} - xml = Element('SyncML',nsmap=nsmap) + xml = E.SyncML() # syncml header data = "%s:%s" % (subscription.getLogin(), subscription.getPassword()) data = subscription.encode(subscription.getAuthenticationFormat(), data) @@ -112,7 +114,8 @@ class SubscriptionSynchronization(XMLSyncUtils): authentication_type=subscription.getAuthenticationType())) # syncml body - sync_body = SubElement(xml, 'SyncBody') + sync_body = E.SyncBody() + xml.append(sync_body) # We have to set every object as NOT_SYNCHRONIZED subscription.startSynchronization() @@ -128,7 +131,7 @@ class SubscriptionSynchronization(XMLSyncUtils): if syncml_put is not None: sync_body.append(syncml_put) cmd_id += 1 - sync_body.append(Element('Final')) + sync_body.append(E.Final()) xml_string = etree.tostring(xml, encoding='utf-8', xml_declaration=True, pretty_print=True) self.sendResponse(from_url=subscription.subscription_url, diff --git a/product/ERP5SyncML/SyncCode.py b/product/ERP5SyncML/SyncCode.py index 1089850511..eca8415941 100644 --- a/product/ERP5SyncML/SyncCode.py +++ b/product/ERP5SyncML/SyncCode.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- ############################################################################## # # Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved. @@ -30,6 +31,8 @@ from Products.ERP5Type.Accessor.TypeDefinition import list_types from Globals import Persistent import re +SYNCML_NAMESPACE = 'SYNCML:SYNCML1.2' + class SyncCode(Persistent): """ Class giving the Synchronization's Constants @@ -133,7 +136,6 @@ class SyncCode(Persistent): #Namespace #In SyncML Representation Protocol OMA #we use URN as format of namespace - XHTML_NAMESPACE = 'SYNCML:SYNCML1.2' # List namespaces supported URN_LIST = ('SYNCML:SYNCML1.1', 'SYNCML:SYNCML1.2') diff --git a/product/ERP5SyncML/SynchronizationTool.py b/product/ERP5SyncML/SynchronizationTool.py index 42c3b341cb..99a26b1fa6 100644 --- a/product/ERP5SyncML/SynchronizationTool.py +++ b/product/ERP5SyncML/SynchronizationTool.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- ## Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved. # Sebastien Robin <seb@nexedi.com> # @@ -35,8 +36,6 @@ from Products.CMFCore.utils import UniqueObject from Globals import InitializeClass, DTMLFile, PersistentMapping, Persistent from AccessControl import ClassSecurityInfo, getSecurityManager from Products.CMFCore import CMFCorePermissions -from Products.ERP5SyncML import _dtmldir -from Products.ERP5SyncML import Conduit from Publication import Publication, Subscriber from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2 from Subscription import Subscription diff --git a/product/ERP5SyncML/XMLSyncUtils.py b/product/ERP5SyncML/XMLSyncUtils.py index bee1b77d03..0d7efc92c6 100644 --- a/product/ERP5SyncML/XMLSyncUtils.py +++ b/product/ERP5SyncML/XMLSyncUtils.py @@ -35,8 +35,10 @@ from ERP5Diff import ERP5Diff from zLOG import LOG, INFO from lxml import etree -from lxml.etree import Element, SubElement -from lxml.builder import E +from lxml.builder import ElementMaker +from SyncCode import SYNCML_NAMESPACE +nsmap = {'syncml' : SYNCML_NAMESPACE} +E = ElementMaker(namespace=SYNCML_NAMESPACE, nsmap=nsmap) parser = etree.XMLParser(remove_blank_text=True) from xml.dom import minidom @@ -187,7 +189,7 @@ class XMLSyncUtilsMixin(SyncCode): cmd_ref = '%s' % remote_xml.xpath("string(.//syncml:CmdID)") target_ref = '%s' % remote_xml.xpath("string(.//syncml:Target/syncml:LocURI)") source_ref = '%s' % remote_xml.xpath("string(.//syncml:Source/syncml:LocURI)") - xml = Element('Status') + xml = E.Status() if cmd_id: xml.append(E.CmdID('%s' % cmd_id)) if msg_ref: @@ -240,7 +242,7 @@ class XMLSyncUtilsMixin(SyncCode): if getattr(conduit, 'getCapabilitiesCTTypeList', None) is not None and \ getattr(conduit, 'getCapabilitiesVerCTList', None) is not None and \ getattr(conduit, 'getPreferedCapabilitieVerCT', None) is not None: - xml = Element(markup) + xml = Element('{%s}%s' % (SYNCML_NAMESPACE, markup)) xml.append(E.CmdID('%s' % cmd_id)) if message_id: xml.append(E.MsgRef('%s' % message_id)) @@ -269,12 +271,12 @@ class XMLSyncUtilsMixin(SyncCode): for x_version in conduit.getCapabilitiesVerCTList(type): rx_element_list.append(E.Rx(E.CTType(type), E.VerCT(x_version))) tx_element_list.append(E.Tx(E.CTType(type), E.VerCT(x_version))) - rx_pref = Element('Rx-Pref') + rx_pref = Element('{%s}Rx-Pref' % SYNCML_NAMESPACE) rx_pref.extend((E.CTType(conduit.getPreferedCapabilitieCTType()), E.VerCT(conduit.getPreferedCapabilitieVerCT()))) data_store.append(rx_pref) data_store.extend(rx_element_list) - tx_pref = Element('Tx-Pref') + tx_pref = Element('{%s}Tx-Pref' % SYNCML_NAMESPACE) tx_pref.extend((E.CTType(conduit.getPreferedCapabilitieCTType()), E.VerCT(conduit.getPreferedCapabilitieVerCT()))) data_store.append(tx_pref) @@ -323,7 +325,7 @@ class XMLSyncUtilsMixin(SyncCode): """ Add an object with the SyncML protocol """ - data_node = Element('Data') + data_node = E.Data() if media_type == self.MEDIA_TYPE['TEXT_XML'] and isinstance(xml_string, str): data_node.append(etree.XML(xml_string, parser=parser)) elif media_type == self.MEDIA_TYPE['TEXT_XML'] and \ @@ -346,8 +348,8 @@ class XMLSyncUtilsMixin(SyncCode): ) )) if more_data: - item_node = xml.find('Item') - item_node.append(Element('MoreData')) + item_node = xml.find('{%s}Item' % SYNCML_NAMESPACE) + item_node.append(E.MoreData()) return etree.tostring(xml, encoding='utf-8', pretty_print=True) def deleteXMLObject(self, cmd_id=0, object_gid=None, rid=None): @@ -375,7 +377,7 @@ class XMLSyncUtilsMixin(SyncCode): elem_to_append = E.Target(E.LocURI('%s' % rid)) else: elem_to_append = E.Source(E.LocURI('%s' % gid)) - data_node = Element('Data') + data_node = E.Data() if not isinstance(xml_string, (str, unicode)): data_node.append(xml_string) else: @@ -391,8 +393,8 @@ class XMLSyncUtilsMixin(SyncCode): ) )) if more_data: - item_node = xml.find('Item') - item_node.append(Element('MoreData')) + item_node = xml.find('{%s}Item' % SYNCML_NAMESPACE) + item_node.append(E.MoreData()) return etree.tostring(xml, encoding='utf-8', pretty_print=True) def getXupdateObject(self, object_xml=None, old_xml=None): @@ -422,76 +424,76 @@ class XMLSyncUtilsMixin(SyncCode): """ We will retrieve the session id of the message """ - namespace = self.getNamespace(xml.nsmap) - return int(xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:SessionID)')) + return int(xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:SessionID)', + namespaces=xml.nsmap)) def getMessageIdFromXml(self, xml): """ We will retrieve the message id of the message """ - namespace = self.getNamespace(xml.nsmap) - return int(xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:MsgID)')) + return int(xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:MsgID)', + namespaces=xml.nsmap)) def getTarget(self, xml): """ return the target in the SyncHdr section """ - namespace = self.getNamespace(xml.nsmap) - return '%s' % xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Target/syncml:LocURI)') + return '%s' %\ + xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Target/syncml:LocURI)', + namespaces=xml.nsmap) - def getAlertLastAnchor(self, xml_stream): + def getAlertLastAnchor(self, xml): """ Return the value of the last anchor, in the alert section of the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) - return '%s' % xml_stream.xpath('string(.//syncml:Alert/syncml:Item/syncml:Meta/syncml:Anchor/syncml:Last)') + return '%s' %\ + xml.xpath('string(.//syncml:Alert/syncml:Item/syncml:Meta/syncml:Anchor/syncml:Last)', + namespaces=xml.nsmap) - def getAlertNextAnchor(self, xml_stream): + def getAlertNextAnchor(self, xml): """ Return the value of the next anchor, in the alert section of the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) return '%s' %\ - xml_stream.xpath('string(.//syncml:Alert/syncml:Item/syncml:Meta/syncml:Anchor/syncml:Next)') + xml.xpath('string(.//syncml:Alert/syncml:Item/syncml:Meta/syncml:Anchor/syncml:Next)', + namespaces=xml.nsmap) def getSourceURI(self, xml): """ return the source uri of the data base """ - namespace = self.getNamespace(xml.nsmap) return '%s' %\ - xml.xpath('string(//syncml:SyncBody/syncml:Alert/syncml:Item/syncml:Source/syncml:LocURI)') + xml.xpath('string(//syncml:SyncBody/syncml:Alert/syncml:Item/syncml:Source/syncml:LocURI)', + namespaces=xml.nsmap) def getTargetURI(self, xml): """ return the target uri of the data base """ - namespace = self.getNamespace(xml.nsmap) return '%s' %\ - xml.xpath('string(//syncml:SyncBody/syncml:Alert/syncml:Item/syncml:Target/syncml:LocURI)') + xml.xpath('string(//syncml:SyncBody/syncml:Alert/syncml:Item/syncml:Target/syncml:LocURI)', + namespaces=xml.nsmap) def getSubscriptionUrlFromXML(self, xml): """ return the source URI of the syncml header """ - namespace = self.getNamespace(xml.nsmap) - return '%s' % xml.xpath('string(//syncml:SyncHdr/syncml:Source/syncml:LocURI)') + return '%s' % xml.xpath('string(//syncml:SyncHdr/syncml:Source/syncml:LocURI)', + namespaces=xml.nsmap) def getStatusTarget(self, xml): """ Return the value of the alert code inside the xml_stream """ - namespace = self.getNamespace(xml.nsmap) - return '%s' % xml.xpath('string(syncml:TargetRef)') + return '%s' % xml.xpath('string(syncml:TargetRef)', namespaces=xml.nsmap) def getStatusCode(self, xml): """ Return the value of the alert code inside the xml_stream """ - namespace = self.getNamespace(xml.nsmap) - status_code = '%s' % xml.xpath('string(syncml:Data)') + status_code = '%s' % xml.xpath('string(syncml:Data)', namespaces=xml.nsmap) if status_code: return int(status_code) return None @@ -500,173 +502,175 @@ class XMLSyncUtilsMixin(SyncCode): """ Return the value of the command inside the xml_stream """ - namespace = self.getNamespace(xml.nsmap) cmd = None if xml.xpath('local-name()') == 'Status': - cmd = '%s' % xml.xpath('string(syncml:Cmd)') + cmd = '%s' % xml.xpath('string(syncml:Cmd)', namespaces=xml.nsmap) return cmd def getCred(self, xml): """ return the credential information : type, format and data """ - namespace = self.getNamespace(xml.nsmap) format = '%s' %\ - xml.xpath("string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred/syncml:Meta/*[local-name() = 'Format'])") + xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred/syncml:Meta/*[local-name() = "Format"])', + namespaces=xml.nsmap) type = '%s' %\ - xml.xpath("string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred/syncml:Meta/*[local-name() = 'Type'])") - data = '%s' % xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred/syncml:Data)') + xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred/syncml:Meta/*[local-name() = "Type"])', + namespaces=xml.nsmap) + data = '%s' % xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred/syncml:Data)', + namespaces=xml.nsmap) return (format, type, data) - def checkCred(self, xml_stream): + def checkCred(self, xml): """ Check if there's a Cred section in the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) - return bool(xml_stream.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred)')) + return bool(xml.xpath('string(/syncml:SyncML/syncml:SyncHdr/syncml:Cred)', namespaces=xml.nsmap)) def getChal(self, xml): """ return the chalenge information : format and type """ - format = '%s' % xml.xpath("string(//*[local-name() = 'Format'])") - type = '%s' % xml.xpath("string(//*[local-name() = 'Type'])") + format = '%s' % xml.xpath('string(//*[local-name() = "Format"])', namespaces=xml.nsmap) + type = '%s' % xml.xpath('string(//*[local-name() = "Type"])', namespaces=xml.nsmap) return (format, type) - def checkChal(self, xml_stream): + def checkChal(self, xml): """ Check if there's a Chal section in the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) - return\ - bool(xml_stream.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Status/syncml:Chal)')) + return bool(xml.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Status/syncml:Chal)', + namespaces=xml.nsmap)) - def checkMap(self, xml_stream): + def checkMap(self, xml): """ Check if there's a Map section in the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) - return bool(xml_stream.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Map)')) + return bool(xml.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Map)', namespaces=xml.nsmap)) - def setRidWithMap(self, xml_stream, subscriber): + def setRidWithMap(self, xml, subscriber): """ get all the local objects of the given target id and set them the rid with the given source id (in the Map section) """ - namespace = self.getNamespace(xml_stream.nsmap) - item_list = xml_stream.xpath('/syncml:SyncML/syncml:SyncBody/syncml:Map/syncml:MapItem') + item_list = xml.xpath('/syncml:SyncML/syncml:SyncBody/syncml:Map/syncml:MapItem', + namespaces=xml.nsmap) for map_item in item_list: - gid = '%s' % map_item.xpath('string(.//syncml:Target/syncml:LocURI)') + gid = '%s' % map_item.xpath('string(.//syncml:Target/syncml:LocURI)', namespaces=xml.nsmap) signature = subscriber.getSignatureFromGid(gid) - rid = '%s' % map_item.xpath('string(.//syncml:Source/syncml:LocURI)') + rid = '%s' % map_item.xpath('string(.//syncml:Source/syncml:LocURI)', namespaces=xml.nsmap) signature.setRid(rid) - def getAlertCodeFromXML(self, xml_stream): + def getAlertCodeFromXML(self, xml): """ Return the value of the alert code inside the full syncml message """ - namespace = self.getNamespace(xml_stream.nsmap) alert_code = '%s' %\ - xml_stream.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Alert/syncml:Data)') + xml.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Alert/syncml:Data)', + namespaces=xml.nsmap) if alert_code: return int(alert_code) else: return None - def checkAlert(self, xml_stream): + def checkAlert(self, xml): """ Check if there's an Alert section in the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) - return bool(xml_stream.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Alert)')) + return bool(xml.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Alert)', + namespaces=xml.nsmap)) - def checkSync(self, xml_stream): + def checkSync(self, xml): """ Check if there's an Sync section in the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) - return bool(xml_stream.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Sync)')) - - def checkFinal(self, xml_stream): + return bool(xml.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Sync)', + namespaces=xml.nsmap)) + + def checkFinal(self, xml): """ Check if there's an Final section in the xml_stream The end sections (inizialisation, modification) have this tag """ - namespace = self.getNamespace(xml_stream.nsmap) - return bool(xml_stream.xpath('/syncml:SyncML/syncml:SyncBody/syncml:Final')) - - def checkStatus(self, xml_stream): + return bool(xml.xpath('/syncml:SyncML/syncml:SyncBody/syncml:Final', + namespaces=xml.nsmap)) + + def checkStatus(self, xml): """ Check if there's a Status section in the xml_stream """ - namespace = self.getNamespace(xml_stream.nsmap) - return bool(xml_stream.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Status)')) + return bool(xml.xpath('string(/syncml:SyncML/syncml:SyncBody/syncml:Status)', + namespaces=xml.nsmap)) - def getSyncActionList(self, xml_stream): + def getSyncActionList(self, xml): """ return the list of the action (could be "add", "replace", "delete"). """ - namespace = self.getNamespace(xml_stream.nsmap) - return xml_stream.xpath('//syncml:Add|//syncml:Delete|//syncml:Replace') + return xml.xpath('//syncml:Add|//syncml:Delete|//syncml:Replace', + namespaces=xml.nsmap) - def getSyncBodyStatusList(self, xml_stream): + def getSyncBodyStatusList(self, xml): """ return the list of dictionary corredponding to the data of each status bloc the data are : cmd, code and source """ - namespace = self.getNamespace(xml_stream.nsmap) status_list = [] - status_node_list = xml_stream.xpath('//syncml:Status') + status_node_list = xml.xpath('//syncml:Status') for status in status_node_list: tmp_dict = {} - tmp_dict['cmd'] = '%s' % status.xpath('string(./syncml:Cmd)') - tmp_dict['code'] = '%s' % status.xpath('string(./syncml:Data)') - tmp_dict['source'] = '%s' % status.xpath('string(./syncml:SourceRef)') - tmp_dict['target'] = '%s' % status.xpath('string(./syncml:TargetRef)') + tmp_dict['cmd'] = '%s' % status.xpath('string(./syncml:Cmd)', + namespaces=xml.nsmap) + tmp_dict['code'] = '%s' % status.xpath('string(./syncml:Data)', + namespaces=xml.nsmap) + tmp_dict['source'] = '%s' % status.xpath('string(./syncml:SourceRef)', + namespaces=xml.nsmap) + tmp_dict['target'] = '%s' % status.xpath('string(./syncml:TargetRef)', + namespaces=xml.nsmap) status_list.append(tmp_dict) return status_list - def getDataText(self, action): + def getDataText(self, xml): """ return the section data in text form, it's usefull for the VCardConduit """ - namespace = self.getNamespace(action.nsmap) - return '%s' % action.xpath('string(.//syncml:Item/syncml:Data)') + return '%s' % xml.xpath('string(.//syncml:Item/syncml:Data)', + namespaces=xml.nsmap) - def getDataSubNode(self, action): + def getDataSubNode(self, xml): """ Return the node starting with <object....> of the action """ - namespace = self.getNamespace(action.nsmap) - object_node_list = action.xpath('.//syncml:Item/syncml:Data/*[1]') + object_node_list = xml.xpath('.//syncml:Item/syncml:Data/*[1]', + namespaces=xml.nsmap) if object_node_list: return object_node_list[0] return None - def getActionId(self, action): + def getActionId(self, xml): """ Return the rid of the object described by the action """ - namespace = self.getNamespace(action.nsmap) - id = '%s' % action.xpath('string(.//syncml:Item/syncml:Source/syncml:LocURI)') + id = '%s' % xml.xpath('string(.//syncml:Item/syncml:Source/syncml:LocURI)', + namespaces=xml.nsmap) if not id: - id = '%s' % action.xpath('string(.//syncml:Item/syncml:Target/syncml:LocURI)') + id = '%s' % xml.xpath('string(.//syncml:Item/syncml:Target/syncml:LocURI)', + namespaces=xml.nsmap) return id - def checkActionMoreData(self, action): + def checkActionMoreData(self, xml): """ Return the rid of the object described by the action """ - namespace = self.getNamespace(action.nsmap) - return bool(action.xpath('.//syncml:Item/syncml:MoreData')) + return bool(xml.xpath('.//syncml:Item/syncml:MoreData', + namespaces=xml.nsmap)) - def getActionType(self, action): + def getActionType(self, xml): """ Return the type of the object described by the action """ - namespace = self.getNamespace(action.nsmap) - return '%s' % action.xpath('string(.//syncml:Meta/syncml:Type)') + return '%s' % xml.xpath('string(.//syncml:Meta/syncml:Type)', + namespaces=xml.nsmap) def cutXML(self, xml_string): """ @@ -675,9 +679,9 @@ class XMLSyncUtilsMixin(SyncCode): line_list = xml_string.split('\n') short_string = '\n'.join(line_list[:self.MAX_LINES]) rest_string = '\n'.join(line_list[self.MAX_LINES:]) - xml_string = etree.Element('Partial') - xml_string.text = etree.CDATA(short_string.decode('utf-8')) - return xml_string, rest_string + xml_tree = E.Partial() + xml_tree.text = etree.CDATA(short_string.decode('utf-8')) + return xml_tree, rest_string def getSyncMLData(self, domain=None, remote_xml=None, cmd_id=0, subscriber=None, xml_confirmation_list=None, conduit=None, @@ -884,11 +888,11 @@ class XMLSyncUtilsMixin(SyncCode): more_data = 1 # Receive the chunk of partial xml short_string = signature.getFirstChunkPdata(self.MAX_LINES) - xml_to_send = etree.Element('Partial') + xml_to_send = E.Partial() xml_to_send.text = etree.CDATA(short_string.decode('utf-8')) status = self.PARTIAL else: - xml_to_send = Element('Partial') + xml_to_send = E.Partial() xml_to_send.text = etree.CDATA(xml_string.decode('utf-8')) signature.setStatus(status) if signature.getAction() == 'Replace': @@ -1275,8 +1279,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin): remote_xml=remote_xml, conduit=conduit, simulate=simulate) - nsmap = {None : self.XHTML_NAMESPACE} - xml = Element('SyncML', nsmap=nsmap) + xml = E.SyncML() # syncml header if domain.domain_type == self.PUB: @@ -1292,7 +1295,8 @@ class XMLSyncUtils(XMLSyncUtilsMixin): domain.getSubscriptionUrl())) # syncml body - sync_body = SubElement(xml, 'SyncBody') + sync_body = E.SyncBody() + xml.append(sync_body) xml_status, cmd_id = self.SyncMLStatus( remote_xml, @@ -1430,9 +1434,8 @@ class XMLSyncUtils(XMLSyncUtilsMixin): if sync_body is None: sync_body = xml_tree.xpath('syncml:SyncBody')[0] if syncml_data_list: - sync_node = SubElement(sync_body, 'Sync') - cmd_id_node = SubElement(sync_node, 'CmdID') - cmd_id_node.text = '%s' % cmd_id_before_getsyncmldata + sync_node = E.Sync(E.CmdID('%s' % cmd_id_before_getsyncmldata)) + sync_body.append(sync_node) target_uri = subscriber.getTargetURI() if target_uri: sync_node.append(E.Target(E.LocURI(target_uri))) @@ -1445,14 +1448,14 @@ class XMLSyncUtils(XMLSyncUtilsMixin): if isinstance(xml_confirmation, str): xml_confirmation = etree.XML(xml_confirmation, parser=parser) sync_body.append(xml_confirmation) - + self.sync_finished = 0 if domain.domain_type == self.PUB: # We always reply # When the publication recieved the response Final and the modification # data is finished so the publication send the tag "Final" if not self.checkSync(remote_xml) and not xml_confirmation_list\ and not syncml_data_list and self.checkFinal(remote_xml): - sync_body.append(Element('Final')) + sync_body.append(E.Final()) self.sync_finished = 1 xml_string = etree.tostring(xml_tree, encoding='utf-8', pretty_print=True) subscriber.setLastSentMessage(xml_string) @@ -1473,7 +1476,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin): # "Final" sent to the publication if not self.checkAlert(remote_xml) and not xml_confirmation_list\ and not syncml_data_list: - sync_body.append(Element('Final')) + sync_body.append(E.Final()) self.sync_finished = 1 xml_string = etree.tostring(xml_tree, encoding='utf-8', pretty_print=True) if not self.sync_finished or not self.checkFinal(remote_xml): @@ -1539,10 +1542,6 @@ class XMLSyncUtils(XMLSyncUtilsMixin): if xml_client is not None: if isinstance(xml_client, (str, unicode)): xml_client = etree.XML(xml_client, parser=parser) - if len(xml_client.nsmap) ==1: - namespace = xml_client.nsmap[None] - else : - namespace = xml_client.nsmap['syncml'] #FIXME to apply a DTD or schema if xml_client.xpath('local-name()') != "SyncML": LOG('PubSync', INFO, 'This is not a SyncML Message') -- 2.30.9