Beispiel #1
0
    def evaluate(self, context):
        """Returns a boolean"""

        rt = Conversions.BooleanValue(self._left.evaluate(context))
        if rt:
            rt = Conversions.BooleanValue(self._right.evaluate(context))
        return rt
Beispiel #2
0
    def evaluate(self, context):
        """Returns a boolean"""
        left = self._left.evaluate(context)
        right = self._right.evaluate(context)

        if isinstance(left, Types.NodesetType) or \
           isinstance(right, Types.NodesetType):
            return _nodeset_compare(self._cmp, left, right)

        # From XPath 1.0 Section 3.4:
        # order for equality expressions when neither is a node-set
        # 1. either is boolean, both are converted as if by boolean()
        # 2. either is number, both are converted as if by number()
        # otherwise, both are converted as if by string()
        if isinstance(left, Types.BooleanType):
            right = Conversions.BooleanValue(right)
        elif isinstance(right, Types.BooleanType):
            left = Conversions.BooleanValue(left)
        elif isinstance(left, Types.NumberType):
            right = Conversions.NumberValue(right)
        elif isinstance(right, Types.NumberType):
            left = Conversions.NumberValue(left)
        else:
            left = Conversions.StringValue(left)
            right = Conversions.StringValue(right)
        return self._cmp(left, right) and boolean.true or boolean.false
Beispiel #3
0
    def check_uniqueness(self, context, nodes):
        '''available in XPath as check-uniqueness'''
        hash = {}

        for n in nodes:
            h = self.nodeUID(n)
            if (hash.has_key(h)):
                return Conversions.BooleanValue(0)
            hash[h] = 1

        return Conversions.BooleanValue(1)
Beispiel #4
0
    def instantiate(self, context, processor, new_level=1):
        context.processorNss = self.namespaces
        context.currentInstruction = self

        if Conversions.BooleanValue(self._test.evaluate(context)):
            for child in self.children:
                child.instantiate(context, processor)

        return
    def test(self,args):
        if not len(args):
            self.outputHandler.display_error("'test' requires atleast one argument")
            return

        expr = string.join(args,',')
        rt = self._select(self.context,expr)
        if rt is None:
            return
        rt = Conversions.BooleanValue(rt)
        self.outputHandler.display_expressionResults(expr,rt)
Beispiel #6
0
def If(context, cond, v1, v2=None):
    """
    If the first argument, when converted to a boolean, is true,
    returns the second argument. Otherwise, returns the third
    argument, or if the third argument is not given, returns an
    empty node-set.
    """
    # contributed by Lars Marius Garshol;
    # originally using namespace URI 'http://garshol.priv.no/symbolic/'
    if Conversions.BooleanValue(cond):
        return v1
    elif v2 is None:
        return []
    else:
        return v2
Beispiel #7
0
    def _xu_if(self, context, element, preserveSpace):
        test = element.getAttributeNS(EMPTY_NAMESPACE, u'test')
        if not test:
            raise XUpdateException(XUpdateException.NO_TEST)

        oldNss = context.processorNss
        context.processorNss = Domlette.GetAllNs(element)

        result = self.evaluateExpression(context, test)
        if Conversions.BooleanValue(result):
            for node in element.childNodes:
                self.visit(context, node, preserveSpace)

        context.processorNss = oldNss
        return
Beispiel #8
0
def If(context, cond, v1, v2=None):
    """
    just like Ft.Xml.XPath.BuiltInExtFunctions.If
    but the then and else parameters are strings that evaluated dynamically 
    thus supporting the short circuit logic you expect from if expressions
    """
    from Ft.Xml.XPath import Conversions
    from rx import raccoon
    queryCache = getattr(context.node.ownerDocument, 'queryCache', None)
    expCache = raccoon.RequestProcessor.expCache
    if Conversions.BooleanValue(cond):
        xpath = Conversions.StringValue(v1)
        return RxPath.evalXPath(xpath, context, expCache, queryCache)
    elif v2 is None:
        return []
    else:
        xpath = Conversions.StringValue(v2)
        return RxPath.evalXPath(xpath, context, expCache, queryCache)
Beispiel #9
0
    def instantiate(self, context, processor):

        chosen = None
        for child in self.children:
            context.processorNss = child.namespaces
            context.currentInstruction = child
            if isinstance(child, WhenElement):
                if Conversions.BooleanValue(child._test.evaluate(context)):
                    chosen = child
                    break
            else:
                # xsl:otherwise
                chosen = child

        if chosen:
            for child in chosen.children:
                child.instantiate(context, processor)

        return
Beispiel #10
0
def EncodeUri(context, uri, escapeReserved, encoding=u'UTF-8'):
    """
    The str:encode-uri function percent-encodes a string for embedding in a URI.
    The second argument is a boolean indicating whether to escape reserved characters;
    if true, the given string can be a URI already, with just some of its characters
    needing to be escaped (not recommended, but users who don't understand the nuances
    of the URI syntax tend to prefer it over assembling a URI piece-by-piece).
    """
    uri = Conversions.StringValue(uri)
    escape_reserved = Conversions.BooleanValue(escapeReserved)
    encoding = Conversions.StringValue(encoding)

    try:
        encoder = codecs.lookup(encoding)[0]
    except LookupError:
        return u''

    # The "%" is escaped only if it is not followed by two hexadecimal digits.
    uri = re.sub('%(?![0-9A-Fa-f]{2})', u'%25', uri)

    safe = _unreserved
    if not escape_reserved:
        safe += _reserved

    res = list(uri)
    for i in xrange(len(res)):
        c = res[i]
        if c not in safe:
            try:
                if ord(c) > 127:
                    encoded = encoder(c, 'strict')[0]
                else:
                    encoded = chr(ord(c))
            except UnicodeError:
                # Not valid in this encoding
                encoded = '%3F'
            else:
                # The Unicode character could map to multiple bytes
                encoded = u''.join(['%%%02X' % ord(c) for c in encoded])
            res[i] = encoded
    return u''.join(res)
Beispiel #11
0
def _nodeset_compare(compare, a, b, relational=False):
    """
    Applies a comparison function to node-sets a and b
    in order to evaluate equality (=, !=) and relational (<, <=, >=, >)
    expressions in which both objects to be compared are node-sets.

    Returns an XPath boolean indicating the result of the comparison.
    """
    if isinstance(a, Types.NodesetType) and isinstance(b, Types.NodesetType):
        # From XPath 1.0 Section 3.4:
        # If both objects to be compared are node-sets, then the comparison
        # will be true if and only if there is a node in the first node-set
        # and a node in the second node-set such that the result of
        # performing the comparison on the string-values of the two nodes
        # is true.
        if not (a and b):
            # One of the two node-sets is empty.  In this case, according to
            # section 3.4 of the XPath rec, no node exists in one of the two
            # sets to compare, so *any* comparison must be false.
            return boolean.false

        # If it is a relational comparison, the actual comparison is done on
        # the string value of each of the nodes. This means that the values
        # are then converted to numbers for comparison.
        if relational:
            # NumberValue internally coerces a node to a string before
            # converting it to a number, so the "convert to string" clause
            # is handled.
            coerce = Conversions.NumberValue
        else:
            coerce = Conversions.StringValue

        # Convert the nodesets into lists of the converted values.
        a = map(coerce, a)
        b = map(coerce, b)
        # Now compare the items; if any compare True, we're done.
        for left in a:
            for right in b:
                if compare(left, right):
                    return boolean.true
        return boolean.false

    # From XPath 1.0 Section 3.4:
    # If one object to be compared is a node-set and the other is a number,
    # then the comparison will be true if and only if there is a node in the
    # node-set such that the result of performing the comparison on the
    # number to be compared and on the result of converting the string-value
    # of that node to a number using the number function is true. If one
    # object to be compared is a node-set and the other is a string, then the
    # comparison will be true if and only if there is a node in the node-set
    # such that the result of performing the comparison on the string-value
    # of the node and the other string is true. If one object to be compared
    # is a node-set and the other is a boolean, then the comparison will be
    # true if and only if the result of performing the comparison on the
    # boolean and on the result of converting the node-set to a boolean using
    # the boolean function is true.
    #
    # (In other words, coerce each node to the same type as the other operand,
    # then compare them. Note, however, that relational comparisons convert
    # their operands to numbers.)
    if isinstance(a, Types.NodesetType):
        # a is nodeset
        if isinstance(b, Types.BooleanType):
            a = Conversions.BooleanValue(a)
            return compare(a, b) and boolean.true or boolean.false
        elif relational:
            b = Conversions.NumberValue(b)
            coerce = Conversions.NumberValue
        elif isinstance(b, Types.NumberType):
            coerce = Conversions.NumberValue
        else:
            b = Conversions.StringValue(b)
            coerce = Conversions.StringValue
        for node in a:
            if compare(coerce(node), b):
                return boolean.true
    else:
        # b is nodeset
        if isinstance(a, Types.BooleanType):
            b = Conversions.BooleanValue(b)
            return compare(a, b) and boolean.true or boolean.false
        elif relational:
            a = Conversions.NumberValue(a)
            coerce = Conversions.NumberValue
        elif isinstance(a, Types.NumberType):
            coerce = Conversions.NumberValue
        else:
            a = Conversions.StringValue(a)
            coerce = Conversions.StringValue
        for node in b:
            if compare(a, coerce(node)):
                return boolean.true

    return boolean.false
Beispiel #12
0
def Not(context, object_):
    """Function: <boolean> not(<boolean>)"""
    return ((not Conversions.BooleanValue(object_) and boolean.true)
            or boolean.false)
Beispiel #13
0
def Boolean(context, object_):
    """Function: <boolean> boolean(<object>)"""
    return Conversions.BooleanValue(object_)
def Test(tester):

    tester.startGroup('Node Tests')

    tester.startTest('Creating test environment')
    from Ft.Xml.XPath.ParsedNodeTest import ParsedNodeTest, ParsedNameTest
    from Ft.Xml.XPath import Context, Conversions
    from Ft.Lib.boolean import true, false

    DomTree = tester.test_data['tree']

    context = Context.Context(DomTree.ROOT, 1, 1, {},
                              {'bar': 'http://foo.com'})
    tests = [
        (ParsedNameTest('*'), [(DomTree.ROOT, true)]),
        (ParsedNameTest('bar:CHILD3'), [
            (DomTree.ROOT, false),
            (DomTree.CHILD1, false),
            (DomTree.CHILD3, true),
        ]),
        (ParsedNameTest('bar:*'), [
            (DomTree.ROOT, false),
            (DomTree.CHILD1, false),
            (DomTree.CHILD3, true),
        ]),
        (ParsedNodeTest('node'), [
            (DomTree.ROOT, true),
            (DomTree.TEXT1, true),
        ]),
        (ParsedNodeTest('text'), [
            (DomTree.ROOT, false),
            (DomTree.TEXT1, true),
        ]),
        (ParsedNodeTest('comment'), [
            (DomTree.ROOT, false),
            (DomTree.COMMENT, true),
        ]),
        (ParsedNodeTest('processing-instruction'), [
            (DomTree.ROOT, false),
            (DomTree.PI, true),
        ]),
        (ParsedNodeTest('processing-instruction', "'xml-stylesheet'"), [
            (DomTree.PI, true),
            (DomTree.PI2, false),
        ]),
    ]

    tester.testDone()

    for nt, nodeTests in tests:
        tester.startTest('Running %s' % repr(nt))
        for node, expected in nodeTests:
            # Use Booleans for display only
            result = Conversions.BooleanValue(nt.match(context, node))
            tester.compare(
                expected, result, 'Filter of "%s" against %s' % (
                    repr(nt),
                    node.nodeName,
                ))
        tester.testDone()

    return tester.groupDone()
Beispiel #15
0
                        context = self.visit(context, child, 1)
                #Conditional statements are not part of the XUpdate spec,
                #though it has provisions for them because the spec is
                #not so much use without them
                #xupdate:if is a common-sense 4Suite extension
                elif node.localName == 'if':
                    test = node.getAttributeNS(EMPTY_NAMESPACE, u'test')
                    if not test:
                        raise XUpdateException(XUpdateException.NO_TEST)
                    #print >>sys.stderr, 'test', test
                    test = self.parseExpression(test)

                    oldNss = context.processorNss
                    context.processorNss = Domlette.GetAllNs(node)

                    if Conversions.BooleanValue(test.evaluate(context)):
                        for n in node.childNodes:
                            self.visit(context, n, preserveSpace)

                    context.processorNss = oldNss
                elif node.localName == 'variable':
                    name = node.getAttributeNS(EMPTY_NAMESPACE, 'name')
                    if not name:
                        raise XUpdateException(XUpdateException.NO_NAME)
                    _name = self.parseAVT(name)

                    oldNss = context.processorNss
                    context.processorNss = Domlette.GetAllNs(node)
                    name = _name.evaluate(context)

                    (prefix, local) = SplitQName(name)