From 9c62bce2060e30e41c3710587f6bd9992625b245 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 30 Aug 2010 14:55:30 -0400 Subject: [PATCH] Updated ElementBase.match to respect namespaces with slashes. Required adding option to _fix_ns to not propagate namespaces to child elements. --- sleekxmpp/xmlstream/stanzabase.py | 30 +++++++++++++++++++++--------- tests/test_elementbase.py | 4 ++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index d7c7c7b..8f4874c 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -586,7 +586,8 @@ class ElementBase(object): string or a list of element names with attribute checks. """ if isinstance(xpath, str): - xpath = xpath.split('/') + xpath = self._fix_ns(xpath, split=True, propagate_ns=False) + # Extract the tag name and attribute checks for the first XPath node. components = xpath[0].split('@') @@ -754,15 +755,20 @@ class ElementBase(object): """ return self - def _fix_ns(self, xpath, split=False): + def _fix_ns(self, xpath, split=False, propagate_ns=True): """ Apply the stanza's namespace to elements in an XPath expression. Arguments: - xpath -- The XPath expression to fix with namespaces. - split -- Indicates if the fixed XPath should be left as a - list of element names with namespaces. Defaults to - False, which returns a flat string path. + xpath -- The XPath expression to fix with namespaces. + split -- Indicates if the fixed XPath should be left as a + list of element names with namespaces. Defaults to + False, which returns a flat string path. + propagate_ns -- Overrides propagating parent element namespaces + to child elements. Useful if you wish to simply + split an XPath that has non-specified namespaces, + and child and parent namespaces are known not to + always match. Defaults to True. """ fixed = [] # Split the XPath into a series of blocks, where a block @@ -774,17 +780,23 @@ class ElementBase(object): # that do not have namespaces. namespace = ns_block.split('}')[0] elements = ns_block.split('}')[1].split('/') - else: + elif use_ns: # Apply the stanza's namespace to the following # elements since no namespace was provided. namespace = self.namespace elements = ns_block.split('/') + else: + # We don't want to propagate namespaces. + elements = ns_block.split('/') for element in elements: if element: # Skip empty entry artifacts from splitting. - fixed.append('{%s}%s' % (namespace, - element)) + if use_ns: + tag = '{%s}%s' % (namespace, element) + else: + tag = element + fixed.append(tag) if split: return fixed return '/'.join(fixed) diff --git a/tests/test_elementbase.py b/tests/test_elementbase.py index b6d7c6f..8898b3f 100644 --- a/tests/test_elementbase.py +++ b/tests/test_elementbase.py @@ -459,7 +459,7 @@ class TestElementBase(SleekTest): class TestStanzaPlugin(ElementBase): name = "plugin" - namespace = "bar" + namespace = "http://test/slash/bar" interfaces = set(('attrib',)) registerStanzaPlugin(TestStanza, TestStanzaPlugin) @@ -483,7 +483,7 @@ class TestElementBase(SleekTest): self.failUnless(stanza.match("foo/plugin@attrib=c"), "Stanza did not match with plugin and attribute.") - self.failUnless(stanza.match("foo/{bar}plugin"), + self.failUnless(stanza.match("foo/{http://test/slash/bar}plugin"), "Stanza did not match with namespaced plugin.") substanza = TestSubStanza()