summaryrefslogtreecommitdiff
path: root/sleekxmpp/xmlstream/matcher/xpath.py
diff options
context:
space:
mode:
Diffstat (limited to 'sleekxmpp/xmlstream/matcher/xpath.py')
-rw-r--r--sleekxmpp/xmlstream/matcher/xpath.py99
1 files changed, 72 insertions, 27 deletions
diff --git a/sleekxmpp/xmlstream/matcher/xpath.py b/sleekxmpp/xmlstream/matcher/xpath.py
index 7f3d20be..669c9f16 100644
--- a/sleekxmpp/xmlstream/matcher/xpath.py
+++ b/sleekxmpp/xmlstream/matcher/xpath.py
@@ -5,30 +5,75 @@
See the file LICENSE for copying permission.
"""
-from . import base
-from xml.etree import cElementTree
-
-ignore_ns = False
-
-class MatchXPath(base.MatcherBase):
-
- def match(self, xml):
- if hasattr(xml, 'xml'):
- xml = xml.xml
- x = cElementTree.Element('x')
- x.append(xml)
- if not ignore_ns:
- if x.find(self._criteria) is not None:
- return True
- return False
- else:
- criteria = [c.split('}')[-1] for c in self._criteria.split('/')]
- xml = x
- for tag in criteria:
- children = [c.tag.split('}')[-1] for c in xml.getchildren()]
- try:
- idx = children.index(tag)
- except ValueError:
- return False
- xml = xml.getchildren()[idx]
- return True
+
+from sleekxmpp.xmlstream.stanzabase import ET
+from sleekxmpp.xmlstream.matcher.base import MatcherBase
+
+
+# Flag indicating if the builtin XPath matcher should be used, which
+# uses namespaces, or a custom matcher that ignores namespaces.
+# Changing this will affect ALL XPath matchers.
+IGNORE_NS = False
+
+
+class MatchXPath(MatcherBase):
+
+ """
+ The XPath matcher selects stanzas whose XML contents matches a given
+ XPath expression.
+
+ Note that using this matcher may not produce expected behavior when using
+ attribute selectors. For Python 2.6 and 3.1, the ElementTree find method
+ does not support the use of attribute selectors. If you need to support
+ Python 2.6 or 3.1, it might be more useful to use a StanzaPath matcher.
+
+ If the value of IGNORE_NS is set to true, then XPath expressions will
+ be matched without using namespaces.
+
+ Methods:
+ match -- Overrides MatcherBase.match.
+ """
+
+ def match(self, xml):
+ """
+ Compare a stanza's XML contents to an XPath expression.
+
+ If the value of IGNORE_NS is set to true, then XPath expressions
+ will be matched without using namespaces.
+
+ Note that in Python 2.6 and 3.1 the ElementTree find method does
+ not support attribute selectors in the XPath expression.
+
+ Arguments:
+ xml -- The stanza object to compare against.
+ """
+ if hasattr(xml, 'xml'):
+ xml = xml.xml
+ x = ET.Element('x')
+ x.append(xml)
+
+ if not IGNORE_NS:
+ # Use builtin, namespace respecting, XPath matcher.
+ if x.find(self._criteria) is not None:
+ return True
+ return False
+ else:
+ # Remove namespaces from the XPath expression.
+ criteria = []
+ for ns_block in self._criteria.split('{'):
+ criteria.extend(ns_block.split('}')[-1].split('/'))
+
+ # Walk the XPath expression.
+ xml = x
+ for tag in criteria:
+ if not tag:
+ # Skip empty tag name artifacts from the cleanup phase.
+ continue
+
+ children = [c.tag.split('}')[-1] for c in xml.getchildren()]
+ try:
+ index = children.index(tag)
+ except ValueError:
+ return False
+ xml = xml.getchildren()[index]
+ return True