def Test(tester): tester.startGroup('Node-set Expressions') tester.startTest('Creating test environment') from Ft.Xml.XPath import ParsedExpr from Ft.Xml.XPath import ParsedPredicateList DomTree = tester.test_data['tree'] import DummyExpr from DummyExpr import boolT, boolF from DummyExpr import num3, numN4, num4p5 from DummyExpr import strPi, strText nodeset0 = DummyExpr.DummyNodeSetExpr([]) nodeset1 = DummyExpr.DummyNodeSetExpr([DomTree.ROOT]) nodeset2 = DummyExpr.DummyNodeSetExpr([DomTree.ROOT, DomTree.CHILD1]) nodeset3 = DummyExpr.DummyNodeSetExpr([DomTree.CHILD1]) nodeset4 = DummyExpr.DummyNodeSetExpr([DomTree.CHILD3]) from Ft.Xml.XPath import Context context1 = Context.Context(DomTree.CHILD1,1,2) context2 = Context.Context(DomTree.CHILD2,2,2) plT = ParsedPredicateList.ParsedPredicateList([boolT]) plF = ParsedPredicateList.ParsedPredicateList([boolF]) tests = {ParsedExpr.ParsedFilterExpr : [((nodeset2, plT), context1, list(nodeset2.val)), ((nodeset2, plF), context1, []), ], ParsedExpr.ParsedPathExpr : [((0, nodeset2, nodeset1), context1, list(nodeset1.val)), ], ParsedExpr.ParsedUnionExpr : [((nodeset2, nodeset1), context1, list(nodeset2.val)), ], } tester.testDone() for (expr, boolTests) in tests.items(): for (args, context, expected) in boolTests: p = apply(expr, args) tester.startTest('Comparing %s' % repr(p)) result = p.evaluate(context) tester.compare(result, expected) tester.testDone() tester.groupDone()
def Test(tester): tester.startGroup('Location path expressions') tester.startTest('Creating test environment') from Ft.Xml.XPath.ParsedAbbreviatedAbsoluteLocationPath import ParsedAbbreviatedAbsoluteLocationPath from Ft.Xml.XPath.ParsedAbbreviatedRelativeLocationPath import ParsedAbbreviatedRelativeLocationPath from Ft.Xml.XPath.ParsedAbsoluteLocationPath import ParsedAbsoluteLocationPath from Ft.Xml.XPath.ParsedRelativeLocationPath import ParsedRelativeLocationPath from Ft.Xml.XPath import ParsedStep from Ft.Xml.XPath import ParsedNodeTest from Ft.Xml.XPath import ParsedAxisSpecifier from Ft.Xml.XPath import Context DomTree = tester.test_data['tree'] nt = ParsedNodeTest.ParsedNameTest('*') as = ParsedAxisSpecifier.ParsedAxisSpecifier('child') step = ParsedStep.ParsedStep(as,nt,None) # [(expression, context, expected)...] tests = [(ParsedAbbreviatedAbsoluteLocationPath(step), Context.Context(DomTree.CHILD2, 1, 1), # all element children [DomTree.ROOT, DomTree.CHILD1] + DomTree.GCHILDREN1 + [DomTree.CHILD2] + DomTree.GCHILDREN2 + [DomTree.CHILD3] + [DomTree.LANG] + DomTree.LCHILDREN), (ParsedAbbreviatedRelativeLocationPath(step, step), Context.Context(DomTree.ROOT, 1, 1), # all element grand children DomTree.GCHILDREN1 + DomTree.GCHILDREN2 + DomTree.LCHILDREN), (ParsedAbsoluteLocationPath(None), Context.Context(DomTree.CHILD1, 1, 1), [DomTree.DOM]), (ParsedAbsoluteLocationPath(step), Context.Context(DomTree.CHILD1, 1, 1), [DomTree.ROOT]), (ParsedRelativeLocationPath(step, step), Context.Context(DomTree.ROOT, 1, 1), DomTree.GCHILDREN1 + DomTree.GCHILDREN2 + DomTree.LCHILDREN), ] tester.testDone() for (location, context, expected) in tests: tester.startTest(repr(location)) actual = location.select(context) tester.compare(expected, actual) tester.testDone() return tester.groupDone()
def Test(tester): tester.startGroup('Exercise namespace nodes') isrc = InputSource.DefaultFactory.fromString(SRC_1, Uri.OsPathToUri(os.getcwd())) doc = NonvalidatingReader.parse(isrc) con = Context.Context(doc, 1, 1) EXPR = '//namespace::node()' expr = Compile(EXPR) #expr is <AbbreviatedAbsoluteLocationPath: /descendant-or-self::node()/namespace::node()> #expr._rel is <Step: namespace::node()> #expr._step is <Step: descendant-or-self::node()> tester.startTest(EXPR) actual = expr.evaluate(con) tester.compare(7, len(actual)) tester.testDone() EXPR = '//node()/namespace::node()' expr = Compile(EXPR) tester.startTest(EXPR) EXPECTED = [] actual = expr.evaluate(con) tester.compare(7, len(actual)) tester.testDone() EXPR = '//*/namespace::node()' expr = Compile(EXPR) tester.startTest(EXPR) EXPECTED = [] actual = expr.evaluate(con) tester.compare(7, len(actual)) tester.testDone() EXPR = '/*/*/namespace::node()' expr = Compile(EXPR) tester.startTest(EXPR) EXPECTED = [] actual = expr.evaluate(con) tester.compare(6, len(actual)) tester.testDone() EXPR = '/*/namespace::node()|/*/*/namespace::node()' expr = Compile(EXPR) tester.startTest(EXPR) EXPECTED = [] actual = expr.evaluate(con) tester.compare(7, len(actual)) tester.testDone() EXPR = '//*' expr = Compile(EXPR) #expr is <AbbreviatedAbsoluteLocationPath: /descendant-or-self::node()/child::*> tester.startTest(EXPR) EXPECTED = [] actual = expr.evaluate(con) tester.compare(4, len(actual)) tester.testDone() return tester.groupDone()
def Test(tester): context = Context.Context(tester.test_data['tree'].CHILD1, 1, 3) tester.startGroup('String Literals') tester.startTest('Parse string literal expression tokens') setupStringLiterals() tester.testDone() tester.startGroup('Evaluate parsed string literal expression tokens') global StringLiterals for parsedexpr, expected in StringLiterals.values(): tester.startTest(repr(parsedexpr)) tester.compare(expected, parsedexpr.evaluate(context)) tester.testDone() tester.groupDone() tester.groupDone() tester.startGroup('Number Literals') tester.startTest('Parse numeric literal expression tokens') setupNumberLiterals() tester.testDone() tester.startGroup('Evaluate parsed numeric literal expression tokens') global NumberLiterals for parsedexpr, expected in NumberLiterals.values(): tester.startTest(repr(parsedexpr)) tester.compare(expected, parsedexpr.evaluate(context)) tester.testDone() tester.groupDone() tester.groupDone()
def execute(self, node, xupdate, variables=None, extFunctionMap=None): variables = variables or {} context = Context.Context(node, varBindings=variables, extFunctionMap=extFunctionMap) self.visit(context, xupdate, 0) #xupdate.instantiate(context, self) return node
def execute(self, node, xupdate, variables=None, processorNss=None): if variables is None: variables = {} if processorNss is None: processorNss = {} context = Context.Context(node, varBindings=variables, processorNss=processorNss) self.visit(context, xupdate, 0) return node
def _xu_append(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) child = element.getAttributeNS(EMPTY_NAMESPACE, u'child') or u'last()' oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not isinstance(nodeset, Types.NodesetType) or not nodeset: # Error if not a node-set or empty node-set raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) for refnode in nodeset: self.pushDomResult(refnode.ownerDocument) # A wrapper element is used in case attributes are being added wrapper_localName = 'wrapper' wrapper_namespace = EMPTY_NAMESPACE try: self.writers[-1].startElement(wrapper_localName, wrapper_namespace) for node in element.childNodes: self.visit(context, node, preserveSpace) finally: self.writers[-1].endElement(wrapper_localName, wrapper_namespace) result = self.popResult() size = len(refnode.childNodes) con = Context.Context(refnode, 1, size, processorNss={'xupdate': XUPDATE_NS}) # Python lists is 0-indexed counting, node-sets 1-indexed position = self.evaluateExpression(con, child) position = int(Conversions.NumberValue(position)) wrapper = result.childNodes[0] if wrapper.attributes and hasattr(refnode, 'setAttributeNodeNS'): for attr in wrapper.attributes.values(): refnode.setAttributeNodeNS(attr) # we operate on a shallow copy of the child nodes here to avoid # modifying the membership of the sequence we're interating over. for node in tuple(wrapper.childNodes): if position >= size: refnode.appendChild(node) else: refnode.insertBefore(node, refnode.childNodes[position]) context.processorNss = oldNss return
def Test(tester): tester.startGroup('Predicate List') tester.startTest('Checking syntax') from Ft.Xml.XPath import ParsedPredicateList from Ft.Xml.XPath import ParsedExpr from Ft.Xml.XPath import Context from Ft.Xml.XPath import Evaluate import DummyExpr DomTree = tester.test_data['tree'] tester.testDone() tester.startTest('Creating test environment') t = DummyExpr.DummyBooleanExpr(1) f = DummyExpr.DummyBooleanExpr(0) a = ParsedExpr.ParsedAndExpr(t, f) o = ParsedExpr.ParsedOrExpr(t, f) context = Context.Context(DomTree.ROOT, 1, 1) tester.testDone() p = ParsedPredicateList.ParsedPredicateList([a, t]) tester.startTest('Filter of "%s"' % repr(p)) result = p.filter([context.node], context, 0) tester.compare(0, len(result)) tester.testDone() p = ParsedPredicateList.ParsedPredicateList([o, t]) tester.startTest('Filter of "%s"' % repr(p)) result = p.filter([context.node], context, 0) tester.compare([DomTree.ROOT], result) tester.testDone() dom = Domlette.NonvalidatingReader.parseString(source_1, '.') expected = filter(lambda x: x.nodeType == Node.ELEMENT_NODE, dom.documentElement.childNodes)[-1] tests = [ ("//element[descendant::y[.='z']]", [expected]), ("//element[descendant::y[.='z']][1]", [expected]), ("//element[descendant::y[.='z']][2]", []), ] for (expr, expected) in tests: tester.startTest(expr) actual = Evaluate(expr, contextNode=dom) tester.compare(expected, actual) tester.testDone() return tester.groupDone()
def Test(tester): tester.startGroup('CDATA sections in doc') isrc = InputSource.DefaultFactory.fromString(SRC_1, Uri.OsPathToUri(os.getcwd())) doc = NonvalidatingReader.parse(isrc) con = Context.Context(doc, 1, 1) EXPR = '/doc/elem/text()' expr = Compile(EXPR) tester.startTest(EXPR) actual = [node.data for node in expr.evaluate(con)] tester.compare(actual, ["abc"] * 3) tester.testDone() return tester.groupDone()
def Test(tester): tester.startTest("Evaluate on a HTML Document") if HtmlLib is None: tester.warning("Requires PyXML to be installed") tester.testDone() return xml_dom = HtmlLib.FromHtml(html) p = Ft.Xml.XPath.parser.new() exp = p.parse("/HTML/HEAD") c=Context.Context(xml_dom,0,0) result=exp.evaluate(c) st = cStringIO.StringIO() Print(result[0],st) tester.compare(expected_1,st.getvalue()) tester.testDone()
class sax2dom_chunker(sax.ContentHandler): """ Note: Ignores nodes prior to the document element, such as PIs and text nodes. Collapses CDATA sections into plain text Only designed to work if you set the feature sax.handler.feature_namespaces to 1 on the parser you use. xpatterns - list of XPatterns. Only portions of the tree within these patterns will be instantiated as DOM (as chunks fed to chunk_consumer in sequence) If None (the default, a DOM node will be created representing the entire tree. nss - a dictionary of prefix -> namespace name mappings used to interpret XPatterns chunk_consumer - a callable object taking a DOM node. It will be invoked as each DOM chunk is prepared. domimpl - DOM implemention to build, e.g. mindom (the default) or cDomlette or pxdom (if you have the right third-party packages installed). owner_doc - for advanced uses, if you want to use an existing DOM document object as the owner of all created nodes. """ def __init__( self, xpatterns=None, nss=None, chunk_consumer=None, domimpl=Domlette.implementation, owner_doc=None, ): nss = nss or {} #HINT: To use minidom #domimpl = xml.dom.minidom.getDOMImplementation() self._impl = domimpl if isinstance(xpatterns, str) or isinstance(xpatterns, unicode): xpatterns = [xpatterns] #print xpatterns if owner_doc: self._owner_doc = owner_doc else: try: dt = self._impl.createDocumentType(DUMMY_DOCELEM, None, u'') except AttributeError: #Domlette doesn't need createDocumentType dt = None self._owner_doc = self._impl.createDocument( DUMMY_DOCELEM, DUMMY_DOCELEM, dt) #Create a docfrag to hold all the generated nodes. root_node = self._owner_doc.createDocumentFragment() self._nodeStack = [root_node] self.state_machine = xpattern_state_manager(xpatterns, nss) self._chunk_consumer = chunk_consumer return def get_root_node(self): """ Only useful if the user does not register trim paths If so, then after SAX processing the user can call this method to retrieve resulting DOM representing the entire document """ return self._nodeStack[0] #Overridden ContentHandler methods def startDocument(self): self.state_machine.event(1, None, None) return def endDocument(self): self.state_machine.event(0, None, None) return def startElementNS(self, (ns, local), qname, attribs): self.state_machine.event(1, ns, local) if not self.state_machine.status(): for attrtest in self.state_machine.attribute_tests: e = self._owner_doc.createElementNS(ns, qname or local) for (ns, local), value in attribs.items(): e.setAttributeNS(ns, attribs.getQNameByName((ns, local)), value) #e = dummy_element(qname, attribs, self._nodeStack[0]) matched = attrtest.evaluate(Context.Context(e)) if matched: #Feed the consumer #self._nodeStack[TOP].appendChild(matched[0]) #"xml.dom.HierarchyRequestErr: Ft.Xml.cDomlette.Attr nodes cannot be a child of Ft.Xml.cDomlette.DocumentFragment nodes" self._chunk_consumer(matched[0]) #Start over with new doc frag so old memory can be reclaimed root_node = self._owner_doc.createDocumentFragment() self._nodeStack = [root_node] return new_element = self._owner_doc.createElementNS(ns, qname or local) for (attr_ns, lname) in attribs: value = attribs[(attr_ns, lname)] if attr_ns is not None: attr_qname = attribs.getQNameByName((attr_ns, lname)) else: attr_qname = lname attr = self._owner_doc.createAttributeNS(attr_ns, attr_qname) attr_qname = attribs.getQNameByName((attr_ns, lname)) attr.value = value new_element.setAttributeNodeNS(attr) self._nodeStack.append(new_element) return
def visit(self, context, node, preserveSpace): #FIXME: We should improve this function from this ugly-ass #switch thingie to dynamic dispatch if node.nodeType == Node.ELEMENT_NODE: xml_space = node.getAttributeNS(XML_NAMESPACE, 'space') if xml_space == 'preserve': preserveSpace = 1 elif xml_space == 'default': preserveSpace = 0 # else, no change if node.namespaceURI != XUPDATE_NS: self.writers[-1].startElement(node.nodeName, node.namespaceURI) # Process the attributes oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) for attr in node.attributes.values(): value = self.parseAVT(attr.value) value = value.evaluate(context) self.writers[-1].attribute(attr.nodeName, value, attr.namespaceURI) context.processorNss = oldNss # Now the children for child in node.childNodes: context = self.visit(context, child, preserveSpace) self.writers[-1].endElement(node.nodeName) return context # XUpdate elements try: restoreGraphContext = False graphURI = node.getAttributeNS(EMPTY_NAMESPACE, u'to-graph') if graphURI: graphURI = self.parseAVT(graphURI) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) graphURI = graphURI.evaluate(context) context.processorNss = oldNss context.node.ownerDocument.pushContext(graphURI) restoreGraphContext = True if node.localName == 'modifications': for n in node.childNodes: self.visit(context, n, preserveSpace) elif node.localName == 'remove': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') #import sys #print >>sys.stderr, 'removing', select if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if nodeset: #change from 4Suite -- why did it only delete the first node in the nodeset? #that's not in the spec or very intuitive #refnode = nodeset[0] for refnode in nodeset: if refnode.nodeType == Node.ATTRIBUTE_NODE: parent = refnode.ownerElement parent.removeAttributeNode(refnode) else: parent = refnode.parentNode if parent is None: parent = refnode.ownerDocument parent.removeChild(refnode) context.processorNss = oldNss elif node.localName in ['insert-after', 'insert-before']: select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() if node.localName == 'insert-before': refnode.parentNode.insertBefore(result, refnode) elif node.localName == 'insert-after': # if arg 2 is None, insertBefore behaves like appendChild refnode.parentNode.insertBefore( result, refnode.nextSibling) context.processorNss = oldNss elif node.localName == 'element': name = node.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = node.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.writers[-1].startElement(name, namespace) for child in node.childNodes: context = self.visit(context, child, preserveSpace) self.writers[-1].endElement(name) context.processorNss = oldNss elif node.localName == 'attribute': name = node.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = node.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.pushStringResult() try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() self.writers[-1].attribute(name, result, namespace) context.processorNss = oldNss elif node.localName == 'append': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) child = node.getAttributeNS(EMPTY_NAMESPACE, u'child') or u'last()' _child = self.parseExpression(child) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, select) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() size = len(refnode.childNodes) con = Context.Context(refnode, 1, size, processorNss={'xupdate': XUPDATE_NS}) # Python lists is 0-indexed counting, node-sets 1-indexed position = int( Conversions.NumberValue(_child.evaluate(con))) if position >= size: refnode.appendChild(result) else: refnode.insertBefore(result, refnode.childNodes[position]) context.processorNss = oldNss elif node.localName == 'replace': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() if refnode.nodeType == Node.ATTRIBUTE_NODE: owner = refnode.parentNode owner.removeAttributeNode(refnode) owner.setAttributeNodeNS(result) else: refnode.parentNode.replaceChild(result, refnode) context.processorNss = oldNss elif node.localName == 'update': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) refnode = nodeset[0] if refnode.nodeType == Node.ATTRIBUTE_NODE: self.pushStringResult() try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() refnode.nodeValue = refnode.value = result else: self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() while refnode.firstChild: #print 'remove', id(refnode), id(refnode.firstChild), len(refnode.childNodes) refnode.removeChild(refnode.firstChild) refnode.appendChild(result) context.processorNss = oldNss
def Test(tester): tester.startGroup('Expression Parser') tester.startTest('Creating test environment') from Ft.Xml.XPath import Context DomTree = tester.test_data['tree'] # not the root node, but the document element root = Context.Context(DomTree.ROOT, 1, 1, varBindings={(None, 'foo'): [DomTree.ROOT]}) child1 = Context.Context(DomTree.CHILD1, 1, 2, processorNss={'x': 'http://spam.com'}) child2 = Context.Context(DomTree.CHILD2, 2, 2) child3 = Context.Context(DomTree.CHILD3, 1, 1) text = Context.Context(DomTree.TEXT1, 3, 3) gchild11 = Context.Context(DomTree.GCHILD11, 1, 2) lang = Context.Context(DomTree.LANG, 1, 1) tests = [ ('child::*', root, DomTree.CHILDREN), ('/child::*', child1, [DomTree.ROOT]), ('/*/*', child1, DomTree.CHILDREN), ('/child::*/*/child::GCHILD', child1, DomTree.GCHILDREN1 + DomTree.GCHILDREN2), ('//*', child1, ([DomTree.ROOT, DomTree.CHILD1] + DomTree.GCHILDREN1 + [DomTree.CHILD2] + DomTree.GCHILDREN2 + [DomTree.CHILD3] + [DomTree.LANG] + DomTree.LCHILDREN)), ('//GCHILD', child1, DomTree.GCHILDREN1 + DomTree.GCHILDREN2), ('//@attr1', child1, [DomTree.ATTR1, DomTree.ATTR2]), ('x:GCHILD', child1, []), ('.//GCHILD', child2, DomTree.GCHILDREN2), ('.//GCHILD', root, DomTree.GCHILDREN1 + DomTree.GCHILDREN2), ('/', text, [DomTree.DOM]), ('//CHILD1/..', child1, [DomTree.ROOT]), ('.//foo:*', child3, []), ('CHILD1 | CHILD2', root, [DomTree.CHILD1, DomTree.CHILD2]), ('descendant::GCHILD[3]', root, [DomTree.GCHILD21]), ('descendant::GCHILD[parent::CHILD1]', root, DomTree.GCHILDREN1), ('descendant::GCHILD[position() > 1]', root, [DomTree.GCHILD12] + DomTree.GCHILDREN2), ('@attr1[.="val1"]', child1, [DomTree.ATTR1]), ('1', root, 1), ('00200', root, 200), ('3+4*7', root, 31), ('3-4*1', root, -1), ("string('1')", root, u"1"), ("concat('1', '2')", root, u"12"), ("true()", root, boolean.true), ("false()", root, boolean.false), ("1=3<4", root, boolean.true), ("1 or 2 and 3", root, boolean.true), ("1 and 2 = 3", root, boolean.false), ('-1 or 2', root, boolean.true), ('. or *', root, boolean.true), ("$foo[1]", root, [DomTree.ROOT]), ("text()", child3, []), ("processing-instruction('f')", root, []), ("$foo[1]/bar", root, []), ("$foo[1]//bar", root, []), ("$foo[1][3]", root, []), ('(child::*)', root, DomTree.CHILDREN), ('. * 0', root, nan), ('.. * 0', root, nan), ('/.. * 0', root, nan), ('CHILD2/@CODE', root, [DomTree.IDATTR2]), ('CHILD2/@CODE * 0', root, 0), (u'f\xf6\xf8', lang, [DomTree.NONASCIIQNAME]), ] tester.testDone() for (expr_str, context, expected) in tests: fromHere = context.node.nodeName tester.startTest('Evaluation of %r' % expr_str) message = 'Error while evaluating "%r" from <%r>' % (expr_str, fromHere) for factory in _parsers: parser = factory.new() try: parsed_expr = parser.parse(expr_str) except: tester.error('Error while parsing "%r"' % expr_str, traceLimit=None) node_set = parsed_expr.evaluate(context) tester.compare(expected, node_set, message) tester.testDone() tester.startTest("Syntax Exception") for factory in _parsers: parser = factory.new() tester.testException(parser.parse, ("\\", ), SyntaxError) tester.testDone() tester.startTest("Compiletime Exception") tester.testException(Compile, ("\\", ), CompiletimeException) tester.testDone() tester.startTest("Runtime Exception") tester.testException(Evaluate, ("$foo", DomTree.ROOT), RuntimeException) tester.testDone() return tester.groupDone()
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()
def Test(tester): tester.startGroup('Steps') tester.startTest('Checking syntax') DomTree = tester.test_data['tree'] from Ft.Xml.XPath import ParsedStep from Ft.Xml.XPath import ParsedNodeTest from Ft.Xml.XPath import ParsedExpr from Ft.Xml.XPath import ParsedPredicateList from Ft.Xml.XPath import ParsedAxisSpecifier from Ft.Xml.XPath import Context tester.testDone() tester.startTest('Creating test environment') rootContext = Context.Context(DomTree.ROOT,1,1) context = child1Context = Context.Context(DomTree.CHILD1,1,3) child2Context = Context.Context(DomTree.CHILD2,2,3) textContext = Context.Context(DomTree.TEXT1,3,3) tests = [] # Test 1 as = ParsedAxisSpecifier.ParsedAxisSpecifier('ancestor') nt = ParsedNodeTest.ParsedNameTest('*') s = ParsedStep.ParsedStep(as, nt) tests.append((s, [DomTree.ROOT])) # Test 2 as = ParsedAxisSpecifier.ParsedAxisSpecifier('ancestor-or-self') s = ParsedStep.ParsedStep(as, nt, None) tests.append((s, [DomTree.ROOT, DomTree.CHILD1])) # Test 3 as = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') nt = ParsedNodeTest.ParsedNameTest('GCHILD') s = ParsedStep.ParsedStep(as, nt) tests.append((s, DomTree.GCHILDREN1)) # Test 4 as = ParsedAxisSpecifier.ParsedAxisSpecifier('child') nt = ParsedNodeTest.ParsedNameTest('GCHILD') left = ParsedExpr.ParsedFunctionCallExpr('position', []) right = ParsedExpr.ParsedNLiteralExpr('1') exp = ParsedExpr.ParsedEqualityExpr('=', left, right) pl = ParsedPredicateList.ParsedPredicateList([exp]) s = ParsedStep.ParsedStep(as, nt, pl) tests.append((s, [DomTree.GCHILD11])) # Test 5 right = ParsedExpr.ParsedNLiteralExpr('1') pl = ParsedPredicateList.ParsedPredicateList([right]) as = ParsedAxisSpecifier.ParsedAxisSpecifier('child') nt = ParsedNodeTest.ParsedNameTest('GCHILD') s = ParsedStep.ParsedStep(as,nt,pl) tests.append((s, [DomTree.GCHILD11])) tester.testDone() for step,expected in tests: tester.startTest('Select "%s"' % repr(step)) node_set = step.select(context) if len(node_set) != len(expected): tester.error('Wrong size of node set. Expected %d, got %d' % ( len(expected), len(node_set) )) results = map(lambda a,b: a == b, node_set, expected) if not reduce(lambda a,b: a and b, results, 1): tester.error('Invalid node in node set. Expected\n%s\ngot\n%s' % ( str(expected), str(node_set), )) tester.testDone() return tester.groupDone()
def Test(tester): tester.startGroup('Core Function Library') tester.startTest('Creating test environment') from Ft.Lib import boolean, number from Ft.Xml import XPath from Ft.Xml.XPath import ParsedExpr, Context from Ft.Xml.XPath import XPathTypes as Types DomTree = tester.test_data['tree'] context1 = Context.Context(DomTree.CHILD1, 1, 3) context2 = Context.Context(DomTree.CHILD2, 2, 3) contextLang1 = Context.Context(DomTree.LCHILD1, 1, 1) contextLang2 = Context.Context(DomTree.LCHILD2, 1, 1) import DummyExpr from DummyExpr import boolT, boolF from DummyExpr import num0, num0p5, numN0p5, num1, num1p5, num2, num2p6, num3, numN4, num4p5 from DummyExpr import numN4p5, numN42, numInf, numNInf, numNan from DummyExpr import str12345, strPi, strText, strPiText, strSpace, strHelloWorld, strEmpty from DummyExpr import ONE_NODE_SET_DOC2, TWO_NODE_SET_DOC2, THREE_NODE_SET_DOC2, FOUR_NODE_SET_DOC2 nodeset0 = DummyExpr.DummyNodeSetExpr([]) nodeset1 = DummyExpr.DummyNodeSetExpr([DomTree.ROOT]) nodeset2 = DummyExpr.DummyNodeSetExpr([DomTree.ROOT, DomTree.CHILD1]) nodeset3 = DummyExpr.DummyNodeSetExpr([DomTree.CHILD1]) nodeset4 = DummyExpr.DummyNodeSetExpr([DomTree.CHILD3]) strNodeset3 = '\n \n \n Text1\n ' # a,b,c,d,e,f,g become A,B,C,D,E,F,G translateFrom1 = DummyExpr.DummyStringExpr('abcdefg') translateTo1 = DummyExpr.DummyStringExpr('ABCDEFG') # e becomes a translateFrom2 = DummyExpr.DummyStringExpr('e') translateTo2 = DummyExpr.DummyStringExpr('a') # e becomes a; extra chars in To string are ignored translateFrom3 = DummyExpr.DummyStringExpr('e') translateTo3 = DummyExpr.DummyStringExpr('abc') # e becomes a; l is deleted translateFrom4 = DummyExpr.DummyStringExpr('el') translateTo4 = DummyExpr.DummyStringExpr('a') # a,b,c,d,e,f,g become A,B,C,D,E,F,G; # repeated chars in From string are ignored translateFrom5 = DummyExpr.DummyStringExpr('abcdefgabc') translateTo5 = DummyExpr.DummyStringExpr('ABCDEFG123') translateFrom6 = DummyExpr.DummyStringExpr('abcdefghhe') translateTo6 = DummyExpr.DummyStringExpr('ABCDEFGH') translateFrom7 = DummyExpr.DummyStringExpr('abcdefgh') translateTo7 = DummyExpr.DummyStringExpr('') tests = [ ('last', [], context1, 3), ('last', [], context2, 3), ('position', [], context1, 1), ('position', [], context2, 2), ('count', [nodeset2], context1, 2), ('id', [num1], context1, [DomTree.CHILD2]), ('id', [DummyExpr.DummyStringExpr('1 1')], context1, [DomTree.CHILD2]), ('id', [DummyExpr.DummyStringExpr('0')], context1, []), ('id', [DummyExpr.DummyStringExpr('0 1')], context1, [DomTree.CHILD2]), ('id', [DummyExpr.DummyStringExpr('0 1 1')], context1, [DomTree.CHILD2]), ('id', [DummyExpr.DummyStringExpr('0 0 1 1')], context1, [DomTree.CHILD2]), ('id', [ONE_NODE_SET_DOC2], context1, []), ('id', [TWO_NODE_SET_DOC2], context1, [DomTree.CHILD2]), ('id', [THREE_NODE_SET_DOC2], context1, [DomTree.CHILD2]), ('id', [FOUR_NODE_SET_DOC2], context1, [DomTree.CHILD2]), ('local-name', [nodeset0], context1, ''), ('local-name', [nodeset4], context1, 'CHILD3'), ('namespace-uri', [nodeset0], context1, ''), ('namespace-uri', [nodeset4], context1, u'http://foo.com'), ('name', [nodeset4], context1, 'foo:CHILD3'), ('string', [nodeset3], context1, strNodeset3), ('concat', [nodeset3, strPi, strText], context1, strNodeset3 + u'3.14Hi'), ('starts-with', [nodeset3, strPi], context1, boolean.false), ('starts-with', [nodeset3, nodeset3], context1, boolean.true), ('starts-with', [nodeset3, strEmpty], context1, boolean.true), ('contains', [nodeset3, strPi], context1, boolean.false), ('contains', [nodeset3, nodeset3], context1, boolean.true), ('contains', [nodeset3, strEmpty], context1, boolean.true), ('substring-before', [strPiText, strText], context1, u'3.14'), ('substring-before', [strPiText, strEmpty], context1, u''), ('substring-after', [strPiText, strPi], context1, u'Hi'), ('substring-after', [strPiText, strEmpty], context1, u''), ('substring', [strPiText, strPi], context1, u'14Hi'), ('substring', [strPiText, strPi, num1], context1, u'1'), ('substring', [str12345, num2, num3], context1, u'234'), ('substring', [str12345, num2], context1, u'2345'), ('substring', [str12345, num1p5, num2p6], context1, u'234'), ('substring', [str12345, num0, num3], context1, u'12'), ('substring', [str12345, numNan, num3], context1, u''), ('substring', [str12345, num1, numNan], context1, u''), ('substring', [str12345, numN42, numInf], context1, u'12345'), ('substring', [str12345, numNInf, numInf], context1, u''), ('string-length', [strPiText], context1, 6), ('normalize-space', [strSpace], context1, u'Ht There Mike'), ('translate', [strSpace, translateFrom1, translateTo1], context1, u'Ht \t ThErE\t MikE'), ('translate', [strHelloWorld, translateFrom2, translateTo2], context1, u'hallo world'), ('translate', [strHelloWorld, translateFrom3, translateTo3], context1, u'hallo world'), ('translate', [strHelloWorld, translateFrom4, translateTo4], context1, u'hao word'), ('translate', [strHelloWorld, translateFrom5, translateTo5], context1, u'hEllo worlD'), ('translate', [strHelloWorld, translateFrom6, translateTo6], context1, u'HEllo worlD'), ('translate', [strHelloWorld, translateFrom7, translateTo7], context1, u'llo worl'), ('boolean', [strPiText], context1, boolean.true), ('not', [strPiText], context1, boolean.false), ('true', [], context1, boolean.true), ('false', [], context1, boolean.false), ('number', [], context1, number.nan), ('floor', [strPi], context1, 3), ('floor', [numNan], context1, number.nan), ('floor', [numInf], context1, number.inf), ('floor', [numNInf], context1, -number.inf), ('floor', [num0p5], context1, 0), ('floor', [numN0p5], context1, -1), ('ceiling', [strPi], context1, 4), ('ceiling', [numNan], context1, number.nan), ('ceiling', [numInf], context1, number.inf), ('ceiling', [num0p5], context1, 1), ('ceiling', [numN0p5], context1, 0), # actually should be negative zero ('round', [strPi], context1, 3), ('round', [numN4p5], context1, -4), ('round', [numNan], context1, number.nan), ('round', [numInf], context1, number.inf), ('round', [numNInf], context1, -number.inf), ('round', [str12345], context1, 12345), ('lang', [DummyExpr.DummyStringExpr('en')], contextLang1, boolean.false), ('lang', [DummyExpr.DummyStringExpr('en')], contextLang2, boolean.true), ('lang', [DummyExpr.DummyStringExpr('')], contextLang1, boolean.true), ('lang', [DummyExpr.DummyStringExpr('')], contextLang2, boolean.false), ('lang', [DummyExpr.DummyStringExpr('foo')], contextLang1, boolean.false), ('lang', [DummyExpr.DummyStringExpr('foo')], contextLang2, boolean.false), ] typetests = [ ('last', [], Types.NumberType), ('position', [], Types.NumberType), ('count', [nodeset0], Types.NumberType), ('id', [DummyExpr.DummyStringExpr('id1')], Types.NodesetType), ('local-name', [nodeset3], Types.StringType), ('namespace-uri', [nodeset3], Types.StringType), ('name', [nodeset3], Types.StringType), ('string', [nodeset3], Types.StringType), ('concat', [nodeset3, DummyExpr.DummyStringExpr('foo')], Types.StringType), ('starts-with', [nodeset3, DummyExpr.DummyStringExpr('foo')], Types.BooleanType), ('contains', [nodeset3, DummyExpr.DummyStringExpr('foo')], Types.BooleanType), ('substring-before', [nodeset3, DummyExpr.DummyStringExpr('foo')], Types.StringType), ('substring-after', [nodeset3, DummyExpr.DummyStringExpr('foo')], Types.StringType), ('substring', [nodeset3, DummyExpr.DummyStringExpr('foo')], Types.StringType), ('string-length', [DummyExpr.DummyStringExpr('foo')], Types.NumberType), ('normalize-space', [DummyExpr.DummyStringExpr('foo')], Types.StringType), ('translate', [ DummyExpr.DummyStringExpr('foo'), DummyExpr.DummyStringExpr('f'), DummyExpr.DummyStringExpr('b') ], Types.StringType), ('boolean', [nodeset0], Types.BooleanType), ('not', [nodeset0], Types.BooleanType), ('true', [], Types.BooleanType), ('false', [], Types.BooleanType), ('lang', [DummyExpr.DummyStringExpr('en')], Types.BooleanType), ('number', [DummyExpr.DummyStringExpr('foo')], Types.NumberType), ('sum', [nodeset3], Types.NumberType), ('floor', [num4p5], Types.NumberType), ('ceiling', [num4p5], Types.NumberType), ('round', [num4p5], Types.NumberType), ] tester.testDone() tester.startGroup('Function evaluation') for (funcname, args, context, expected) in tests: p = ParsedExpr.ParsedFunctionCallExpr(funcname, args) tester.startTest('Evaluation of %s' % repr(p)) result = p.evaluate(context) tester.compare(expected, result) tester.testDone() tester.groupDone() tester.startGroup('Evaluated function type') for (funcname, args, expected) in typetests: p = ParsedExpr.ParsedFunctionCallExpr(funcname, args) tester.startTest('%s()' % funcname) result = p.evaluate(context1) tester.compare(expected, type(result)) tester.testDone() tester.groupDone() tester.groupDone() return
else: _select = self.parseExpression(select) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, select) templateNode = nodeset[0] context.processorNss = oldNss t_nss, t_node, t_preserveSpace = self.templates[name] t_context = Context.Context( templateNode, varBindings=context.varBindings, extFunctionMap=context.functions, processorNss=t_nss) for n in t_node.childNodes: self.visit(t_context, n, t_preserveSpace) elif node.localName == 'for-each': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss