diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 7458f3c..75b9b92 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -354,6 +354,26 @@ class ElementBase(object): """ return self.xml.attrib.get(name, default) + def _getSubText(self, name, default=''): + """ + Return the text contents of a sub element. + + In case the element does not exist, or it has no textual content, + a default value can be returned instead. An empty string is returned + if no other default is supplied. + + Arguments: + name -- The name or XPath expression of the element. + default -- Optional default to return if the element does + not exists. An empty string is returned otherwise. + """ + name = self._fix_ns(name) + stanza = self.xml.find(name) + if stanza is None or stanza.text is None: + return default + else: + return stanza.text + @property def attrib(self): #backwards compatibility return self @@ -449,15 +469,6 @@ class ElementBase(object): return False return True - def _getSubText(self, name): - if '}' not in name: - name = "{%s}%s" % (self.namespace, name) - stanza = self.xml.find(name) - if stanza is None or stanza.text is None: - return '' - else: - return stanza.text - def _setSubText(self, name, attrib={}, text=None): if '}' not in name: name = "{%s}%s" % (self.namespace, name) @@ -490,6 +501,23 @@ class ElementBase(object): def __repr__(self): return self.__str__() + def _fix_ns(self, xpath): + """ + Apply the stanza's namespace to elements in an XPath expression. + + Arguments: + xpath -- The XPath expression to fix with namespaces. + """ + + def fix_ns(name): + """Apply namespace to an element if needed.""" + if "}" in name: + return name + return "{%s}%s" % (self.namespace, name) + + return "/".join(map(fix_ns, xpath.split("/"))) + + #def __del__(self): #prevents garbage collection of reference cycle # if self.parent is not None: # self.parent.xml.remove(self.xml) diff --git a/tests/test_elementbase.py b/tests/test_elementbase.py index 78277af..78cf47d 100644 --- a/tests/test_elementbase.py +++ b/tests/test_elementbase.py @@ -267,5 +267,39 @@ class TestElementBase(SleekTest): self.failUnless(stanza._getAttr('bar', 'c') == 'c', "Incorrect default value returned for an unset XML attribute.") + + def testGetSubText(self): + """Test retrieving the contents of a sub element.""" + + class TestStanza(ElementBase): + name = "foo" + namespace = "foo" + interfaces = set(('bar',)) + + def setBar(self, value): + wrapper = ET.Element("{foo}wrapper") + bar = ET.Element("{foo}bar") + bar.text = value + wrapper.append(bar) + self.xml.append(wrapper) + + def getBar(self): + return self._getSubText("wrapper/bar", default="not found") + + stanza = TestStanza() + self.failUnless(stanza['bar'] == 'not found', + "Default _getSubText value incorrect.") + + stanza['bar'] = 'found' + self.checkStanza(TestStanza, stanza, """ + + + found + + + """) + self.failUnless(stanza['bar'] == 'found', + "_getSubText value incorrect: %s." % stanza['bar']) + suite = unittest.TestLoader().loadTestsFromTestCase(TestElementBase)