From b0a2a305028bf284fc5dcf7e1a696d85787f128f Mon Sep 17 00:00:00 2001 From: Thibaut Horel Date: Mon, 8 Nov 2010 00:59:14 +0100 Subject: Add the sleekxmpp library (will be added as a submodule later) --- sleekxmpp/xmlstream/matcher/xpath.py | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 sleekxmpp/xmlstream/matcher/xpath.py (limited to 'sleekxmpp/xmlstream/matcher/xpath.py') diff --git a/sleekxmpp/xmlstream/matcher/xpath.py b/sleekxmpp/xmlstream/matcher/xpath.py new file mode 100644 index 0000000..669c9f1 --- /dev/null +++ b/sleekxmpp/xmlstream/matcher/xpath.py @@ -0,0 +1,79 @@ +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2010 Nathanael C. Fritz + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +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 -- cgit v1.2.3-70-g09d2