Updated ElementBase.match to respect namespaces with slashes.

Required adding option to _fix_ns to not propagate namespaces to child elements.
This commit is contained in:
Lance Stout 2010-08-30 14:55:30 -04:00
parent f5ae27da4f
commit 9c62bce206
2 changed files with 23 additions and 11 deletions

View file

@ -586,7 +586,8 @@ class ElementBase(object):
string or a list of element names with attribute checks. string or a list of element names with attribute checks.
""" """
if isinstance(xpath, str): 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. # Extract the tag name and attribute checks for the first XPath node.
components = xpath[0].split('@') components = xpath[0].split('@')
@ -754,15 +755,20 @@ class ElementBase(object):
""" """
return self 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. Apply the stanza's namespace to elements in an XPath expression.
Arguments: Arguments:
xpath -- The XPath expression to fix with namespaces. xpath -- The XPath expression to fix with namespaces.
split -- Indicates if the fixed XPath should be left as a split -- Indicates if the fixed XPath should be left as a
list of element names with namespaces. Defaults to list of element names with namespaces. Defaults to
False, which returns a flat string path. 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 = [] fixed = []
# Split the XPath into a series of blocks, where a block # Split the XPath into a series of blocks, where a block
@ -774,17 +780,23 @@ class ElementBase(object):
# that do not have namespaces. # that do not have namespaces.
namespace = ns_block.split('}')[0] namespace = ns_block.split('}')[0]
elements = ns_block.split('}')[1].split('/') elements = ns_block.split('}')[1].split('/')
else: elif use_ns:
# Apply the stanza's namespace to the following # Apply the stanza's namespace to the following
# elements since no namespace was provided. # elements since no namespace was provided.
namespace = self.namespace namespace = self.namespace
elements = ns_block.split('/') elements = ns_block.split('/')
else:
# We don't want to propagate namespaces.
elements = ns_block.split('/')
for element in elements: for element in elements:
if element: if element:
# Skip empty entry artifacts from splitting. # Skip empty entry artifacts from splitting.
fixed.append('{%s}%s' % (namespace, if use_ns:
element)) tag = '{%s}%s' % (namespace, element)
else:
tag = element
fixed.append(tag)
if split: if split:
return fixed return fixed
return '/'.join(fixed) return '/'.join(fixed)

View file

@ -459,7 +459,7 @@ class TestElementBase(SleekTest):
class TestStanzaPlugin(ElementBase): class TestStanzaPlugin(ElementBase):
name = "plugin" name = "plugin"
namespace = "bar" namespace = "http://test/slash/bar"
interfaces = set(('attrib',)) interfaces = set(('attrib',))
registerStanzaPlugin(TestStanza, TestStanzaPlugin) registerStanzaPlugin(TestStanza, TestStanzaPlugin)
@ -483,7 +483,7 @@ class TestElementBase(SleekTest):
self.failUnless(stanza.match("foo/plugin@attrib=c"), self.failUnless(stanza.match("foo/plugin@attrib=c"),
"Stanza did not match with plugin and attribute.") "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.") "Stanza did not match with namespaced plugin.")
substanza = TestSubStanza() substanza = TestSubStanza()