changeset 534:cccb6c748609

Add XPath `matches()` function which, of course, supports the Python regular expression sytax.
author athomas
date Sun, 24 Jun 2007 08:10:47 +0000
parents dfb45908fadc
children c8806216aec4
files genshi/path.py genshi/tests/path.py
diffstat 2 files changed, 34 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/path.py
+++ b/genshi/path.py
@@ -755,6 +755,27 @@
     def __repr__(self):
         return 'contains(%r, %r)' % (self.string1, self.string2)
 
+class MatchesFunction(Function):
+    """The `matches` function, which returns whether a string matches a regular
+    expression.
+    """
+    __slots__ = ['string1', 'string2']
+    flag_mapping = {'s': re.S, 'm': re.M, 'i': re.I, 'x': re.X}
+
+    def __init__(self, string1, string2, flags=''):
+        self.string1 = string1
+        self.string2 = string2
+        self.flags = self._map_flags(flags)
+    def __call__(self, kind, data, pos, namespaces, variables):
+        string1 = as_string(self.string1(kind, data, pos, namespaces, variables))
+        string2 = as_string(self.string2(kind, data, pos, namespaces, variables))
+        return re.search(string2, string1, self.flags)
+    def _map_flags(self, flags):
+        return reduce(lambda a, b: a | b,
+                      [self.flag_map[flag] for flag in flags], re.U)
+    def __repr__(self):
+        return 'contains(%r, %r)' % (self.string1, self.string2)
+
 class FalseFunction(Function):
     """The `false` function, which always returns the boolean `false` value."""
     __slots__ = []
@@ -977,17 +998,16 @@
 
 _function_map = {'boolean': BooleanFunction, 'ceiling': CeilingFunction,
                  'concat': ConcatFunction, 'contains': ContainsFunction,
-                 'false': FalseFunction, 'floor': FloorFunction,
-                 'local-name': LocalNameFunction, 'name': NameFunction,
-                 'namespace-uri': NamespaceUriFunction,
+                 'matches': MatchesFunction, 'false': FalseFunction, 'floor':
+                 FloorFunction, 'local-name': LocalNameFunction, 'name':
+                 NameFunction, 'namespace-uri': NamespaceUriFunction,
                  'normalize-space': NormalizeSpaceFunction, 'not': NotFunction,
                  'number': NumberFunction, 'round': RoundFunction,
-                 'starts-with': StartsWithFunction,
-                 'string-length': StringLengthFunction,
-                 'substring': SubstringFunction,
-                 'substring-after': SubstringAfterFunction,
-                 'substring-before': SubstringBeforeFunction,
-                 'translate': TranslateFunction, 'true': TrueFunction}
+                 'starts-with': StartsWithFunction, 'string-length':
+                 StringLengthFunction, 'substring': SubstringFunction,
+                 'substring-after': SubstringAfterFunction, 'substring-before':
+                 SubstringBeforeFunction, 'translate': TranslateFunction,
+                 'true': TrueFunction}
 
 # Literals & Variables
 
--- a/genshi/tests/path.py
+++ b/genshi/tests/path.py
@@ -328,6 +328,11 @@
         path = Path('*[contains(name(), "oo")]')
         self.assertEqual('<foo>bar</foo>', path.select(xml).render())
 
+    def test_predicate_matches_function(self):
+        xml = XML('<root><foo>bar</foo><bar>foo</bar></root>')
+        path = Path('*[matches(name(), "foo|bar")]')
+        self.assertEqual('<foo>bar</foo><bar>foo</bar>', path.select(xml).render())
+
     def test_predicate_false_function(self):
         xml = XML('<root><foo>bar</foo></root>')
         path = Path('*[false()]')
Copyright (C) 2012-2017 Edgewall Software