def insertText(self, data, insertBefore=None): """Insert data as text in the current node, positioned before the start of node insertBefore or to the end of the node's text. """ if insertBefore: self.insertBefore(tree.text(data), insertBefore) else: self.xml_append(tree.text(data))
def replace_function(context, string, search, replace): """ The str:replace function converts a string to a node-set, with each instance of a substring from a given list (obtained from the string-values of nodes in the second argument) replaced by the node at the corresponding position of the node-set given as the third argument. Unreplaced substrings become text nodes. The second and third arguments can be any type of object; if either is not a node-set, it is treated as if it were a node-set of just one text node, formed from the object's string-value. Attribute and namespace nodes in the replacement set are erroneous but are treated as empty text nodes. All occurrences of the longest substrings are replaced first, and once a replacement is made, that span of the original string is no longer eligible for future replacements. An empty search string matches between every character of the original string. See http://exslt.org/str/functions/replace/str.replace.html for details. """ #FIXME: http://www.exslt.org/str/functions/replace/ doesn't say we have #to convert the first arg to a string, but should we, anyway? #If not, we should at least check and flag non-strings with a clear error? # prepare a list of strings to search for (based on searchNodeSet) string = string.evaluate_as_string(context) search = search.evaluate(context) replace = replace.evaluate(context) if isinstance(search, datatypes.nodeset): search = map(datatypes.string, search) else: search = [datatypes.string(search)] if isinstance(replace, datatypes.nodeset): # use `replace` but replace attr, ns nodes with empty text nodes for index, node in enumerate(replace): if isinstance(node, (tree.attribute, tree.namespace)): replace[index] = tree.text(u'') else: replace = [tree.text(datatypes.string(replace))] # Unpaired search patterns are to be deleted (replacement is None) replace = itertools.chain(replace, itertools.repeat(None)) # Sort the tuples in ascending order by length of string. # So that the longest search strings will be replaced first, replacements = zip(search, replace, itertools.imap(len, search)) replacements.sort(key=operator.itemgetter(2), reverse=True) # generate a result tree fragment context.push_tree_writer(context.instruction.baseUri) _replace(context, string, *replacements) writer = context.pop_writer() rtf = writer.get_result() return datatypes.nodeset(rtf.xml_children)
def replace_function(context, string, search, replace): """ The str:replace function converts a string to a node-set, with each instance of a substring from a given list (obtained from the string-values of nodes in the second argument) replaced by the node at the corresponding position of the node-set given as the third argument. Unreplaced substrings become text nodes. The second and third arguments can be any type of object; if either is not a node-set, it is treated as if it were a node-set of just one text node, formed from the object's string-value. Attribute and namespace nodes in the replacement set are erroneous but are treated as empty text nodes. All occurrences of the longest substrings are replaced first, and once a replacement is made, that span of the original string is no longer eligible for future replacements. An empty search string matches between every character of the original string. See http://exslt.org/str/functions/replace/str.replace.html for details. """ # FIXME: http://www.exslt.org/str/functions/replace/ doesn't say we have # to convert the first arg to a string, but should we, anyway? # If not, we should at least check and flag non-strings with a clear error? # prepare a list of strings to search for (based on searchNodeSet) string = string.evaluate_as_string(context) search = search.evaluate(context) replace = replace.evaluate(context) if isinstance(search, datatypes.nodeset): search = map(datatypes.string, search) else: search = [datatypes.string(search)] if isinstance(replace, datatypes.nodeset): # use `replace` but replace attr, ns nodes with empty text nodes for index, node in enumerate(replace): if isinstance(node, (tree.attribute, tree.namespace)): replace[index] = tree.text(u"") else: replace = [tree.text(datatypes.string(replace))] # Unpaired search patterns are to be deleted (replacement is None) replace = itertools.chain(replace, itertools.repeat(None)) # Sort the tuples in ascending order by length of string. # So that the longest search strings will be replaced first, replacements = zip(search, replace, itertools.imap(len, search)) replacements.sort(key=operator.itemgetter(2), reverse=True) # generate a result tree fragment context.push_tree_writer(context.instruction.baseUri) _replace(context, string, *replacements) writer = context.pop_writer() rtf = writer.get_result() return datatypes.nodeset(rtf.xml_children)
def pagelink(self, on, pagename="", page=None, **kw): FormatterBase.pagelink(self, on, pagename, page, **kw) if page is None: page = Page(self.request, pagename, formatter=self) link_text = page.link_to(self.request, on=on, **kw) self._curr.xml_append(tree.text(U(link_text))) return ""
def pagelink(self, on, pagename='', page=None, **kw): FormatterBase.pagelink(self, on, pagename, page, **kw) if page is None: page = Page(self.request, pagename, formatter=self) link_text = page.link_to(self.request, on=on, **kw) self._curr.xml_append(tree.text(U(link_text))) return ''
def test_chardata_unb(self): spam = tree.text(u'Spam') self.assertEqual(spam.xml_value, u'Spam') self.assertEqual(len(spam.xml_value), 4) self.assertEqual(spam.xml_value[1:3], u'pa') spam.xml_value += u' eggs' self.assertEqual(spam.xml_value, u'Spam eggs')
def list_services(self, ident=None): document = tree.entity() services = document.xml_append(tree.element(None, 'services')) for path, service in sorted(self._registered_services.iteritems()): if ident is not None and service.ident != ident: continue service_node = services.xml_append(tree.element(None, 'service')) service_node.xml_attributes['ident'] = service.ident E = service_node.xml_append(tree.element(None, 'path')) template = service.template if template is not None: E.xml_attributes["template"] = service.template.template E.xml_append(tree.text(path)) E = service_node.xml_append(tree.element(None, 'description')) E.xml_append(tree.text(service.doc)) return document
def xml_append(self, obj): # Can't really rely on super here base_class = {tree.element.xml_type: tree.element, tree.entity.xml_type: tree.entity}[self.xml_type] if isinstance(obj, str): base_class.xml_append(self, tree.text(obj.decode(self.factory_entity.xml_encoding))) elif isinstance(obj, unicode): base_class.xml_append(self, tree.text(obj)) elif isinstance(obj, tree.node): base_class.xml_append(self, obj) elif isinstance(obj, E): buf = StringIO() w = structwriter(indent=u"yes", stream=buf) w.feed(obj) self.xml_append_fragment(buf.getvalue()) else: raise TypeError return
def xml_append(self, obj): #Can't really rely on super here base_class = {tree.element.xml_type: tree.element, tree.entity.xml_type: tree.entity}[self.xml_type] if isinstance(obj, str): base_class.xml_append(self, tree.text(obj.decode(self.factory_entity.xml_encoding))) elif isinstance(obj, unicode): base_class.xml_append(self, tree.text(obj)) elif isinstance(obj, tree.node): base_class.xml_append(self, obj) elif isinstance(obj, E): buf = StringIO() w = structwriter(indent=u"yes", stream=buf) w.feed(obj) self.xml_append_fragment(buf.getvalue()) else: raise TypeError return
def _addTextElem(self, target, elemName, text): """ Creates an element of the name elemName and adds a text node to it with the nodeValue of text. The new element is then added as a child to the element target. """ newElement = tree.element(None, elemName) newElement.xml_append(tree.text(text)) target.xml_append(newElement)
def test_create_new_doc_comment(self): EXPECTED = '<A a="b">One</A><!--This is easy-->' doc = tree.entity() A = tree.element(None, u'A') A.xml_attributes[u'a'] = u'b' A.xml_append(tree.text(u'One')) doc.xml_append(A) doc.xml_append(tree.comment(u"This is easy")) self.compare_output(doc, XMLDECL+EXPECTED) return
def test_create_new_doc_comment(self): EXPECTED = '<A a="b">One</A><!--This is easy-->' doc = tree.entity() A = tree.element(None, u'A') A.xml_attributes[u'a'] = u'b' A.xml_append(tree.text(u'One')) doc.xml_append(A) doc.xml_append(tree.comment(u"This is easy")) self.compare_output(doc, XMLDECL + EXPECTED) return
def test_create_new_doc_pi(self): EXPECTED = '<?xml-stylesheet href="classic.xsl" type="text/xml"?><A a="b">One</A>' doc = tree.entity() doc.xml_append(tree.processing_instruction(u'xml-stylesheet', u'href="classic.xsl" type="text/xml"')) A = tree.element(None, u'A') A.xml_attributes[u'a'] = u'b' A.xml_append(tree.text(u'One')) doc.xml_append(A) self.compare_output(doc, XMLDECL+EXPECTED) return
def test_create_new_doc_attr_factory(self): EXPECTED = '<A a="b">One</A>' doc = tree.entity() A = tree.element(None, u'A') new_attr = A.xml_attribute_factory(None, u'a', u'b') A.xml_attributes.setnode(new_attr) A.xml_append(tree.text(u'One')) doc.xml_append(A) self.compare_output(doc, XMLDECL+EXPECTED) return
def test_create_new_doc_attr_factory(self): EXPECTED = '<A a="b">One</A>' doc = tree.entity() A = tree.element(None, u'A') new_attr = A.xml_attribute_factory(None, u'a', u'b') A.xml_attributes.setnode(new_attr) A.xml_append(tree.text(u'One')) doc.xml_append(A) self.compare_output(doc, XMLDECL + EXPECTED) return
def test_create_new_doc_pi(self): EXPECTED = '<?xml-stylesheet href="classic.xsl" type="text/xml"?><A a="b">One</A>' doc = tree.entity() doc.xml_append( tree.processing_instruction(u'xml-stylesheet', u'href="classic.xsl" type="text/xml"')) A = tree.element(None, u'A') A.xml_attributes[u'a'] = u'b' A.xml_append(tree.text(u'One')) doc.xml_append(A) self.compare_output(doc, XMLDECL + EXPECTED) return
def paramvalue(obj): """ Try to convert a Python object into an XPath data model value returns the value if successful, else None """ if isinstance(obj, datatypes.xpathobject): return obj if isinstance(obj, unicode): return datatypes.string(obj) elif isinstance(obj, str): try: obj = obj.decode("utf-8") except UnicodeError: return None else: return datatypes.string(obj) elif isinstance(obj, bool): # <bool> is subclasses of <int>, test first return datatypes.TRUE if obj else datatypes.FALSE elif isinstance(obj, (int, long, float)): return datatypes.number(obj) elif isinstance(obj, tree.node): return obj # NOTE: At one time (WSGI.xml days) this attemped to be smart and handle # all iterables but this would mean blindly dealing with dangerous # creatures, such as sockets. So now it's more conservative and sticks to # just list & tuple. elif isinstance(obj, (list, tuple)): # We can only use the list if the items are all nodes or all strings. # Strings are converted to a nodeset of text nodes. for item in obj: if not isinstance(item, (str, unicode)): break else: # We need to use an entity to preserve ordering entity = tree.entity() for item in obj: if isinstance(item, str): try: item = unicode(item, "utf8") except UnicodeError: return None entity.xml_append(tree.text(item)) return datatypes.nodeset(entity.xml_children) # We can only use the list if all the items are nodes. for item in obj: if not isinstance(item, tree.node): return None return datatypes.nodeset(obj) else: return None
def paramvalue(obj): """ Try to convert a Python object into an XPath data model value returns the value if successful, else None """ if isinstance(obj, datatypes.xpathobject): return obj if isinstance(obj, unicode): return datatypes.string(obj) elif isinstance(obj, str): try: obj = obj.decode('utf-8') except UnicodeError: return None else: return datatypes.string(obj) elif isinstance(obj, bool): # <bool> is subclasses of <int>, test first return datatypes.TRUE if obj else datatypes.FALSE elif isinstance(obj, (int, long, float)): return datatypes.number(obj) elif isinstance(obj, tree.node): return obj # NOTE: At one time (WSGI.xml days) this attemped to be smart and handle # all iterables but this would mean blindly dealing with dangerous # creatures, such as sockets. So now it's more conservative and sticks to # just list & tuple. elif isinstance(obj, (list, tuple)): # We can only use the list if the items are all nodes or all strings. # Strings are converted to a nodeset of text nodes. for item in obj: if not isinstance(item, (str, unicode)): break else: # We need to use an entity to preserve ordering entity = tree.entity() for item in obj: if isinstance(item, str): try: item = unicode(item, 'utf8') except UnicodeError: return None entity.xml_append(tree.text(item)) return datatypes.nodeset(entity.xml_children) # We can only use the list if all the items are nodes. for item in obj: if not isinstance(item, tree.node): return None return datatypes.nodeset(obj) else: return None
def text(self, text, **kw): if text == u"\\n": srcText = u"\n" else: srcText = text if srcText and self._isInsidePreformatted(): # 4Suite version used CDATASection nodes. Don't bother self.cur.xml_last_child.xml_append(tree.text(srcText)) elif self.cur.xml_qname in self.wrap_text_in_para: """ If we already wrapped one text item in a para, we should add to that para and not create a new one. Another question is if we should add a space? """ if self.cur.xml_last_child is not None and self.cur.xml_last_child.xml_qname == u'para': self.cur.xml_last_child.xml_append(tree.text(srcText)) else: self.paragraph(1) self.text(text) self.paragraph(0) else: self.cur.xml_append(tree.text(srcText)) return ""
def text(self, text, **kw): if text == u"\\n": srcText = u"\n" else: srcText = text if srcText and self._isInsidePreformatted(): # 4Suite version used CDATASection nodes. Don't bother self.cur.xml_last_child.xml_append(tree.text(srcText)) elif self.cur.xml_qname in self.wrap_text_in_para: """ If we already wrapped one text item in a para, we should add to that para and not create a new one. Another question is if we should add a space? """ if self.cur.xml_last_child is not None and self.cur.xml_last_child.xml_qname == u"para": self.cur.xml_last_child.xml_append(tree.text(srcText)) else: self.paragraph(1) self.text(text) self.paragraph(0) else: self.cur.xml_append(tree.text(srcText)) return ""
def test_reading_building(self): doc = tree.entity() doc.xml_append(tree.processing_instruction(u'xml-stylesheet', u'href="classic.xsl" type="text/xml"')) A = tree.element(None, u'A') A.xml_attributes[u'a'] = u'b' A.xml_append(tree.text(u'One')) doc.xml_append(A) doc.xml_append(tree.comment(u"This is easy")) doc2 = amara.parse('docs/whatsnew_doc1.xml') output1 = cStringIO.StringIO() output2 = cStringIO.StringIO() xml_print(doc, stream=output1) xml_print(doc2, stream=output2) self.assertEqual(output1.getvalue(), output2.getvalue()) return
def set_default(self, node): #XXX: Should be able to reuse named_node_test function #What prefix to use for prefix, ns in node.xml_namespaces.items(): if ns == self.ns and prefix: qname = prefix + u':' + self.local break else: #No prefix: just hijack the default namespace qname = self.local ownerdoc = node.xml_select(u'/')[0] eclass = ownerdoc.eclass(self.ns, self.local) new_elem = eclass(self.ns, qname) new_elem.xml_append(tree.text(self.default)) node.xml_append(new_elem) return
def test_reading_building(self): doc = tree.entity() doc.xml_append( tree.processing_instruction(u'xml-stylesheet', u'href="classic.xsl" type="text/xml"')) A = tree.element(None, u'A') A.xml_attributes[u'a'] = u'b' A.xml_append(tree.text(u'One')) doc.xml_append(A) doc.xml_append(tree.comment(u"This is easy")) doc2 = amara.parse('docs/whatsnew_doc1.xml') output1 = cStringIO.StringIO() output2 = cStringIO.StringIO() xml_print(doc, stream=output1) xml_print(doc2, stream=output2) self.assertEqual(output1.getvalue(), output2.getvalue()) return
def _map(context, nodeset, expr): focus = context.node, context.position, context.size context.size = len(nodeset) position = 1 inputs = iter(nodeset) return_type = None result = set() for node in inputs: context.node = node context.position = position position += 1 try: obj = expr.evaluate(context) except: lines = traceback.format_exception(*sys.exc_info()) lines[:1] = [("Runtime error in XPath expression '%(expr)s', " "lower-level traceback:\n") % { 'expr': string }] context.processor.warning(''.join(lines)) else: if not return_type: if isinstance(obj, datatypes.nodeset): tag_name = None elif isinstance(obj, datatypes.number): tag_name = 'exsl:number' converter = datatypes.string elif isinstance(obj, datatypes.boolean): tag_name = 'exsl:boolean' converter = lambda obj: u'true' if obj else u'' else: tag_name = 'exsl:string' converter = datatypes.string return_type = True if tag_name: E = tree.element(EXSL_COMMON_NS, tag_name) E.xml_append(tree.text(converter(obj))) result.add(E) else: result.update(obj) context.node, context.position, context.size = focus return datatypes.nodeset(result)
def trim(node, count): newnode = copy(node) for child in node.xml_children: if count >= maxcount: break words = len(child.xml_select(u'string(.)').split()) if count + words < maxcount: newnode.xml_append(deepcopy(child)) count += words else: if isinstance(child, tree.text): words_required = maxcount - count chunk = child.xml_value.rsplit(None, words - words_required)[0] newnode.xml_append(tree.text(chunk)) else: newnode.xml_append(trim(child, count)) count = maxcount return newnode
def trim(node, count): newnode = copy(node) for child in node.xml_children: if count >= maxcount: break words = len(child.xml_select(u'string(.)').split()) if count + words < maxcount: newnode.xml_append(deepcopy(child)) count += words else: if isinstance(child, tree.text): words_required = maxcount - count chunk = child.xml_value.rsplit(None, words-words_required)[0] newnode.xml_append(tree.text(chunk)) else: newnode.xml_append(trim(child, count)) count = maxcount return newnode
def nodeset_function(context, arg0): """ The purpose of the exsl:node-set function is to return a node-set from a result tree fragment. If the argument is a node-set already, it is simply returned as is. If the argument to exsl:node-set is not a node-set or a result tree fragment, then it is converted to a string as by the string() function, and the function returns a node-set consisting of a single text node with that string value. The exsl:node-set function does not have side-effects: the result tree fragment used as an argument is still available as a result tree fragment after it is passed as an argument to exsl:node-set. """ obj = arg0.evaluate(context) if not isinstance(obj, datatypes.nodeset): if not isinstance(obj, tree.entity): obj = (tree.text(datatypes.string(obj)), ) obj = datatypes.nodeset([obj]) return obj
def nodeset_function(context, arg0): """ The purpose of the exsl:node-set function is to return a node-set from a result tree fragment. If the argument is a node-set already, it is simply returned as is. If the argument to exsl:node-set is not a node-set or a result tree fragment, then it is converted to a string as by the string() function, and the function returns a node-set consisting of a single text node with that string value. The exsl:node-set function does not have side-effects: the result tree fragment used as an argument is still available as a result tree fragment after it is passed as an argument to exsl:node-set. """ obj = arg0.evaluate(context) if not isinstance(obj, datatypes.nodeset): if not isinstance(obj, tree.entity): obj = (tree.text(datatypes.string(obj)),) obj = datatypes.nodeset([obj]) return obj
def _map(context, nodeset, expr): focus = context.node, context.position, context.size context.size = len(nodeset) position = 1 inputs = iter(nodeset) return_type = None result = set() for node in inputs: context.node = node context.position = position position += 1 try: obj = expr.evaluate(context) except: lines = traceback.format_exception(*sys.exc_info()) lines[:1] = [("Runtime error in XPath expression '%(expr)s', " "lower-level traceback:\n") % {'expr': string}] context.processor.warning(''.join(lines)) else: if not return_type: if isinstance(obj, datatypes.nodeset): tag_name = None elif isinstance(obj, datatypes.number): tag_name = 'exsl:number' converter = datatypes.string elif isinstance(obj, datatypes.boolean): tag_name = 'exsl:boolean' converter = lambda obj: u'true' if obj else u'' else: tag_name = 'exsl:string' converter = datatypes.string return_type = True if tag_name: E = tree.element(EXSL_COMMON_NS, tag_name) E.xml_append(tree.text(converter(obj))) result.add(E) else: result.update(obj) context.node, context.position, context.size = focus return datatypes.nodeset(result)
def process_pre_poem(node): ''' >>> X = ['<div>', '<pre>The red cap chiefs stack up their wealth,', 'Shards of what once was bred in bone.', '', 'Church tales of wandering accursed—', 'It\'s forty years full fifty times;', '</pre>', '</div>'] >>> X = '\n'.join(X) >>> doc = parse(X) >>> process_pre_poem(doc.xml_first_child) >>> doc.xml_write() <?xml version="1.0" encoding="UTF-8"?> <div> <p>The red cap chiefs stack up their wealth,<br/>Shards of what once was bred in bone.<br/></p><p>Church tales of wandering accursed—<br/>It's forty years full fifty times;<br/><br/></p> </div> ''' for pre in node.xml_select(u'.//pre'): ptext = U(pre) if pre.xml_first_child: pre.xml_remove(pre.xml_first_child) for stanza in ptext.split(u'\n\n'): p = element(None, u'p') pre.xml_append(p) for line in stanza.split(u'\n'): p.xml_append(text(line)) p.xml_append(element(None, u'br')) unwrap(pre) return
def attachment_drawing(self, url, text, **kw): self._elem(u"attachmentimage", on) self._curr.xml_attributes[None, u"href"] = U(url) self._curr.xml_append(tree.text(U(text))) self._elem(u"attachmentimage", off) return ""
def text(self, text, **kw): self._curr.xml_append(tree.text(text)) return ''
def rule(self, size=0, **kw): e = tree.element(None, u'br') # <hr/> not supported in stylebook e.xml_append(tree.text((u"-" * 78))) self._curr.xml_append(e) return ''
def attachment_drawing(self, url, text, **kw): self._elem(u'attachmentimage', on) self._curr.xml_attributes[None, u'href'] = U(url) self._curr.xml_append(tree.text(U(text))) self._elem(u'attachmentimage', off) return ''
def smiley(self, text): self._curr.xml_append(tree.text(U(text))) return ''
FALSE, # number literals (for special values) NOT_A_NUMBER, POSITIVE_INFINITY, NEGATIVE_INFINITY, # nodeset literals nodeset_literal, EMPTY_NODESET, ) from amara.xpath import context from test_expressions import DOC default_context = context(DOC, 1, 1) EGG1 = tree.element(None, 'egg1') EGG1.xml_append(tree.text('egg1')) EGG2 = tree.element(None, 'egg2') EGG2.xml_append(tree.text('egg2')) NUM = tree.element(None, 'num') NUM0 = tree.attribute(None, 'num0', '0') NUM.xml_attributes.setnode(NUM0) NUM2 = tree.attribute(None, 'num2', '2') NUM.xml_attributes.setnode(NUM0) NUM4 = tree.attribute(None, 'num4', '4') NUM.xml_attributes.setnode(NUM0) NUM31 = tree.attribute(None, 'num31', '31') NUM.xml_attributes.setnode(NUM0) def test_or_expr():
NOT_A_NUMBER, POSITIVE_INFINITY, NEGATIVE_INFINITY, # nodeset literals nodeset_literal, EMPTY_NODESET, ) from amara.xpath import context from test_expressions import DOC default_context = context(DOC, 1, 1) EGG1 = tree.element(None, "egg1") EGG1.xml_append(tree.text("egg1")) EGG2 = tree.element(None, "egg2") EGG2.xml_append(tree.text("egg2")) NUM = tree.element(None, "num") NUM0 = tree.attribute(None, "num0", "0") NUM.xml_attributes.setnode(NUM0) NUM2 = tree.attribute(None, "num2", "2") NUM.xml_attributes.setnode(NUM0) NUM4 = tree.attribute(None, "num4", "4") NUM.xml_attributes.setnode(NUM0) NUM31 = tree.attribute(None, "num31", "31") NUM.xml_attributes.setnode(NUM0) def test_or_expr():
def text(self, text, **kw): self._curr.xml_append(tree.text(text)) return ""
def rule(self, size=0, **kw): e = tree.element(None, u"br") # <hr/> not supported in stylebook e.xml_append(tree.text((u"-" * 78))) self._curr.xml_append(e) return ""
CHILD1, CHILD2, CHILD3, LCHILD1, LCHILD2) # contexts for nodeset {CHILD1, CHILD2, CHILD3} CONTEXT1 = context(CHILD1, 1, 3) CONTEXT2 = context(CHILD2, 2, 3) # contexts for nodeset {LCHILD1, LCHILD2, NONASCIIQNAME} CONTEXTLANG1 = context(LCHILD1, 1, 3) CONTEXTLANG2 = context(LCHILD2, 2, 3) DOC = tree.entity() EGG1 = DOC.xml_append(tree.element(None, 'egg0')) EGG1.xml_append(tree.text('0')) EGG2 = DOC.xml_append(tree.element(None, 'egg1')) EGG2.xml_append(tree.text('1')) EGG3 = DOC.xml_append(tree.element(None, 'egg0')) EGG3.xml_append(tree.text('0')) EGG4 = DOC.xml_append(tree.element(None, 'egg1')) EGG4.xml_append(tree.text('1')) EGG5 = DOC.xml_append(tree.element(None, 'egg0')) EGG5.xml_append(tree.text('0')) from amara.xpath.expressions.functioncalls import function_call def test_last_function(): for context in (CONTEXT1, CONTEXT2): result = function_call('last', ()).evaluate_as_number(context)
# <x> # <y>a</y> # </x> # </element> # <element> # <x> # <y>z</y> # </x> # </element> # </elements> ELEMENTS = tree.entity().xml_append(tree.element(None, 'elements')) for cdata in ('a', 'z'): node = ELEMENTS.xml_append(tree.element(None, 'element')) node = node.xml_append(tree.element(None, 'x')) node = node.xml_append(tree.element(None, 'y')) node.xml_append(tree.text(cdata)) del node, cdata CONTEXT_ELEMENT = context(ELEMENTS, 1, 1) ELEMENT1, ELEMENT2 = ELEMENTS from amara.xpath.parser import parse def _run_parser_pass(test_cases): for args, expected, ctx in test_cases: result = parse(*args).evaluate(ctx) if hasattr(expected, "isnan") and expected.isnan(): assert result.isnan() continue if isinstance(expected, list): # convert nodesets to lists to prevent XPath-style nodeset compares
def code_line(self, on): if on: self.cur.xml_append(tree.text(u"\n")) return ""
</catalog>''' EXTRACT_AUTHORS_PAT = r'(\s*By\s*)|(\s*,\s*)|(\s*and\s*)' EXTRACT_AUTHORS_PAT_GROUPS = 4 doc = amara.parse(SOURCE) for author_node in doc.xml_select(u'/catalog/book/authors'): authors = re.split(EXTRACT_AUTHORS_PAT, U(author_node)) for n in author_node.xml_children: author_node.xml_remove(n) #Collect the regex match into the regex-defined groups for i, subenum in groupby(enumerate(authors), lambda i: i[0]//EXTRACT_AUTHORS_PAT_GROUPS): matchgroup = [ group for i, group in subenum ] if matchgroup[0]: link = element(None, u'a') link.xml_attributes[None, u'href'] = 'http://example.org' link.xml_append(text(matchgroup[0])) author_node.xml_append(link) for match in matchgroup[1:]: if match: author_node.xml_append(text(match)) doc.xml_write() print #The following variation contributed by Luis Miguel Morillas: SOURCE = '''<catalog> <book> <title>Spam for Supper</title> By A.X. Ham and Franco Bacon <info> Other info</info>
def code_line(self, on): if on: self.cur.xml_append(tree.text(u'\n')) return ''
# number literals (for special values) NOT_A_NUMBER, POSITIVE_INFINITY, NEGATIVE_INFINITY, # nodeset literals nodeset_literal, ROOT, CHILD1, CHILD2, CHILD3, LCHILD1, LCHILD2 ) # contexts for nodeset {CHILD1, CHILD2, CHILD3} CONTEXT1 = context(CHILD1, 1, 3) CONTEXT2 = context(CHILD2, 2, 3) # contexts for nodeset {LCHILD1, LCHILD2, NONASCIIQNAME} CONTEXTLANG1 = context(LCHILD1, 1, 3) CONTEXTLANG2 = context(LCHILD2, 2, 3) DOC = tree.entity() EGG1 = DOC.xml_append(tree.element(None, 'egg0')) EGG1.xml_append(tree.text('0')) EGG2 = DOC.xml_append(tree.element(None, 'egg1')) EGG2.xml_append(tree.text('1')) EGG3 = DOC.xml_append(tree.element(None, 'egg0')) EGG3.xml_append(tree.text('0')) EGG4 = DOC.xml_append(tree.element(None, 'egg1')) EGG4.xml_append(tree.text('1')) EGG5 = DOC.xml_append(tree.element(None, 'egg0')) EGG5.xml_append(tree.text('0')) from amara.xpath.expressions.functioncalls import function_call def test_last_function(): for context in (CONTEXT1, CONTEXT2): result = function_call('last', ()).evaluate_as_number(context)
def smiley(self, text): self._curr.xml_append(tree.text(U(text))) return ""