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
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
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)
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)
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
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
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)
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
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)
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
def Not(context, object_): """Function: <boolean> not(<boolean>)""" return ((not Conversions.BooleanValue(object_) and boolean.true) or boolean.false)
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()
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)