PyXML-0.8.2/0040755000076400001440000000000007614726124011724 5ustar martinusersPyXML-0.8.2/demo/0040755000076400001440000000000007614726123012647 5ustar martinusersPyXML-0.8.2/demo/dom/0040755000076400001440000000000007614726123013426 5ustar martinusersPyXML-0.8.2/demo/dom/4tidy.py0100644000076400001440000000135507413602737015037 0ustar martinusersimport sys, cStringIO from xml.dom.ext.reader import HtmlLib from xml.dom.ext import XHtmlPrint def Tidy(doc): #stream = cStringIO.StringIO() #XHtmlPrint(doc, stream=stream) #text = stream.getvalue() XHtmlPrint(doc) return if __name__ == "__main__": html_reader = HtmlLib.Reader() if len(sys.argv) == 3: uri = sys.argv[1] encoding = sys.argv[2] elif len(sys.argv) == 2: uri = sys.argv[1] encoding = '' else: print "%s requires one or two arguments: the first is a URL or file name to be tidied. The optional second is the encoding to assume for the input."%sys.argv[0] sys.exit(-1) html_doc = html_reader.fromUri(uri, charset=encoding) Tidy(html_doc) PyXML-0.8.2/demo/dom/README0100644000076400001440000000767007244341241014306 0ustar martinusersExample Programs and Demos for 4DOM. ==================================== Sample data files which can be used to exercise the various demos: * addr_book1.xml * addr_book2.xml * book_catalog1.xml * addr_book.dtd * employee_table.html Demos: ------ * dom_from_html_file.py Demonstrates reading HTML from a file, and pretty-printing. Example: "python dom_from_html_file.py employee_table.html" * dom_from_xml_file.py Demonstrates reading XML from a file, and pretty-printing. Try changing FromXml to have "validate=1". Example: "python dom_from_xml_file.py addr_book1.xml" * generate_html1.py Demonstrates putting together a simple HTML page (a form in this case) with the standard DOM factory interface. Just execute with "python generate_html1.py" You can re-direct the output to file and view the result with a browser. Try adding in more sophisticated form elements. * generate_xml1.py Demonstrates putting together a simple XML document with the standard DOM factory interface. Just execute with "python generate_xml1.py" * 4tidy.py Demonstrates the XHTML support in 4DOM. It takes a URL or file name on the command line and reads the HTML source. It then prints xhtml based on the HTML source to standard output. try "python 4tidy.py http://fourthought.com" * iterator1.py Demonstrates the DOM standard Node Iterator interface. It iterates over each node in the read-in file, and prints out its node type and name. Then it iterates again, using the NodeFilter interface to restrict it to nodes of type Element. Example: "python iterator1.py addr_book1.xml" * visitor1.py Demonstrates 4DOM's proprietary Walker/Visitor interface. If you only need to iterate over a tree in pre-order, you are advised to use the standard NodeIterator instead (see iterator1.py and xll_replace.py for examples). dom.ext.Visitor is best for defi ning other iteration orders and rules. This sample actually just runs through a pre-order walk, for simplicity. The output should be identical to that of the first part of iterator1.py. Example: "python visitor1.py addr_book1.xml" * trace_ns.py A demo of 4DOM's namespace extensions. Given an XML file-name on the command line, it will walk through the elements in document order (using NodeIterator) and print out the default namespace in effect as well as those of the element and its attributes. Example: "python trace_ns.py book_catalog1.xml" For the Namespace spec, see http://www.w3.org/TR/REC-xml-names/ For James Clark's excellent introduction to and clarification of namespaces, see http://www.jclark.com/xml/xmlns.htm * link_title_invert.py Demonstrates node manipulations. It takes a sample document with anchors embedded in header tags, and flips them so that the header tags are instead embedded in the anchors. just "python link_title_invert.py" * xll_replace.py A rather more involved demo. This program reads in an XML file, and looks for XLL-type hyperlinks (see http://www.oasis-open.org/cover/xll.html for information on this remarkably powerful spec). Warning: This script uses a very obsolete version of XLink When it finds such a link, it looks for the target XML doc ument and parses it into a DOM node. It doesn't support XPointer for document fragments yet, but with a decent Xpointer processor, such as xptr (see below), you can add this yourself. It then replaces the node that contained the link with the entire con tents of the target document of that link. For a good example, look at addr_book1.xml and then addr_book2.xml. The former contains the following line: if you run "python xll_replace.py addr_book1.xml" it will read in the addr_book2.xml file into a node, and replace the ENTRY-LINK node with the new one. It will then print out the result, which should be self-explanatory. If you need help with the demos, or any other help working with 4DOM, please don't hesistate to as on the mailing list: 4Suite@lists.fourthought.com. PyXML-0.8.2/demo/dom/__init__.py0100644000076400001440000000027007166146226015535 0ustar martinusers######################################################################## # # File Name: __init__.py # # Documentation: http://docs.4suite.com/4DOM/__init__.py.html # PyXML-0.8.2/demo/dom/addr_book.dtd0100644000076400001440000000063607117052117016042 0ustar martinusers PyXML-0.8.2/demo/dom/addr_book1.xml0100644000076400001440000000172307117052117016146 0ustar martinusers Pieter Aaron
404 Error Way
404-555-1234 404-555-4321 404-555-5555 pieter.aaron@inter.net
Emeka Ndubuisi
42 Spam Blvd
767-555-7676 767-555-7642 800-SKY-PAGEx767676 endubuisi@spamtron.com
Vasia Zhugenev
2000 Disaster Plaza
000-987-6543 000-000-0000 vxz@magog.ru
PyXML-0.8.2/demo/dom/addr_book2.xml0100644000076400001440000000043007117052117016141 0ustar martinusers Gegbefuna Nwannem
666 Murtala Mohammed Blvd.
999-101-1001 nwanneg@naija.ng
PyXML-0.8.2/demo/dom/benchmark.py0100644000076400001440000000171707413602737015736 0ustar martinusers# A DOM benchmark import sys, time from xml.dom import core, utils def main(): global L, doc if len(sys.argv) == 1: print 'Usage: benchmark.py ' sys.exit() filename = sys.argv[1] file = open(filename, 'r') size = len(file.read()) file.close() print 'File %s is %iK in size' % (filename, size / 1024) start_time = time.time() doc = utils.FileReader( filename ).document end_time = time.time() print 'Building DOM tree:', end_time - start_time, 'sec' # Convert DOM tree back to XML start_time = time.time() xml = doc.toxml() end_time = time.time() print 'Serializing back to XML:', end_time - start_time, 'sec' # Time a complete getElementsByTagName() start_time = time.time() L = doc.getElementsByTagName("*") end_time = time.time() print 'getElementsByTagName("*"):', end_time - start_time, 'sec' print L[0].nodeName if __name__ == '__main__': main() PyXML-0.8.2/demo/dom/book_catalog1.xml0100644000076400001440000000076707117052117016655 0ustar martinusers Cheaper by the Dozen 1568491379

This is a funny book!

PyXML-0.8.2/demo/dom/building.py0100644000076400001440000000257707413602740015600 0ustar martinusers# This demo converts a few nested objects into an XML representation, # and provides a simple example of using the Builder class. from xml.dom import core from xml.dom.builder import Builder import types, time def object_convert(builder, obj): # Put the entire object inside an element with the same name as # the class. builder.startElement( obj.__class__.__name__ ) L = obj.__dict__.keys() L.sort() for attr in obj.__dict__.keys(): # Skip internal attributes (ones that begin with a '_') if attr[0] == '_': continue value = getattr(obj, attr) if type(value) == types.InstanceType: # Recursively process subobjects object_convert( builder, value) else: # Convert anything else to a string and put it in an element builder.startElement(attr) builder.text( str(value) ) builder.endElement(attr) builder.endElement( obj.__class__.__name__ ) if __name__ == '__main__': class Folder: pass class Bookmark: pass f=Folder() f.title = "Folder Title" f.createdTime = time.asctime( time.localtime( time.time() ) ) f.bookmark = b = Bookmark() b.url, b.title = "http://www.python.org", "Python Home Page" builder = Builder() object_convert(builder, f) print "Output from two nested objects:" print builder.document.toxml() PyXML-0.8.2/demo/dom/dom_from_html_file.py0100644000076400001440000000111107413602740017607 0ustar martinusers"""Reads in an HTML file from the command line and pretty-prints it.""" from xml.dom.ext.reader import HtmlLib from xml.dom import ext def read_html_from_file(fileName): #build a DOM tree from the file reader = HtmlLib.Reader() dom_object = reader.fromUri(fileName) #strip any ignorable white-space in preparation for pretty-printing ext.StripHtml(dom_object) #pretty-print the node ext.PrettyPrint(dom_object) #reclaim the object reader.releaseNode(dom_object); if __name__ == '__main__': import sys read_html_from_file(sys.argv[1]) PyXML-0.8.2/demo/dom/dom_from_xml_file.py0100644000076400001440000000060007244341241017443 0ustar martinusersfrom xml.dom import ext from xml.dom.ext.reader import PyExpat def read_xml_from_file(fileName): #build a DOM tree from the file reader = PyExpat.Reader() xml_dom_object = reader.fromUri(fileName) ext.Print(xml_dom_object) #reclaim the object reader.releaseNode(xml_dom_object) if __name__ == '__main__': import sys read_xml_from_file(sys.argv[1]) PyXML-0.8.2/demo/dom/domconv.py0100644000076400001440000000472107413602740015441 0ustar martinusers# A simple library to convert DOM object structures to SGML or XML output, # usually for xml2html conversion. import sys,types,string,StringIO SKIP=1 # Ignore the element and its contents STRIP=2 # Ignore the element, but process its contents ID=3 # Identity transform MAP=4 # Arg: (elem,hash). Map element to elem, map attrs using hash. def escape_markup(str): """Takes a string and escapes all '<'s and quotes in it with character entity references.""" str=string.replace(str,"<","<") return string.replace(str,'"',""") def convert(rootnode,spec,writer=sys.stdout): """Takes a DOM node, a conversion specification and a file-like object to write the converted data to, and performs the actual conversion. The spec hashtable must map element names to (action,arg) tuples, where action must be one of the constants at the top of this file. arg is only used for MAP, where it must be a tuple (elementname,maphash) where the elementname is the name of the element to substitute for the original one, and maphash is a hashtable that maps attribute names to either the attribute name to substitute or a function that takes the attribute value and returns the string to replace the entire attr='val' sequence with. """ try: (action,arg)=spec[rootnode.GI] except KeyError: action=STRIP if action==SKIP: return elif action==STRIP: pass elif action==ID: writer.write("<" + rootnode.GI) for (name,val) in rootnode.attributes.items(): writer.write(" %s='%s'" % (name,escape_markup(val))) writer.write(">") elif action==MAP: writer.write("<" + arg[0]) for (name,val) in rootnode.attributes.items(): if arg[1].has_key(name): map=arg[1][name] if type(map)==types.StringType: writer.write(" %s=\"%s\"" % (map,escape_markup(val))) else: writer.write(map(escape_markup(val))) writer.write(">") for child in rootnode.getChildren(): if child.GI=="#PCDATA": writer.write(escape_markup(child.data)) else: convert(child,spec,writer) if action==ID: writer.write("" % rootnode.GI) elif action==MAP: writer.write("" % arg[0]) def convert_str(rootnode,spec): obj=StringIO.StringIO() convert(rootnode,spec,obj) return obj.getvalue() PyXML-0.8.2/demo/dom/employee_table.html0100644000076400001440000000232207244341241017267 0ustar martinusers FourThought Employee List
Last Name, First Name Email address Extension Department
Butte, Brian Brian.Butte@fourthought.com x1111 1028
Ogbuji, Uche Uche.Ogbuji@fourthought.com x1112 1029
Olson, Mike Mike.Olson@fourthought.com x1113 1028
Roberts, Rich Rich.Roberts@fourthought.com x1114 1029
PyXML-0.8.2/demo/dom/generate_html1.py0100644000076400001440000000305007413602740016665 0ustar martinusers""" A basic example of using the DOM to create an HTML document from scratch. Also demonstrates creation of HTML forms """ from xml.dom import ext from xml.dom import implementation if __name__ == '__main__': #create a concrete HTMLDocument instance. doc = implementation.createHTMLDocument('A Basic HTML Document') #add in body doc.body = doc.createElement('Body') #Create a form form = doc.createElement('Form') #Create some text. Note: every character is represented in some #DOM object. All text (even between tags) is in a text node t = doc.createTextNode('Employee Name:') #Create an input tag i = doc.createElement('Input') #All elements can have attributes directly set i.setAttribute('TYPE','TEXT') #Some have helper functions defined. #This one sets the SIZE attribute to 20 #Note that the argument must be a string. 4DOM closely #follows the DOM spec for the type of the arguments, even #when the spec is inconsistent or counter-intuitive i.size = '20' #This sets the NAME attribute i.name = 'EmployeeName' #Set the form's ACTION attribute form.action = '/cgi-local/test.py' #this inserts i as the last child in the form form.appendChild(i) #Insert t before i in form's child list form.insertBefore(t,i) #add the form to the document's body. Note that you can't #add child elements directly to the document. doc.body.appendChild(form) #This prints out the text representation of the HTML document ext.PrettyPrint(doc) PyXML-0.8.2/demo/dom/generate_xml1.py0100644000076400001440000000222207413602740016521 0ustar martinusers""" A basic example of using the DOM to create an XML document from scratch. """ from xml.dom import ext from xml.dom import implementation if __name__ == '__main__': #Create a doctype using document type name, sysid and pubid dt = implementation.createDocumentType('mydoc', '', '') #Create a document using document element namespace URI, doc element #name and doctype. This automatically creates a document element #which is the single element child of the document doc = implementation.createHTMLDocument('', 'mydoc', dt) #Get the document element doc_elem = doc.documentElement #Create an element: the Document instanmce acts as a factory new_elem = doc.createElementNS('', 'spam') #Create an attribute on the new element new_elem.setAttributeNS('', 'eggs', 'sunnysideup') #Create a text node new_text = doc.createTextNode('some text here...') #Add the new text node to the new element new_elem.appendChild(new_text) #Add the new element to the document element doc_elem.appendChild(new_elem) #Print out the resulting document import xml.doc.ext xml.doc.ext.Print(doc) PyXML-0.8.2/demo/dom/html2html0100755000076400001440000000355706624412225015271 0ustar martinusers#!/usr/bin/python # # This example program converts a chunk of HTML to a DOM tree. # It then prints the tree as HTML, as XML, and it prints a list of all # the hyperlinks in the document by using getElementsByTagName() to # retrieve all the A elements. from xml.dom.html_builder import HtmlBuilder from xml.dom.writer import HtmlWriter from xml.dom import core HTML_DATA = """ Les HOWTO Linux

Les HOWTO Linux

Les Howto que vous trouverez ci-dessous sont en français. Ils peuvent etre trouvés dans les formats suivants sur le site ftp.lip6.fr dans le répertoire /pub/linux/french/docs/HOWTO :

""" # Construct an HtmlBuilder object and feed the data to it b = HtmlBuilder() b.feed(HTML_DATA) # Get the newly-constructed document object doc = b.document # Output it as HTML print "============" print "HTML version" w = HtmlWriter() w.write(b.document) # Output it as XML print "\n===========" print "XML version" print doc.toxml() print "\n===========" print "Links in the document" # Retrieve all the link objects links = doc.getElementsByTagName('A') for node in links: # Collect any children of the A element that are Text nodes # (Note that this won't work on invalid HTML, like # Text. You could fix this by actually # traversing all the child nodes of the A element.) linktext = "" for child in node.childNodes: if child.nodeType == core.TEXT_NODE: linktext = linktext + child.value # Get the HREF attribute, if present url = node.getAttribute('HREF') if url != "": print "HREF=", url, linktext print links PyXML-0.8.2/demo/dom/iterator1.py0100644000076400001440000000172107413602740015703 0ustar martinusers"""Demonstrates basic walking using DOM level 2 iterators""" from xml.dom.ext.reader import PyExpat from xml.dom.NodeFilter import NodeFilter def Iterate(xml_dom_object): print "Printing all nodes:" nit = xml_dom_object.ownerDocument.createNodeIterator(xml_dom_object, NodeFilter.SHOW_ALL, None, 0) curr_node = nit.nextNode() while curr_node: print "%s node %s\n"%(curr_node.nodeType, curr_node.nodeName) curr_node = nit.nextNode() print "\n\n\nPrinting only element nodes:" snit = xml_dom_object.ownerDocument.createNodeIterator(xml_dom_object, NodeFilter.SHOW_ELEMENT, None, 0) curr_node = snit.nextNode() while curr_node: print "%s node %s\n"%(curr_node.nodeType, curr_node.nodeName) curr_node = snit.nextNode() if __name__ == '__main__': import sys reader = PyExpat.Reader() xml_dom_object = reader.fromUri(sys.argv[1]) Iterate(xml_dom_object) reader.releaseNode(xml_dom_object) PyXML-0.8.2/demo/dom/link_title_invert.py0100644000076400001440000000227207413602740017520 0ustar martinusersfrom xml.dom import Node, ext from xml.dom.ext.reader import PyExpat test_doc = """ LADIES

LADIES

Agathas

Four and forty lovers had Agathas in the old days,...

Young Lady

I have fed your lar with poppies,...

Lesbia Illa

Memnon, Memnon, that lady... """ def link_title_invert(): #build a DOM tree from the file reader = PyExpat.Reader() doc = reader.fromString(test_doc) h2_elements = doc.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'h2') for e in h2_elements: parent = e.parentNode a_list = filter(lambda x: (x.nodeType == Node.ELEMENT_NODE) and (x.localName == 'a'), e.childNodes) a = a_list[0] e.removeChild(a) for node in a.childNodes: #Automatically also removes the child from a e.appendChild(node) parent.replaceChild(a, e) a.appendChild(e) ext.Print(doc) #reclaim the object; not necessary with Python 2.0 reader.releaseNode(doc) if __name__ == '__main__': import sys link_title_invert() PyXML-0.8.2/demo/dom/trace_ns.py0100644000076400001440000000223107413602740015564 0ustar martinusers''' Walk through a namespace-compliant XML file and print out the the namespaces of all elements and attributes in document order ''' from xml.dom.ext.reader import PyExpat from xml.dom.NodeFilter import NodeFilter def TraceNs(doc): snit = doc.createNodeIterator(doc, NodeFilter.SHOW_ELEMENT, None, 0) curr_elem = snit.nextNode() while curr_elem: print "Current Element", curr_elem.nodeName #FIXME: put a GetDefaultNs method into Ext #ns = Namespace.GetDefaultNs(curr_elem) #print "\tDefault NS\t", ns print "\t"+curr_elem.nodeName+"\t\t", curr_elem.namespaceURI header_printed = 0 for k in curr_elem.attributes.keys(): if curr_elem.attributes[k].namespaceURI: if not header_printed: header_printed = 1 print "\tAttributes" print "\t\t"+curr_elem.attributes[k].nodeName+"\t", curr_elem.attributes[k].namespaceURI print curr_elem = snit.nextNode() if __name__ == "__main__": import sys reader = PyExpat.Reader() doc = reader.fromUri(sys.argv[1]) TraceNs(doc) reader.releaseNode(doc) PyXML-0.8.2/demo/dom/visitor1.py0100644000076400001440000000235507413602740015555 0ustar martinusers"""Demonstrates basic, pre-order DOM walking using the default, bare-bones visitor""" from xml.dom.ext.reader import PyExpat from xml.dom import Node from xml.dom.ext import Visitor from xml.dom.ext.reader import Sax2 from xml.dom.ext import ReleaseNode class NsVisitor(Visitor.Visitor): def visit(self, node): print "Node %s namespaceURI: '%s' qualified name: '%s' localName: '%s' prefix: '%s'\n"%(str(node), node.namespaceURI, node.nodeName, node.localName, node.prefix) if node.nodeType == Node.ELEMENT_NODE: for k in node.attributes.keys(): print "Node %s namespaceURI: '%s' qualified name: '%s' localName: '%s' prefix: '%s'\n"%(str(node.attributes[k]), node.attributes[k].namespaceURI, node.attributes[k].nodeName, node.attributes[k].localName, node.attributes[k].prefix) return None def Walk(xml_dom_object): visitor = Visitor.Visitor() walker = Visitor.Walker(visitor, xml_dom_object) walker.run() visitor = NsVisitor() walker = Visitor.Walker(visitor, xml_dom_object) walker.run() if __name__ == '__main__': import sys reader = PyExpat.Reader() xml_dom_object = reader.fromUri(sys.argv[1]) Walk(xml_dom_object) reader.releaseNode(xml_dom_object) PyXML-0.8.2/demo/dom/xll_replace.py0100644000076400001440000000371607413602740016271 0ustar martinusers""" Demonstrates some advanced DOM manipulation. This function looks for simple XLinks and replaces the node containing such links with the contents of the referenced document. """ from xml.dom import Node from xml.dom.NodeFilter import NodeFilter from xml.dom import ext from xml.dom.ext.reader import PyExpat def XllReplace(start_node): reader = PyExpat.Reader() owner_doc = start_node.ownerDocument snit = owner_doc.createNodeIterator(start_node, NodeFilter.SHOW_ELEMENT, None, 0) curr_node = snit.nextNode() while curr_node: #Only empty nodes are allowed to have Links if not curr_node.childNodes.length and curr_node.attributes: is_link = 0 href = None for k in curr_node.attributes.keys(): if (curr_node.attributes[k].localName, curr_node.attributes[k].namespaceURI) == ("link", "http://www.w3.org/XML/XLink/0.9"): is_link = 1 elif (curr_node.attributes[k].localName, curr_node.attributes[k].namespaceURI) == ("href", "http://www.w3.org/XML/XLink/0.9"): href = curr_node.attributes[k].value if is_link and href: #Then make a tree of the new file and insert it f = open(href, "r") st = f.read() new_df = reader.fromString(st, ownerDoc=start_node.ownerDocument) #Get the first element node and assume it's the document node for a_node in new_df.childNodes: if a_node.nodeType == Node.ELEMENT_NODE: doc_root = a_node break curr_node.parentNode.replaceChild(doc_root, curr_node) curr_node = snit.nextNode() return start_node if __name__ == "__main__": import sys reader = PyExpat.Reader() xml_dom_tree = reader.fromUri(sys.argv[1]) XllReplace(xml_dom_tree) ext.PrettyPrint(xml_dom_tree) reader.releaseNode(xml_dom_tree) PyXML-0.8.2/demo/dom/xpointer_query.py0100644000076400001440000000121107413602740017060 0ustar martinusers"""Demonstrates using the xptr.py tool to query DOM Nodes using the XPointer spec""" from xml.dom import ext from xml.dom.ext.reader import Sax2 import xptr if __name__ == '__main__': import sys xpointer_expr = sys.argv[1] try: xml_dom_object = Sax2.FromXmlUrl(sys.argv[2], validate=0) except Sax.saxlib.SAXException, msg: print "SAXException caught:", msg except Sax.saxlib.SAXParseException, msg: print "SAXParseException caught:", msg result_node = xptr.LocateNode(xml_dom_object, xpointer_expr) ext.StripXml(result_node) ext.PrettyPrint(result_node) ext.ReleaseNode(result_node) PyXML-0.8.2/demo/dom/xptr.py0100644000076400001440000004376307413602740015002 0ustar martinusers""" This is an experimental implementation of the XPointer locator language. Version 0.20 - 23.Aug.98 Lars Marius Garshol - larsga@ifi.uio.no http://www.stud.ifi.uio.no/~larsga/download/python/xml/xptr.html Changes since version 0.10: - 'id' locator term implemented - 'attr' locator term implemented - node type qualifiers implemented - 'origin' locator term implemented Modified by Uche Ogbuji 25.Jan.99 to work with 4DOM. Modified by Uche Ogbuji 18.Nov.99 to work with the emerging Python/DOM binding 4DOM. Distributed with permission. """ import re,string,sys from xml.dom import Node from xml.dom import ext # Spec deviations: # - html keyword not supported # - negative instance numbers not supported # - #cdata node type selector not supported # - * for attribute values/names not supported # - preceding keyword not supported # - span keyword unsupported # - support 'string' location terms # Spec questions # - what if locator fails? # - what to do with "span(...).child(1)"? # - how to continue from a set of selected nodes? # - attr: error if does not use element as source? # - should distinguish between semantic errors and failures? # - can string terms locate inside attr vals? # - are the string loc semantics a bit extreme? perhaps restrict to one node? # - how to represent span and string results in terms of the DOM? # Global variables version="0.20" specver="WD-xptr-19980303" # Useful regular expressions reg_sym=re.compile("[a-z]+|\\(|\\)|\\.|[-+]?[1-9][0-9]*|[A-Za-z_:][\-A-Za-z_:.0-9]*|,|#[a-z]+|\\*|\"[^\"]*\"|'[^']*'") reg_sym_param=re.compile(",|\)|\"|'") reg_name=re.compile("[A-Za-z_:][\-A-Za-z_:.0-9]*") # Some exceptions class XPointerException(Exception): "Means something went wrong when attempting to follow an XPointer." pass class XPointerParseException(XPointerException): "Means the XPointer was syntactically invalid." def __init__(self,msg,pos): self.__msg=msg self.__pos=pos def get_pos(self): return self.__pos def __str__(self): return self.__msg % self.__pos class XPointerFailedException(XPointerException): "Means the XPointer was logically invalid." pass class XPointerUnsupportedException(XPointerException): "Means the XPointer used unsupported constructs." pass # Simple XPointer lexical analyzer class SymbolGenerator: "Chops XPointers up into distinct symbols." def __init__(self,xpointer): self.__data=xpointer self.__pos=0 self.__last_was_param=0 self.__next_is="" def get_pos(self): "Returns the current position in the string." return self.__pos def more_symbols(self): "True if there are more symbols in the XPointer." return self.__pos1: type=params[1] if not (type=="#element" or type=="#pi" or type=="#comment" or \ type=="#text" or type=="#cdata" or type=="#all" or \ self.__is_valid(type,reg_name)): raise XPointerParseException("Invalid type at %s", self.__sgen.get_pos()) else: type="#element" attrs=[] ix=2 while ix+11: skiplit=params[1] else: skiplit=None if len(params)>2: if params[2]=="end": pos="end" else: try: pos=int(params[2]) except ValueError,e: raise XPointerParseException("Expected number at %s", self.__sgen.get_pos()) if pos==0: raise XPointerParseException("0 is not an acceptable " "value at %s", self.__sgen.get_pos()) else: pos=None if len(params)>3: try: length=int(params[3]) except ValueError,e: raise XPointerParseException("Expected number at %s", self.__sgen.get_pos()) else: length=0 self.handle_string_term(no,skiplit,pos,length) # Event methods to be overridden def handle_abs_term(self,name,param): "Called to handle absolute location terms." pass def handle_rel_term(self,name,no,type,attrs): "Called to handle relative location terms." pass def handle_attr_term(self,attr_name): "Called to handle 'attr' location terms." pass def handle_span_term(self,frm,to): "Called to handle 'span' location terms." pass def handle_string_term(self,no,skiplit,pos,length): "Called to handle 'string' location terms." pass # ----- XPointer implementation that navigates a DOM tree # Iterator classes class DescendantIterator: def __init__(self): self.stack=[] def __call__(self,node): next=node.firstChild if next==None: next=node.nextSibling while next==None: if self.stack==[]: raise XPointerFailedException("No matching node") next=self.stack[-1].nextSibling del self.stack[-1] self.stack.append(next) return next class FollowingIterator: def __init__(self): self.seen_hash={} self.skip_child=0 def __call__(self,node): if not self.skip_child: next=node.firstChild else: self.skip_child=0 next=None if next==None: next=node.getNextSibling() if next==None: next=node.parentNode self.skip_child=1 # Don't go down, we've been there :-) if next.GI=="#DOCUMENT": raise XPointerFailedException("No matching node") if self.seen_hash.has_key(next.id()): next=node.nextSibling prev=node while next==None: next=prev.parentNode self.skip_child=1 # Don't go down, we've been there :-) prev=next if next.nodeName=="#DOCUMENT": raise XPointerFailedException("No matching node") if self.seen_hash.has_key(next.id()): next=prev.nextSibling if next!=None: self.skip_child=0 else: # We're above all the nodes we've looked at. Throw out the # hashed objects. self.seen_hash.clear() self.seen_hash[next.id()]=1 return next # The implementation itself class XDOMLocator(XPointerParser): def __init__(self, xpointer, document): XPointerParser.__init__(self, xpointer) self.__node=document self.__first=1 self.__prev=None def __node_matches(self,node,type,attrs): "Checks whether a DOM node matches a foo(2,SECTION,ID,I5) selector." if type==node.nodeName or \ (type=="#element" and node.nodeType == Node.ELEMENT_NODE) or \ (type=="#pi" and node.nodeType == Node.PROCESSING_INSTRUCTION_NODE) or \ (type=="#comment" and node.nodeType == Node.COMMENT_NODE) or \ (type=="#text" and node.nodeType == Node.TEXT_NODE) or \ (type=="#cdata" and node.nodeType == Node.CDATA_SECTION_NODE) or \ type=="#all": if attrs!=None: for (a,v) in attrs: try: if v!=node.getAttribute(a): return 0 except KeyError,e: return 0 return 1 else: return 0 def __get_node(self,no,type,attrs,iterator): """General method that iterates through the tree calling the iterator on the current node for each step to get the next node.""" count=0 current=iterator(self.__node) while current!=None: if self.__node_matches(current,type,attrs): count=count+1 if count==no: return current current=iterator(current) raise XPointerFailedException("No matching node") def __get_child(self,no,type,attrs): if type==None: candidates = self.__node.childNodes else: candidates = [] for obj in self.__node.childNodes: if self.__node_matches(obj,type,attrs): candidates.append(obj) try: return candidates[no-1] except IndexError,e: raise XPointerFailedException("No matching node") def get_node(self): "Returns the located node." return self.__node def handle_abs_term(self,name,param): "Called to handle absolute location terms." if name=="root": if self.__node.nodeType != Node.DOCUMENT_NODE: raise XPointerFailedException("Expected document node") self.__node=self.__node.documentElement elif name=="origin": pass # Just work from current node elif name=="id": self.__node=ext.GetElementById(self.__node, param) elif name=="html": raise XPointerUnsupportedException("Term type 'html' unsupported.") def handle_rel_term(self,name,no,type,attrs): "Called to handle relative location terms." if name=="child": next=self.__get_child(no,type,attrs) elif name=="ancestor": next=self.__get_node(no,type,attrs,DOM.Node._get_parentNode) elif name=="psibling": next=self.__get_node(no,type,attrs,DOM.Node._get_previousSibling) elif name=="fsibling": next=self.__get_node(no,type,attrs,DOM.Node._get_nextSibling) elif name=="descendant": next=self.__get_node(no,type,attrs,DescendantIterator()) elif name=="following": next=self.__get_node(no,type,attrs,FollowingIterator()) self.__node=next self.__prev=name def handle_attr_term(self, attr_name): if __node.nodeType != Node.ELEMENT_NODE: raise XPointerFailedException("'attr' location term used from " "non-element node") if not self.__node.attributes.has_key(attr_name): raise XPointerFailedException("Non-existent attribute '%s' located" " by 'attr' term" % attr_name) self.__node=self.__node.attributes.getNamedItem(attr_name) def handle_string_term(self,no,skiplit,pos,length): raise XPointerUnsupportedException("'string' location terms not " "supported") def LocateNode(node, xpointer): try: xp=XDOMLocator(xpointer, node) xp.parse() return xp.get_node() except XPointerParseException,e: print "ERROR: "+str(e) PyXML-0.8.2/demo/genxml/0040755000076400001440000000000007614726123014141 5ustar martinusersPyXML-0.8.2/demo/genxml/README0100644000076400001440000000242307001374222015004 0ustar martinusersThis example demonstrates how to generate XML from non-XML data sources. This example is based directly on an example presented by Tom Gavin and Joseph E. Hughes at the August 1999 Washington DC SGML/XML User's Group meeting. PowerPoint slides containing the original DOM-based solution in Java are available at http://www.eccnet.com/sgmlug/. Since the specifics of reading other data formats vary greatly, this example will use a simple comma-separated-value format similar to that found as an "export" format for many applications which work with tabular data. A sample data file is contained in data.txt. The loaddata.py script demonstrates three different approaches to XML generation: DOM-based, SAX-based, and .write()-based. The first two approaches are specific to generating XML, while the third could be used to generate any format. It is interesting to note the differences in code size to get roughly the same output using each of the three approaches. The script's main() function does little but parse the command line, selecting the processing class appropriately. Processing consists of instantiating the processing class and calling its run() method. Concrete subclasses of the abstract processing class determine the actual machinery used to create the XML output. PyXML-0.8.2/demo/genxml/data.txt0100644000076400001440000000012407001374222015572 0ustar martinuserslname,fname,emp,manager Jones,Tom,1111,1111 Smith,John,2222,1111 Doe,Jane,3333,1111 PyXML-0.8.2/demo/genxml/loaddata.py0100644000076400001440000001762707165177650016304 0ustar martinusers#! /usr/bin/env python """ %(program)s -- example script to convert comma-separated value file to XML using the Document Object Model (DOM), the Simple API for XML (SAX), or the 'write' model (a bunch of calls to .write()). Usage: %(program)s [--dom|--sax|--write] [infile [outfile]] """ __version__ = '$Revision: 1.3 $' import getopt import os import string import sys # Note that we only need one of these for any given version of the # processing class. # from xml.dom.DOMImplementation import implementation import xml.sax.writer import xml.utils def main(): """Process command line parameters and run the conversion.""" inpath = "-" outpath = "-" args = sys.argv[1:] processor_class = DOMProcess try: opts, args = getopt.getopt(args, "dhsw", ["dom", "help", "sax", "write"]) except getopt.error, e: usage(err=e, rc=2) for opt, arg in opts: if opt in ("-d", "--dom"): processor_class = DOMProcess elif opt in ("-h", "--help"): usage() elif opt in ("-s", "--sax"): processor_class = SAXProcess elif opt in ("-w", "--write"): processor_class = WriteProcess if len(args) == 2: inpath, outpath = args elif len(args) == 1: inpath = args[0] elif len(args) == 0: pass else: usage(err="too many command-line arguments", rc=2) infp = get_input(inpath) outfp = get_output(outpath) processor = processor_class(infp, outfp) processor.run() infp.close() outfp.close() class BaseProcess: """Base class for the conversion processors. Each concrete subclass must provide the following methods: initOutput() Initialize the output stream and any internal data structures that the conversion process needs. addRecord(lname, fname, type) Add one record to the output stream (or the internal structures) where lname is the last name, fname is the first name, and type is either 'manager' or 'employee'. finishOutput() Finish all output generation. If all work has been on internal data structures, this is where they should be converted to text and written out. """ def __init__(self, infp, outfp): """Store the input and output streams for later use.""" self.infp = infp self.outfp = outfp def run(self): """Perform the complete conversion process. This method is responsible for parsing the input and calling the subclass-provided methods in the right order. """ self.initOutput() self.infp.readline() # ignore field names rec = self.getNextRecord() while rec: lname, fname, type = rec self.addRecord(lname, fname, type) rec = self.getNextRecord() self.finishOutput() def getNextRecord(self): """Read and return the next input record, or return None.""" line = self.infp.readline() if line: parts = map(string.strip, string.split(line, ',')) lname, fname, eid, mid = parts type = ("employee", "manager")[eid == mid] return lname, fname, type else: return None class DOMProcess(BaseProcess): """Concrete conversion process which uses a DOM structure as an internal data structure. Content is added to the DOM tree for each input record, and the entire tree is serialized and written to the output stream in the finishOutput() method. """ def initOutput(self): # Create a new document with no namespace uri, qualified name, # or document type self.document = implementation.createDocument(None,None,None) self.personnel = self.document.createElement("personnel") self.document.appendChild(self.personnel) def addRecord(self, lname, fname, type): doc = self.document self.personnel.appendChild(doc.createTextNode("\n ")) emp = doc.createElement("employee") emp.setAttribute("type", type) self.personnel.appendChild(emp) emp.appendChild(doc.createTextNode("\n ")) ln = doc.createElement("lname") ln.appendChild(doc.createTextNode(lname)) emp.appendChild(ln) emp.appendChild(doc.createTextNode("\n ")) fn = doc.createElement("fname") fn.appendChild(doc.createTextNode(fname)) emp.appendChild(fn) emp.appendChild(doc.createTextNode("\n ")) def finishOutput(self): t = self.document.createTextNode("\n") self.personnel.appendChild(t) # XXX toxml not supported by 4DOM # self.outfp.write(self.document.toxml()) xml.dom.ext.PrettyPrint(self.document, self.outfp) self.outfp.write("\n") class SAXProcess(BaseProcess): """Concrete conversion process that uses a SAX implementation that writes output to a file. XML is generated by calling the SAX methods that would be called when the resulting document instance is parsed. Data is written to the output stream incrementally with this approach, and no real internal state is maintained. """ def initOutput(self): info = xml.sax.writer.XMLDoctypeInfo() info.add_element_container("personnel") info.add_element_container("employee") saxout = self.saxout = xml.sax.writer.PrettyPrinter( self.outfp, dtdinfo=info) saxout.startDocument() saxout.startElement("personnel", {}) def addRecord(self, lname, fname, type): saxout = self.saxout saxout.startElement("employee", {"type": type}) saxout.startElement("lname", {}) saxout.characters(lname, 0, len(lname)) saxout.endElement("lname") saxout.startElement("fname", {}) saxout.characters(fname, 0, len(fname)) saxout.endElement("fname") saxout.endElement("employee") def finishOutput(self): self.saxout.endElement("personnel") self.saxout.endDocument() class WriteProcess(BaseProcess): """Concrete conversion process that simply formats the XML directly and uses the write() method of a file to write it out. The only helper function used to generate the XML is the xml.utils.escape() function; the methods of this class are solely responsible for proper formatting of the markup. """ # # Note the simplicity of using a bunch of write() calls; using print # statements would also be reasonable in many contexts. # def initOutput(self): self.outfp.write('\n') self.outfp.write("\n") def addRecord(self, lname, fname, type): self.outfp.write(' \n' % type) self.outfp.write(" %s\n" % xml.utils.escape(lname)) self.outfp.write(" %s\n" % xml.utils.escape(fname)) self.outfp.write(" \n") def finishOutput(self): self.outfp.write("\n") def get_input(path): """Get input file from path; '-' indicates stdin.""" if path == "-": return sys.stdin else: return open(path) def get_output(path): """Get output file from path; '-' indicates stdout.""" if path == "-": return sys.stdout else: return open(path, "w") def usage(err=None, rc=0): """Write out a usage message, possibly to stderr. If err or rc are true, the message is written to stderr instead of stdout. The script docstring is used as the source of help text. Exits with result code rc. """ if err or rc: sys.stdout = sys.stderr program = os.path.basename(sys.argv[0]) if err: print "%s: %s" % (program, str(err)) vars = {"program": program} print __doc__ % vars sys.exit(rc) if __name__ == "__main__": main() PyXML-0.8.2/demo/quotes/0040755000076400001440000000000007614726123014167 5ustar martinusersPyXML-0.8.2/demo/quotes/README0100644000076400001440000000163607175443715015057 0ustar martinusersThe files in this directory demonstrate maintaining a quotation collection in XML. The still-unnamed markup language contains 'quotation' elements, which contain the text of the quotation and optional 'author' and 'source' elements. For the quotation text, there are some simple semantic markups such as 'em', 'cite', and 'foreign'. quotations.dtd DTD for the markup language. sample.xml A sample quotation file. qtfmt.py Program to read a file marked up using the language specified in quotations.dtd, and output the list in HTML, text, or fortune format. The qtfmt.py script requires Python 2.0, since it assumes UTF-8 output and uses the codecs module to convert its output to Latin-1. Contact amk1@bigfoot.com if you have questions or comments about the contents of this directory. For the author's complete quotation collections, please go to http://starship.python.net/crew/amk/quotations/ PyXML-0.8.2/demo/quotes/qtfmt.py0100644000076400001440000003311007413602740015662 0ustar martinusers#!/usr/bin/env python # # qtfmt.py v1.10 # v1.10 : Updated to use Python 2.0 Unicode type. # # Read a document in the quotation DTD, converting it to a list of Quotation # objects. The list can then be output in several formats. __doc__ = """Usage: qtfmt.py [options] file1.xml file2.xml ... If no filenames are provided, standard input will be read. Available options: -f or --fortune Produce output for the fortune(1) program -h or --html Produce HTML output -t or --text Produce plain text output -m N or --max N Suppress quotations longer than N lines; defaults to 0, which suppresses no quotations at all. """ import string, re, cgi, types import codecs from xml.sax import saxlib, saxexts def simplify(t, indent="", width=79): """Strip out redundant spaces, and insert newlines to wrap the text at the given width.""" t = string.strip(t) t = re.sub('\s+', " ", t) if t=="": return t t = indent + t t2 = "" while len(t) > width: index = string.rfind(t, ' ', 0, width) if index == -1: t2 = t2 + t[:width] ; t = t[width:] else: t2 = t2 + t[:index] ; t = t[index+1:] t2 = t2 + '\n' return t2 + t class Quotation: """Encapsulates a single quotation. Attributes: stack -- used during construction and then deleted text -- A list of Text() instances, or subclasses of Text(), containing the text of the quotation. source -- A list of Text() instances, or subclasses of Text(), containing the source of the quotation. (Optional) author -- A list of Text() instances, or subclasses of Text(), containing the author of the quotation. (Optional) Methods: as_fortune() -- return the quotation formatted for fortune as_html() -- return an HTML version of the quotation as_text() -- return a plain text version of the quotation """ def __init__(self): self.stack = [ Text() ] self.text = [] def as_text(self): "Convert instance into a pure text form" output = "" def flatten(textobj): "Flatten a list of subclasses of Text into a list of paragraphs" if type(textobj) != types.ListType: textlist=[textobj] else: textlist = textobj paragraph = "" ; paralist = [] for t in textlist: if (isinstance(t, PreformattedText) or isinstance(t, CodeFormattedText) ): paralist.append(paragraph) paragraph = "" paralist.append(t) elif isinstance(t, Break): paragraph = paragraph + t.as_text() paralist.append(paragraph) paragraph = "" else: paragraph = paragraph + t.as_text() paralist.append(paragraph) return paralist # Flatten the list of instances into a list of paragraphs paralist = flatten(self.text) if len(paralist) > 1: indent = 2*" " else: indent = "" for para in paralist: if isinstance(para, PreformattedText) or isinstance(para, CodeFormattedText): output = output + para.as_text() else: output = output + simplify(para, indent) + '\n' attr = "" for i in ['author', 'source']: if hasattr(self, i): paralist = flatten(getattr(self, i)) text = string.join(paralist) if attr: attr = attr + ', ' text = string.lower(text[:1]) + text[1:] attr = attr + text attr=simplify(attr, width = 79 - 4 - 3) if attr: output = output + ' -- '+re.sub('\n', '\n ', attr) return output + '\n' def as_fortune(self): return self.as_text() + '%' def as_html(self): output = "

" def flatten(textobj): if type(textobj) != types.ListType: textlist = [textobj] else: textlist = textobj paragraph = "" ; paralist = [] for t in textlist: paragraph = paragraph + t.as_html() if isinstance(t, Break): paralist.append(paragraph) paragraph = "" paralist.append(paragraph) return paralist paralist = flatten(self.text) for para in paralist: output = output + string.strip(para) + '\n' attr = "" for i in ['author', 'source']: if hasattr(self, i): paralist = flatten(getattr(self, i)) text = string.join(paralist) attr=attr + ('

' % i) + string.strip(text) return output + attr # Text and its subclasses are used to hold chunks of text; instances # know how to display themselves as plain text or as HTML. class Text: "Plain text" def __init__(self, text=""): self.text = text # We need to allow adding a string to Text instances. def __add__(self, val): newtext = self.text + str(val) # __class__ must be used so subclasses create instances of themselves. return self.__class__(newtext) def __str__(self): return self.text def __repr__(self): s = string.strip(self.text) if len(s) > 15: s = s[0:15] + '...' return '<%s: "%s">' % (self.__class__.__name__, s) def as_text(self): return self.text def as_html(self): return cgi.escape(self.text) class PreformattedText(Text): "Text inside

...
" def as_text(self): return str(self.text) def as_html(self): return '
' + cgi.escape(str(self.text)) + '
' class CodeFormattedText(Text): "Text inside ..." def as_text(self): return str(self.text) def as_html(self): return '' + cgi.escape(str(self.text)) + '' class CitedText(Text): "Text inside ..." def as_text(self): return '_' + simplify(str(self.text)) + '_' def as_html(self): return '' + string.strip(cgi.escape(str(self.text))) + '' class ForeignText(Text): "Foreign words, from Latin or French or whatever." def as_text(self): return '_' + simplify(str(self.text)) + '_' def as_html(self): return '' + string.strip(cgi.escape(str(self.text))) + '' class EmphasizedText(Text): "Text inside ..." def as_text(self): return '*' + simplify(str(self.text)) + '*' def as_html(self): return '' + string.strip(cgi.escape(str(self.text))) + '' class Break(Text): def as_text(self): return "" def as_html(self): return "

" # The QuotationDocHandler class is a SAX handler class that will # convert a marked-up document using the quotations DTD into a list of # quotation objects. class QuotationDocHandler(saxlib.HandlerBase): def __init__(self, process_func): self.process_func = process_func self.newqt = None # Errors should be signaled, so we'll output a message and raise # the exception to stop processing def fatalError(self, exception): sys.stderr.write('ERROR: '+ str(exception)+'\n') sys.exit(1) error = fatalError warning = fatalError def characters(self, ch, start, length): if self.newqt != None: s = ch[start:start+length] # Undo the UTF-8 encoding, converting to ISO Latin1, which # is the default character set used for HTML. latin1_encode = codecs.lookup('iso-8859-1') [0] unicode_str = s s, consumed = latin1_encode( unicode_str ) assert consumed == len( unicode_str ) self.newqt.stack[-1] = self.newqt.stack[-1] + s def startDocument(self): self.quote_list = [] def startElement(self, name, attrs): methname = 'start_'+str(name) if hasattr(self, methname): method = getattr(self, methname) method(attrs) else: sys.stderr.write('unknown start tag: <' + name + ' ') for name, value in attrs.items(): sys.stderr.write(name + '=' + '"' + value + '" ') sys.stderr.write('>\n') def endElement(self, name): methname = 'end_'+str(name) if hasattr(self, methname): method = getattr(self, methname) method() else: sys.stderr.write('unknown end tag: \n') # There's nothing to be done for the tag def start_quotations(self, attrs): pass def end_quotations(self): pass def start_quotation(self, attrs): if self.newqt == None: self.newqt = Quotation() def end_quotation(self): st = self.newqt.stack for i in range(len(st)): if type(st[i]) == types.StringType: st[i] = Text(st[i]) self.newqt.text=self.newqt.text + st del self.newqt.stack if self.process_func: self.process_func(self.newqt) else: print "Completed quotation\n ", self.newqt.__dict__ self.newqt=Quotation() # Attributes of a quotation: ... and ... def start_author(self, data): # Add the current contents of the stack to the text of the quotation self.newqt.text = self.newqt.text + self.newqt.stack # Reset the stack self.newqt.stack = [ Text() ] def end_author(self): # Set the author attribute to contents of the stack; you can't # have more than one tag per quotation. self.newqt.author = self.newqt.stack # Reset the stack for more text. self.newqt.stack = [ Text() ] # The code for the tag is exactly parallel to that for def start_source(self, data): self.newqt.text = self.newqt.text + self.newqt.stack self.newqt.stack = [ Text() ] def end_source(self): self.newqt.source = self.newqt.stack self.newqt.stack = [ Text() ] # Text markups:
for breaks,

...
for preformatted # text, ... for emphasis, ... for citations. def start_br(self, data): # Add a Break instance, and a new Text instance. self.newqt.stack.append(Break()) self.newqt.stack.append( Text() ) def end_br(self): pass def start_pre(self, data): self.newqt.stack.append( Text() ) def end_pre(self): self.newqt.stack[-1] = PreformattedText(self.newqt.stack[-1]) self.newqt.stack.append( Text() ) def start_code(self, data): self.newqt.stack.append( Text() ) def end_code(self): self.newqt.stack[-1] = CodeFormattedText(self.newqt.stack[-1]) self.newqt.stack.append( Text() ) def start_em(self, data): self.newqt.stack.append( Text() ) def end_em(self): self.newqt.stack[-1] = EmphasizedText(self.newqt.stack[-1]) self.newqt.stack.append( Text() ) def start_cite(self, data): self.newqt.stack.append( Text() ) def end_cite(self): self.newqt.stack[-1] = CitedText(self.newqt.stack[-1]) self.newqt.stack.append( Text() ) def start_foreign(self, data): self.newqt.stack.append( Text() ) def end_foreign(self): self.newqt.stack[-1] = ForeignText(self.newqt.stack[-1]) self.newqt.stack.append( Text() ) if __name__ == '__main__': import sys, getopt # Process the command-line arguments opts, args = getopt.getopt(sys.argv[1:], 'fthm:r', ['fortune', 'text', 'html', 'max=', 'help', 'randomize'] ) # Set defaults maxlength = 0 ; method = 'as_fortune' randomize = 0 # Process arguments for opt, arg in opts: if opt in ['-f', '--fortune']: method='as_fortune' elif opt in ['-t', '--text']: method = 'as_text' elif opt in ['-h', '--html']: method = 'as_html' elif opt in ['-m', '--max']: maxlength = string.atoi(arg) elif opt in ['-r', '--randomize']: randomize = 1 elif opt == '--help': print __doc__ ; sys.exit(0) # This function will simply output each quotation by calling the # desired method, as long as it's not suppressed by a setting of # --max. qtlist = [] def process_func(qt, qtlist=qtlist, maxlength=maxlength, method=method): func = getattr(qt, method) output = func() length = string.count(output, '\n') if maxlength!=0 and length > maxlength: return qtlist.append(output) # Loop over the input files; use sys.stdin if no files are specified if len(args) == 0: args = [sys.stdin] for file in args: if type(file) == types.StringType: input = open(file, 'r') else: input = file # Enforce the use of the Expat parser, because the code needs to be # sure that the output will be UTF-8 encoded. p=saxexts.XMLParserFactory.make_parser(["xml.sax.drivers.drv_pyexpat"]) dh = QuotationDocHandler(process_func) p.setDocumentHandler(dh) p.setErrorHandler(dh) p.parseFile(input) if type(file) == types.StringType: input.close() p.close() # Randomize the order of the quotations if randomize: import whrandom q2 = [] for i in range(len(qtlist)): qt = whrandom.randint(0,len(qtlist)-1 ) q2.append( qtlist[qt] ) qtlist[qt:qt+1] = [] assert len(qtlist) == 0 qtlist = q2 for quote in qtlist: print quote # We're done! PyXML-0.8.2/demo/quotes/quotations.dtd0100644000076400001440000000176606772561171017105 0ustar martinusers PyXML-0.8.2/demo/quotes/sample.xml0100644000076400001440000000451207175443715016176 0ustar martinusers We will perhaps eventually be writing only small modules which are identified by name as they are used to build larger ones, so that devices like indentation, rather than delimiters, might become feasible for expressing local structure in the source language. Donald E. Knuth, "Structured Programming with goto Statements", Computing Surveys, Vol 6 No 4, Dec. 1974 I don't know a lot about this artificial life stuff -- but I'm suspicious of anything Newsweek gets goofy about -- and I suspect its primary use is as another money extraction tool to be applied by ai labs to the department of defense (and more power to 'em).
Nevertheless in wondering why free software is so good these days it occured to me that the propagation of free software is one gigantic artificial life evolution experiment, but the metaphor isn't perfect.
Programs are thrown out into the harsh environment, and the bad ones die. The good ones adapt rapidly and become very robust in short order.
The only problem with the metaphor is that the process isn't random at all. Python chooses to include tk's genes; Linux decides to make itself more suitable for symbiosis with X, etcetera.
Free software is artificial life, but better. Aaron Watters, 29 Sep 2025
It has also been referred to as the "Don Beaudry hack," but that's a misnomer. There's nothing hackish about it -- in fact, it is rather elegant and deep, even though there's something dark to it. Guido van Rossum, Metaclass Programming in Python 1.5 This is not a technical issue so much as a human issue; we are limited and so is our time. (Is this a bug or a feature of time? Careful; trick question!) Fred Drake on the Documentation SIG, 9 Sep 2025 Counting is the most simple and primitive of narratives -- 1 2 3 4 5 6 7 8 9 10 -- a tale with a beginning, a middle and an end and a sense of progression -- arriving at a finish of two digits -- a goal attained, a denouement reached. Peter Greenaway Fear of Drowning By Numbers (1988)
PyXML-0.8.2/demo/sax/0040755000076400001440000000000007614726123013442 5ustar martinusersPyXML-0.8.2/demo/sax/README0100644000076400001440000000205707165434556014332 0ustar martinusersThese examples demonstrate the Python SAX API, version 1. In all examples, the sax driver can be specified by setting the PY_SAX_PARSER environment variable. Valid settings are - xml.sax.drivers.drv_pyexpat - xml.sax.drivers.drw_xmlproc - xml.sax.drivers.drv_sgmlop as well as any other driver listed in the xml/sax/drivers directory. sax2obj.py ??? saxdemo.py Parses an XML file, and prints it in canonical form. Invoke as 'python saxdemo.py filename.xml'. The standard driver will be pyexpat. Alternative drivers can be specified with the -d option of saxdemo.py; the prefix 'xml.sax.drivers.drv_' is automatically added to the driver. saxhack.py appears to be broken saxstats.py Prints statistics about an xml file. saxtimer.py Times parsing a document; arguments are the parser name (the prefix 'xml.sax.drivers.drv_' is automatically added) and the document name. saxtrace.py parses a document using xmlproc, and prints all SAX events.PyXML-0.8.2/demo/sax/sax2obj.py0100644000076400001440000001023307413602740015353 0ustar martinusers""" A general XML element -> Python object converter based on SAX. """ from xml.sax import saxexts,saxlib,saxutils import re,string reg_ws=re.compile("[%s]+" % string.whitespace) class ConvSpec: """Contains the information needed to convert SAX events to Python objects.""" def __init__(self): pass class SAXObject: def __init__(self): self._fields={} def has_field(self,field): return self._fields.has_key(field) def get_fields(self): return self._fields.keys() def get_field(self,field): return self._fields[field] def set_field(self,field,value): self._fields[field]=value def display(self): for field in self._fields.keys(): print "%s=%s" % (field,self._fields[field]) def __getattr__(self,attr): try: return self._fields[attr] except KeyError,e: raise AttributeError(str(e)) def __cmp__(self,obj): if id(obj)==id(self): return 0 else: return 1 class DocHandler(saxlib.DocumentHandler): def __init__(self,target_elem,list_elems,ign_elems,rep_field): self.target_elem=target_elem self.list_elems=list_elems self.ign_elems=ign_elems self.rep_field=rep_field self.ignoring=0 self.objects=[] self.current=None self.cur_data="" self.stack=[] def startElement(self,name,attrs): if self.ignoring: return if name==self.target_elem: self.current=SAXObject() for attr in attrs: self.current.set_field(attr,attrs[attr]) elif self.list_elems.has_key(name): if not self.current.has_field(name): self.current.set_field(name,[]) self.stack.append(self.current) self.current=SAXObject() elif self.rep_field.has_key(name) and not self.current.has_field(name): self.current.set_field(name,[]) else: if self.ign_elems.has_key(name): self.ignoring=self.ignoring+1 self.cur_data="" def characters(self,data,start,length): if self.ignoring or self.current==None: return data=data[start:start+length] mo=reg_ws.match(data) if mo!=None and mo.end(0)==len(data): return self.cur_data=self.cur_data+data def endElement(self,name): if self.ign_elems.has_key(name): self.ignoring=self.ignoring-1 return if self.ignoring or self.current==None: return if name==self.target_elem: self.objects.append(self.current) self.current=None elif self.list_elems.has_key(name): obj=self.current self.current=self.stack[-1] del self.stack[-1] self.current.get_field(name).append(obj) elif self.rep_field.has_key(name): self.current.get_field(name).append(self.cur_data) else: self.current.set_field(name,self.cur_data) def get_objects(self): return self.objects def make_objects(url,element,list_elems={},ign_elems={},rep_field={}): dh=DocHandler(element,list_elems,ign_elems,rep_field) eh=saxutils.ErrorPrinter() parser=saxexts.make_parser() parser.setDocumentHandler(dh) parser.setErrorHandler(eh) parser.parse(url) return dh.get_objects() def make_xml(filename,root_elem,trgt_elem,list): out=open(filename,"w") out.write("<%s>\n" % root_elem) for obj in list: out.write(" <%s>\n" % trgt_elem) for field in obj.get_fields(): out.write(" <%s>%s\n" % \ (field,escape_markup(obj.get_field(field)),field)) out.write(" \n" % trgt_elem) out.write("\n" % root_elem) out.close() def list2hash(lst,key_field): hash={} for obj in lst: hash[obj.get_field(key_field)]=obj return hash def escape_markup(str): out="" for ch in str: if ch=="<": out=out+"<" elif ch==">": out=out+">" else: out=out+ch return out PyXML-0.8.2/demo/sax/saxdemo.py0100644000076400001440000000314507534565152015460 0ustar martinusers# A demo SAX application: using SAX to parse XML documents into ESIS # or canonical XML. from xml.sax import saxexts, saxlib, saxutils import sys,urllib2,getopt ### Interpreting arguments (rather crudely) try: (args,trail)=getopt.getopt(sys.argv[1:],"sed:") assert trail, "No argument provided" except Exception,e: print "ERROR: %s" % e print print "Usage: python saxdemo.py [-e] [-d drv] filename [outfilename]" print print " -e: Output ESIS instead of normalized XML." print " -s: Silent (no messages except error messages)" print " -d: Use driver 'drv', where 'drv' is a module name." print " outfilename: Write to this file." sys.exit(1) driver=None esis=0 silent=0 in_sysID=trail[0] if len(trail)==2: out_sysID=trail[1] else: out_sysID="" for (arg,val) in args: if arg=="-d": driver="xml.sax.drivers.drv_" + val elif arg=="-e": esis=1 elif arg=="-s": silent=1 p=saxexts.make_parser(driver) p.setErrorHandler(saxutils.ErrorPrinter()) if out_sysID=="": out=sys.stdout else: try: out=urllib2.urlopen(out_sysID) except IOError,e: print out_sysID+": "+str(e) if esis: dh=saxutils.ESISDocHandler(out) else: dh=saxutils.Canonizer(out) ### Ready. Let's go! if not silent: print "Parser: %s (%s, %s)" % (p.get_parser_name(),p.get_parser_version(), p.get_driver_version()) print try: p.setDocumentHandler(dh) p.parse(in_sysID) except IOError,e: print in_sysID+": "+str(e) except saxlib.SAXException,e: print str(e) ### Cleaning up. out.close() PyXML-0.8.2/demo/sax/saxhack.py0100644000076400001440000000676107413602734015443 0ustar martinusers# # # $Id: saxhack.py,v 1.5 2024/12/30 12:17:32 loewis Exp $ # # illustrate how a saxlib parser can interface directly to sgmlop # # history: # 98-05-23 fl created (derived from the coreXML parser) # # Copyright (c) 1998 by Secret Labs AB # # info@pythonware.com # http://www.pythonware.com # from xml.sax.saxlib import HandlerBase class DocumentHandler:#(HandlerBase): # SAX interface def startElement(self, tag, attrs): pass # print "start", tag def endElement(self, tag): pass # print "end", tag def characters(self, text, start, len): pass # print "data", text[start:start+len] # -------------------------------------------------------------------- # sgmlop-based parser from xml.parsers import sgmlop class Parser: def setDocumentHandler(self, dh): self.parser = sgmlop.XMLParser() self.parser.register(dh, 1) def parseFile(self, file): parser = self.parser while 1: data = file.read(16384) if not data: break parser.feed(data) parser.close() # -------------------------------------------------------------------- # xmllib-based parser from xml.parsers import xmllib class xmllibParser(xmllib.XMLParser): def setDocumentHandler(self, dh): self.characters = dh.characters self.unknown_starttag = dh.startElement self.unknown_endtag = dh.endElement def handle_data(self, data): self.characters(data, 0, len(data)) def parseFile(self, file): while 1: data = file.read(16384) if not data: break self.feed(data) self.close() # -------------------------------------------------------------------- # original xmllib-based parser class slowParser(xmllib.SlowXMLParser): def setDocumentHandler(self, dh): self.characters = dh.characters self.unknown_starttag = dh.startElement self.unknown_endtag = dh.endElement def handle_data(self, data): self.characters(data, 0, len(data)) def parseFile(self, file): while 1: data = file.read(16384) if not data: break self.feed(data) file.close() # ==================================================================== # test stuff import time, os, sys if len(sys.argv) == 1: print 'Usage: saxhack.py ' sys.exit(1) FILE = sys.argv[1] size = os.stat(FILE)[6] p = Parser() dh = DocumentHandler() p.setDocumentHandler(dh) f = open(FILE) t = time.clock() p.parseFile(f) # dry run t_direct = time.clock() - t f.close() #import sys ; sys.exit(0) print t_direct if t_direct == 0: print 'Measured time was too small; use a larger XML file' sys.exit(1) print "sgmlop:", int(size / t_direct), "bytes per second" p = xmllibParser() #p=slowParser() dh = DocumentHandler() p.setDocumentHandler(dh) f = open(FILE) t = time.clock() p.parseFile(f) # dry run t_fast = time.clock() - t f.close() print "xmllib:", int(size / t_fast), "bytes per second" p = slowParser() dh = DocumentHandler() p.setDocumentHandler(dh) f = open(FILE) t = time.clock() p.parseFile(f) # dry run t_slow = time.clock() - t f.close() print "slow xmllib:", int(size / t_slow), "bytes per second" print print "normalized timings:" print "slow xmllib", 1.0 print "fast xmllib", round(t_fast / t_slow, 2), "(%sx)" % round(t_slow / t_fast, 1) print "sgmlop ", round(t_direct / t_slow, 2), "(%sx)" % round(t_slow / t_direct, 1) print PyXML-0.8.2/demo/sax/saxstats.py0100644000076400001440000000220407413602740015654 0ustar martinusers# A simple SAX application that counts the number of elements, attributes and # processing instructions in a document. from xml.sax import saxexts from xml.sax import saxlib import sys class CounterHandler(saxlib.DocumentHandler): def __init__(self): self.elems=0 self.attrs=0 self.pis=0 def startElement(self,name,attrs): self.elems=self.elems+1 self.attrs=self.attrs+len(attrs) def processingInstruction(self,target,data): self.pis=self.pis+1 # --- Main prog if len(sys.argv)<2: print "Usage: python saxstats.py " print print " : file name of the document to parse" sys.exit(1) # Load parser and driver print "\nLoading parser..." p=saxexts.make_parser() ch=CounterHandler() p.setDocumentHandler(ch) # Ready, set, go! print "Starting parse..." OK=0 try: p.parse(sys.argv[1]) OK=1 except IOError,e: print "\nERROR: "+sys.argv[1]+": "+str(e) except saxlib.SAXException,e: print "\nERROR: "+str(e) print "Parse complete:" print " Elements: %d" % ch.elems print " Attributes: %d" % ch.attrs print " Proc instrs: %d" % ch.pis PyXML-0.8.2/demo/sax/saxtimer.py0100644000076400001440000000206407413602740015642 0ustar martinusers# A simple SAX application that measures the time spent parsing a # document with an empty document handler. from xml.sax import saxexts from xml.sax import saxlib import sys,time if len(sys.argv)<3: print "Usage: python " print print " : file name of the document to parse" print " : driver package name" sys.exit(1) # Load parser and driver print "\nLoading parser..." try: p=saxexts.make_parser("xml.sax.drivers.drv_" + sys.argv[1]) except saxlib.SAXException,e: print "ERROR: Parser not available" sys.exit(1) # Ready, set, go! sum=0 print "Starting parse..." for ix in range(3): start=time.clock() OK=0 pt=0 try: p.parse(sys.argv[2]) pt=time.clock()-start OK=1 except IOError,e: print "\nERROR: "+sys.argv[2]+": "+str(e) except saxlib.SAXException,e: print "\nERROR: "+str(e) if OK: print "Parse time: "+`pt` else: print "Error occurred, parse aborted." sum=sum+pt print "Average: %f" % (sum/3.0) PyXML-0.8.2/demo/sax/saxtrace.py0100644000076400001440000000351407413602740015621 0ustar martinusers""" A minimal SAX application that just prints out the document-handler events it receives. """ import sys from xml.sax import saxexts # --- SAXtracer class SAXtracer: def __init__(self,objname): self.objname=objname self.met_name="" def __getattr__(self,name): self.met_name=name # UGLY! :) return self.trace def error(self,exception): print "err_handler.error(%s)" % str(exception) def fatalError(self,exception): print "err_handler.fatalError(%s)" % str(exception) def warning(self,exception): print "err_handler.warning(%s)" % str(exception) def characters(self,data,start,length): print "doc_handler.characters(%s,%d,%d)" % (`data[start:start+length]`, start,length) def ignorableWhitespace(self,data,start,length): print "doc_handler.ignorableWhitespace(%s,%d,%d)" % \ (`data[start:start+length]`,start,length) def startElement(self, name, attrs): attr_str="{" for attr in attrs: attr_str="%s '%s':'%s'," % (attr_str,attr,attrs[attr]) if attr_str=="{": attr_str="{}" else: attr_str=attr_str[:-1]+" }" print "doc_handler.startElement('%s',%s)" % (name,attr_str) def trace(self,*rest): str="%s.%s(" % (self.objname,self.met_name) for param in rest[:-1]: str=str+`param`+", " if len(rest)>0: print str+`rest[-1]`+")" else: print str+")" # --- Main prog pf=saxexts.ParserFactory() p=pf.make_parser("xml.sax.drivers.drv_xmlproc") p.setDocumentHandler(SAXtracer("doc_handler")) p.setDTDHandler(SAXtracer("dtd_handler")) p.setErrorHandler(SAXtracer("err_handler")) p.setEntityResolver(SAXtracer("ent_handler")) p.parse(sys.argv[1]) PyXML-0.8.2/demo/sgmlop/0040755000076400001440000000000007614726123014150 5ustar martinusersPyXML-0.8.2/demo/sgmlop/benchsgml.py0100644000076400001440000000400607413602740016454 0ustar martinusers# benchmark import time from xml.parsers import sgmlop import sgmllib SIZE = 16384 FILE = "test2.htm" bytes = len(open(FILE).read()) def t1(): fp = open(FILE) parser = sgmllib.SlowSGMLParser() while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() def t2(): fp = open(FILE) parser = sgmllib.FastSGMLParser() while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() def t3(): fp = open(FILE) parser = sgmlop.SGMLParser() while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() class Dummy: def finish_starttag(self, tag, data): pass def finish_endtag(self, tag): pass def handle_entityref(self, data): pass def handle_data(self, data): pass def t4(): fp = open(FILE) parser = sgmlop.SGMLParser() parser.register(Dummy()) while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() t = time.time() t1(); t1(); t1(); t1(); t1(); t1(); t1(); t1(); t1(); t1(); t = (time.time() - t) / 10 print "t1:", t if t: print int(bytes / t), "bytes per second" t = time.time() t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t2(); t = (time.time() - t) / 20 print "t2:", t if t: print int(bytes / t), "bytes per second" t = time.time() t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t3(); t = (time.time() - t) / 20 print "t3:", t if t: print int(bytes / t), "bytes per second" t = time.time() t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t4(); t = (time.time() - t) / 20 print "t4:", t if t: print int(bytes / t), "bytes per second" PyXML-0.8.2/demo/sgmlop/benchxml.py0100644000076400001440000001060307413602740016312 0ustar martinusers# benchmark import time, sys, os from xml.parsers import xmllib, sgmlop SIZE = 16384 FILE = "hamlet.xml" try: FILE = sys.argv[1] except IndexError: pass print "---", FILE, "---" bytes = os.stat(FILE)[6] # -------------------------------------------------------------------- # 1) sgmlop with null parser (no registered callbacks) def test1(): fp = open(FILE) parser = sgmlop.XMLParser() while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() # -------------------------------------------------------------------- # 2) sgmlop with dummy parser class sgmlopDummy: def finish_starttag(self, tag, data): pass def finish_endtag(self, tag): pass def handle_entityref(self, data): pass def handle_data(self, data): pass def handle_proc(self, name, data): pass def handle_cdata(self, data): pass def handle_charref(self, data): pass def handle_comment(self, data): pass def handle_special(self, data): pass def test2(): fp = open(FILE) out = sgmlopDummy() parser = sgmlop.XMLParser() parser.register(out) while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() # -------------------------------------------------------------------- # 3) accelerated xmllib class FastXMLParser(xmllib.FastXMLParser): def unknown_starttag(self, tag, data): pass def unknown_endtag(self, tag): pass def handle_entityref(self, data): pass def handle_data(self, data): pass def handle_cdata(self, data): pass def test3(): fp = open(FILE) parser = FastXMLParser() while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() # -------------------------------------------------------------------- # 4) old xmllib class SlowXMLParser(xmllib.SlowXMLParser): def unknown_starttag(self, tag, data): pass def unknown_endtag(self, tag): pass def handle_entityref(self, data): pass def handle_data(self, data): pass def handle_cdata(self, data): pass def test4(): fp = open(FILE) parser = SlowXMLParser() while 1: data = fp.read(SIZE) if not data: break parser.feed(data) parser.close() fp.close() # -------------------------------------------------------------------- # 5) xmltok parser try: import xmltok except (ImportError, SystemError): xmltok = None class xmltokDummy: def do_tag(self, tag, data): pass def do_endtag(self, tag): pass def do_entity(self, tag, data): pass def do_data(self, data): pass def test5(): fp = open(FILE) out = xmltokDummy() parser = xmltok.ParserCreate() parser.StartElementHandler = out.do_tag parser.EndElementHandler = out.do_endtag parser.CharacterDataHandler = out.do_data parser.ProcessingInstructionHandler = out.do_entity while 1: data = fp.read(SIZE) if not data: break parser.Parse(data) parser.Parse("", 1) fp.close() # ==================================================================== # main test = test1 t = time.clock() test(); test(); test(); test(); test(); t = (time.clock() - t) / 5 print "sgmlop/null parser:", round(t, 3), "seconds;", print int(bytes / t), "bytes per second" time1 = t test = test2 t = time.clock() test(); test(); test(); test(); test(); t = (time.clock() - t) / 5 print "sgmlop/dummy parser:", round(t, 3), "seconds;", print int(bytes / t), "bytes per second" time2 = t test = test3 t = time.clock() test(); test(); t = (time.clock() - t) / 2 print "xmllib/fast parser:", round(t, 3), "seconds;", print int(bytes / t), "bytes per second" time3 = t test = test4 t = time.clock() test(); t = (time.clock() - t) / 1 print "xmllib/slow parser:", round(t, 3), "seconds;", print int(bytes / t), "bytes per second" time4 = t print print "normalized timings:" print "slow xmllib ", 1.0 print "fast xmllib ", round(time3/time4, 3), "(%sx)" % round(time4/time3, 1) print "sgmlop dummy", round(time2/time4, 3), "(%sx)" % round(time4/time2, 1) print "sgmlop null ", round(time1/time4, 3), "(%sx)" % round(time4/time1, 1) print PyXML-0.8.2/demo/sgmlop/test2.htm0100644000076400001440000000000006631372347015711 0ustar martinusersPyXML-0.8.2/demo/sgmlop/testxml1.py0100644000076400001440000001340707413574667016320 0ustar martinusers# basic tests import sys import time, string from xml.parsers import sgmlop try: from xml.parsers import xmllib have_xmllib = 1 except ImportError: have_xmllib = 0 class xmllib: class FastXMLParser:pass class SlowXMLParser:pass try: FILE, VERBOSE = sys.argv[1], 2 except IndexError: FILE, VERBOSE = "hamlet.xml", 1 print print "test collecting parsers on", FILE print # -------------------------------------------------------------------- # sgmlop class myCollector: def __init__(self): self.data = [] self.text = [] def finish_starttag(self, tag, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append(("start", tag, data)) def handle_proc(self, tag, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append(("pi", tag, data)) def handle_special(self, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append(("special", data)) def handle_entityref(self, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append(("entity", data)) def handle_data(self, data): self.text.append(data) def handle_cdata(self, data): self.text.append("CDATA" + data) t = time.clock() for i in range(1000): out = myCollector() fp = open(FILE) parser = sgmlop.XMLUnicodeParser() parser.register(out) b = 0 while 1: data = fp.read(1024) if not data: break parser.feed(data) b = b + len(data) parser.close() t1 = time.clock() - t print "raw sgmlop:", len(out.data), "items;", round(t1, 3), "seconds;", print round(b / t1 / 1024, 2), "kbytes per second" print out.data # -------------------------------------------------------------------- # xmllib class FastXMLParser(xmllib.FastXMLParser): def __init__(self): xmllib.FastXMLParser.__init__(self) self.data = [] self.text = [] def unknown_starttag(self, tag, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("start", tag, data) def handle_proc(self, tag, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("pi", tag, data) def handle_special(self, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("special", data) def handle_entityref(self, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("entity", data) def handle_data(self, data): self.text.append(data) def handle_cdata(self, data): self.text.append("CDATA" + data) if have_xmllib: t = time.clock() for i in range(1): fp = open(FILE) parser2 = FastXMLParser() b = 0 while 1: data = fp.read(1024) if not data: break parser2.feed(data) b = b + len(data) parser2.close() t2 = time.clock() - t print "fast xmllib:", len(parser2.data), "items;", round(t2, 3), "seconds;", print round(b / t2 / 1024, 2), "kbytes per second" class SlowXMLParser(xmllib.SlowXMLParser): def __init__(self): xmllib.SlowXMLParser.__init__(self) self.data = [] self.text = [] def unknown_starttag(self, tag, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("start", tag, data) def handle_proc(self, tag, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("pi", tag, data) def handle_special(self, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("special", data) def handle_entityref(self, data): if self.text: self.data.append(repr(string.join(self.text, ""))) self.text = [] self.data.append("entity", data) def handle_data(self, data): self.text.append(data) def handle_cdata(self, data): self.text.append("CDATA" + data) if have_xmllib: t = time.clock() for i in range(1): fp = open(FILE) parser3 = SlowXMLParser() b = 0 while 1: data = fp.read(1024) if not data: break parser3.feed(data) b = b + len(data) parser3.close() t3 = time.clock() - t print "slow xmllib:", len(parser3.data), "items;", round(t3, 3), "seconds;", print round(b / t3 / 1024, 2), "kbytes per second" print print "normalized timing:" print "slow xmllib", 1.0 print "fast xmllib", round(t2 / t3, 2), "(%sx)" % round(t3 / t2, 1) print "sgmlop ", round(t1 / t3, 2), "(%sx)" % round(t3 / t1, 1) print print "looking for differences:" items = min(len(parser2.data), len(parser3.data)) for i in xrange(items): if parser2.data[i] != parser3.data[i]: for j in range(max(i-5, 0), min(i+5, items)): if parser2.data[j] != parser3.data[j]: print "+", j+1, parser2.data[j] print "*", j+1, parser3.data[j] else: print "=", j+1, parser2.data[j] break else: print " (none found)" PyXML-0.8.2/demo/sgmlop/testxml2.py0100644000076400001440000000262506635616746016321 0ustar martinusers# dry runs from xml.parsers import xmllib, sgmlop import sys import time, string try: FILE, VERBOSE = sys.argv[1], 2 except IndexError: FILE, VERBOSE = "hamlet.xml", 1 BLOCK = 16384 print print "test empty parsers on", FILE print t = time.clock() b = 0 for i in range(1): fp = open(FILE) parser = sgmlop.XMLParser() while 1: data = fp.read(BLOCK) if not data: break parser.feed(data) b = b + len(data) parser.close() t1 = time.clock() - t print "sgmlop", round(t1, 3), "seconds;", print round(b / t1 / 1024, 2), "kbytes per second" t = time.clock() b = 0 for i in range(1): fp = open(FILE) parser = xmllib.FastXMLParser() while 1: data = fp.read(BLOCK) if not data: break parser.feed(data) b = b + len(data) parser.close() t2 = time.clock() - t print "fast xmllib", round(t2, 3), "seconds;", print round(b / t2 / 1024, 2), "kbytes per second" t = time.clock() b = 0 for i in range(1): fp = open(FILE) parser = xmllib.SlowXMLParser() while 1: data = fp.read(BLOCK) if not data: break parser.feed(data) b = b + len(data) parser.close() t3 = time.clock() - t print "slow xmllib", round(t3, 3), "seconds;", print round(b / t3 / 1024, 2), "kbytes per second" print print "sgmlop is", round(t3 / t1, 2), "times faster than slow xmllib" PyXML-0.8.2/demo/xbel/0040755000076400001440000000000007614726123013601 5ustar martinusersPyXML-0.8.2/demo/xbel/doc/0040755000076400001440000000000007614726123014346 5ustar martinusersPyXML-0.8.2/demo/xbel/doc/xbel.bib0100644000076400001440000000700306620203620015737 0ustar martinusers% This is the bibliography database for the XBEL report. @book(unicode20, title = "The {U}nicode Standard, Version 2.0", author = "The {U}nicode Consotium", publisher = "Addison-Wesley Developers Press", address = "Reading, MA", year = "1996", isbn = "0-201-48345-9" ) @techreport(unicode21, title = "The {U}nicode Standard, Version 2.1", author = "The {U}nicode Consortium", institution = "The {U}nicode Consortium", year = "1998", month = "Sep", number = "8", address = "San Jose, CA", note = "\url{http://www.unicode.org/unicode/reports/tr8.html}" ) @book(iso8601, title = "Data elements and interchange formats --- Information interchange --- Representation of dates and times", author = "International Organization for Standardization", publisher = "International Organization for Standardization", year = "1988" ) @techreport(w3c-xml, author = "Tim Bray and Jean Paoli and C. M. Sperberg-McQueen", title = "Extensible Markup Language ({XML}) 1.0", institution = "World Wide Web Consortium", type = "Recommendation", year = "1998", month = "Feb", note = "\url{http://www.w3.org/TR/REC-xml}" ) @techreport(w3c-xml-names, author = "Tim Bray and Dave Hollander and Andrew Layman", title = "Namespaces in {XML}", institution = "World Wide Web Consortium", type = "Working Draft", year = "1998", month = "Sep", note = "\url{http://www.w3.org/TR/WD-xml-names}" ) @techreport(w3c-rdf-syntax, author = "Ora Lassila and Ralph R. Swick", title = "Resource Description Framework ({RDF}) Model and Syntax Specification", institution = "World Wide Web Consortium", type = "Working Draft", year = "1998", month = "Oct", note = "\url{http://www.w3.org/TR/WD-rdf-syntax}" ) @techreport(w3c-rdf-schema, author = "Dan Brickley and R. V. Guha and Andrew Layman", title = "Resource Description Framework ({RDF}) Schema Specification", institution = "World Wide Web Consortium", type = "Working Draft", year = "1998", month = "Aug", note = "\url{http://www.w3.org/TR/WD-rdf-schema}" ) @techreport(w3c-datetime, author = "Misha Wolf and Charles Wicksteed", title = "Date and Time Formats", institution = "World Wide Web Consortium", type = "Technical note", year = "1998", month = "Sep", note = "\url{http://www.w3.org/TR/WD-rdf-schema}" ) @manual(w3c-xmlspec, author = "Eve Maler", title = "W3C XML Specification DTD (`XMLspec')", organization = "World Wide Web Consortium", month = "Sep", year = "1998", note = "\url{http://www.w3.org/XML/1998/06/xmlspec-report-19980910.htm}" ) @misc(iso8601-houston, author = "Gary Houston", title = "{ISO} 8601 Date/Time Representations", year = "1993", month = "Jan", note = "\url{ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/ISO8601.ps.Z}" ) @misc(iso8601-kuhn, author = "Markus Kuhn", title = "A Summary of the International Standard Date and Time Notation", year = "1998", month = "Sep", note = "\url{http://www.cl.cam.ac.uk/~mgk25/iso-time.html}" ) % The "author" field here is completely bogus: @misc(dublin-core, title = "Dublin Core Metadata", author = "{Dublin Core Working Group}", year = "1997", month = "Nov", note = "\url{http://purl.oclc.org/metadata/dublin_core/}" ) @misc(python-xml, title = "Python and {XML} Processing", author = "Andrew M. Kuchling", note = "\url{http://www.python.org/topics/xml/}" ) @misc(xbel-home, title = "The {XML} Bookmark Exchange Language Resource Page", author = "Drake, Jr., Fred L.", note = "\url{http://www.python.org/topics/xml/xbel/}" ) PyXML-0.8.2/demo/xbel/doc/xbel.tex0100644000076400001440000007751407263756426016046 0ustar martinusers% When generating HTML, use: % mkhowto --html --iconserver . --split 4 --link 2 xbel % % The catch: % You have to be running the version of mkhowto from the Python % 1.5.2 (post-alpha2) tree, since that's when I added bibtex % support. ;-) \documentclass{howto} \usepackage{verbatim} % define some local macros: \newcommand{\element}[1]{\texttt{<#1>}} \newcommand{\attribute}[1]{\texttt{#1}} \newcommand{\nmtoken}[1]{\texttt{#1}} \newcommand{\paramentity}[1]{\texttt{\char`\%#1;}} \newenvironment{longexample} {\begingroup\small} {\endgroup} \newcommand{\contributor}[2]{\term{#1 \textnormal{(\email{#2})}}} \newenvironment{contributorlist} {\begin{definitions}} {\end{definitions}} \title{The XML Bookmark Exchange Language} \author{Fred L. Drake, Jr.} \authoraddress{ PythonLabs at Digital Creations \\ E-mail: \email{fdrake@acm.org} } \date{\today} % XXX update before release! \release{1.1} \setshortversion{1.1} \begin{document} \maketitle \begin{abstract} \noindent The XML Bookmark Exchange Language (XBEL) is a rich interchange format for ``bookmark'' data as used by most Internet browsers. This document describes the origin of the design, the requirements which drove the design process, and the resulting document type. \end{abstract} \tableofcontents \section{Introduction \label{intro}} The XML Bookmark Exchange Language, or XBEL, is an interchange format for the hierarchical bookmark data used by current Internet browsers. It is defined as an application of the Extensible Markup Language, or XML \cite{w3c-xml}. This section descibes the origin of the effort which created the XML Bookmark Exchange Language (XBEL), identifies the contributors, and provides information on the availability of the public text of the DTD and additional documentation on the applications which support XBEL. \subsection{Origins \label{origins}} The XML Bookmark Exchange Language is a product of the Python XML Special Interest Group (XML-SIG). The initial intent of the XBEL effort was to create a demonstration of XML facilities available to Python programmers which would also be useful. \subsection{Contributors \label{contrib}} The initial idea for XBEL was contributed by Mark Hammond. Mark sent his idea to the Python XML-SIG mailing list. This was closely followed by discussions and additional ideas by many of the list participants. The following people contributed to the design of the DTD and the related software (listed in alphabetical order by last name): \begin{contributorlist} \contributor{Fred L. Drake, Jr.}{fdrake@acm.org} Documentation. Design input on DTD and the storage of metadata. Implemented direct support for XBEL in Grail. \contributor{David Faure}{david@mandrakesoft.com} Suggested adding the \attribute{icon} attribute to \element{folder} and \element{bookmark} elements, and \attribute{icon} to \element{folder}. Implemented XBEL in the Konqueror file manager for the K Desktop Envionment (KDE). \contributor{Stefane Fermigier}{fermigie@math.jussieu.fr} Modified implementation of software for Internet Explorer Favorites conversion using his original Python DOM implementation. \contributor{Lars Marius Garshol}{larsga@garshol.priv.no} Extended the concept to cover all Internet browsers bookmarks and came up with the name and acronym. Implemented support for Navigator and Opera bookmark formats. \contributor{Geir Ove Gr{\o}nmo}{grove@infotek.no} General input on XML and the desired level of complexity. \contributor{Marc van Grootel}{bwaumg@urc.tue.nl} Design input on the DTD, storage of metadata, and comments on the use of XBEL with architectural forms. \contributor{Mark Hammond}{MHammond@skippinet.com.au} Original concept and DTD for an archival storage format for Internet Explorer ``Favorites.'' \contributor{Jack Jansen}{Jack.Jansen@cwi.nl} General input on potential advanced applications. \contributor{Andrew M. Kuchling}{akuchling@acm.org} Implemented conversion software between XBEL and Lynx bookmarks. \contributor{Fredrik Lundh}{fredrik@pythonware.com} Initial software implementation for Internet Explorer. \contributor{Sean McGrath}{digitome@iol.ie} General input on XML and document type definitions. \contributor{Greg Stein}{gstein@lyra.org} General input on XML Namespaces and moderator of complexity. \contributor{Walter R. Underwood}{wunder@infoseek.com} General input on the use of XML character entites instead of adding general entities, and discussion on date/time values in XML. \end{contributorlist} \subsection{Availability \label{availability}} Information on XBEL, including the public text and this document, is available on the Python XML-SIG Web site at \url{http://pyxml.sourceforge.net/topics/xml/xbel/} \cite{xbel-home}. Please refer to this Web resource for information on new versions, DTD variants, and supporting software. The public text for XBEL will be made available through a SOCAT catalog at available at: \url{http://pyxml.sourceforge.net/topics/xml/dtds/catalog}. This catalog may be used by including a DELEGATE entry in a catalog already used by XML processing software. The DELEGATE entry should be: \begin{verbatim} DELEGATE "+//IDN python.org" "http://www.python.org/topics/xml/dtds/catalog" \end{verbatim} \subsection{Formal Identification \label{formal-ident}} The XBEL DTD documented in this report has the Formal Public Identifier: \begin{verbatim} +//IDN python.org//DTD XML Bookmark Exchange Language 1.1//EN//XML \end{verbatim} Valid instances of this document type may use the following document type declaration: \begin{verbatim} \end{verbatim} \section{Requirements \label{requirements}} This section describes the functional capabilities which this document type supports. There are three categories of functionality supported: basic bookmark exchange between browsers, data storage for advanced Internet resource management tools, and simplicity in extending the DTD if needed for specific applications. \subsection{Relation to Browser Functionality \label{req-browser}} XBEL instances must be able to describe sufficient data to represent the bookmarks of all major Internet browsers. It must be possible to convert browser-specific bookmark data to XBEL in a lossless manner, though specific conversions may remove data for application-specific reasons. It is especially important to consider privacy issues when exchanging bookmark data. Conversion from XBEL to a browser-specific format may lose information when the data originates from a browser supporting bookmark features not available in all browsers. It is expected that software implementing the conversion be able to warn the user if conversion will cause the loss of information, as appropriate. \subsection{Advanced Application Support \label{req-applications}} XBEL must be able to support interchange requirements for applications not currently implemented as part of typical Internet browsers, including (but not limited to!) application-specific preference and history information which only pertains to specific bookmarks, metadata information, and alternate sources or formats for the documents. It must be possible for applications to operate on subsets of the information stored in an XBEL instance without affecting private information stored by other applications. Application-specific data stored in an XBEL instance may be simple text or may be heavily structured. \subsection{Extensibility \label{req-extensibility}} Some ability to extend the document type definition is required to encourage reuse of the existing design. Due to the use of XML, only a minimum of inherant flexibility is required, as new document types may be formed using namespaces or by allowing the use of well-formed but possibly invalid markup \cite{w3c-xml-names}. \section{XBEL Document Structure \label{document-structure}} This section describes the structure of XBEL documents. This includes information on each element and attribute defined in the DTD. Some descriptions include references to the parameter entities used to construct the DTD; these are described in Section \ref{parameter-entities}, ``Use of Parameter Entities.'' \subsection{Date/time Attribute Values \label{date-time}} Several attributes defined in this document type require date/time values stored as CDATA. For these attributes, the value must be formatted as an ISO 8601:1988 value containing a date \cite{iso8601,iso8601-houston,iso8601-kuhn}. A time value should be supplied whenever the information is available to the application which set the value. The format of the values is restricted to the forms specified in the profile defined in \emph{Date and Time Formats} \cite{w3c-datetime}. Attributes which require this form of value are described below as having a \dfn{date/time value} rather than a CDATA value. \subsection{Top-level Information \label{top-level}} This section describes the top-level element type of XBEL documents. \subsubsection{The \element{xbel} Element \label{element-xbel}} The \element{xbel} element defines the top-level data structure stored in an XBEL instance. It may contain optional \element{title}, \element{info}, and \element{desc} elements, followed by any number of elements from \paramentity{nodes.mix}. This is similar to the \element{folder} element, but it may not be nested and carries different attributes. \paragraph*{Attributes} The \element{xbel} element carries a \attribute{version} attribute which has a fixed value that specifies the version of the XBEL DTD. Other attributes indicate the similarity to the \element{folder} element. \begin{definitions} \term{\attribute{version}, \emph{fixed}} Fixed value which specifies the version of the DTD in use. \term{\attribute{id}} ID value to allow linking to this element; only the \element{alias} element's \attribute{ref} attribute supports a corresponding IDREF value. \term{\attribute{added}} Date/time value which can be used to record when the collection of bookmarks was created. \end{definitions} \paragraph*{Processing Expectations} The \element{xbel} element is in many ways similar to a \element{folder} element, but may not be ``folded.'' Auxillary information, such as an optional \element{title} element, may be shown in a substantially different way than for \element{folder} in a user interface. \subsection{Common Elements \label{common-elements}} Elements described in this section may occur in different contexts within an XBEL instance, but share fundamental semantic interpretation in each case. \subsubsection{The \element{title} Element \label{element-title}} The \element{title} element is used to mark the title associated with the immediately enclosing element. It is used for the \element{xbel}, \element{folder}, and \element{bookmark} elements. This element is always optional and may contain only character data. \paragraph*{Processing Expectations} Software which presents bookmark information to the user in any form should use the content of this element to identify the resource to the user. Additional information may be needed to make the identification unambiguous. Applications may use the text of the \element{title} during search operations. \paragraph*{Rationale} Many Internet resources are described by a short title, often displayed by the bookmarking facilities. Storing the title allows a significant improvement in user interface responsiveness when compared to retrieving the resource to reload the title. Title storage is the approach taken by all browsers known to the XBEL designers. \subsubsection{The \element{desc} Element \label{element-desc}} The \element{desc} element is used to store a human-readable description of the enclosing element. For a \element{folder} or the \element{xbel} element, this may be used to more thoroughly explain the subject of the bookmarks stored in the collection and why they may be interesting. For a \element{bookmark}, a summary of the resource pointed to by the bookmark may be more appropriate. This element is always optional and may contain only character data. \paragraph*{Processing Expectations} The content of this element may be displayed to a user requesting more information on the folder or bookmark containing the description. In the case of a \element{bookmark}, this can be used before actually making a request over the network to retrieve the resource. Applications may use the text of the \element{desc} during search operations. \paragraph*{Rationale} Many Internet browsers support simple annotation of bookmark data with human readable text. This element is required to support exchange of this data. \subsubsection{The \element{info} Element \label{element-info}} The \element{info} element is used to store metadata related to the immediately enclosing element. The intended use is for \element{info} to store a series of \element{metadata} elements, each of which ``belongs'' to some application. An ``application'' in this sense may be either a program, such as a specific Internet browser, or a more general metadata scheme, such as the Dublin Core \cite{dublin-core}. The \element{info} element is always optional. If present, it must contain one or more \element{metadata} elements. \paragraph*{Processing Expectations} Applications are expected to ignore \element{info} elements if they are not able to deal with the contents of constituent \element{metadata} elements. Whether or not \element{info} elements should be ``passed through'' transparently or removed depends on the purpose of the processing application, but an effort should be made to retain the information whenever the enclosing element is retained, even in a modified form. \paragraph*{Rationale} This element provides a clean way of isolating application-specific metadata from more generally supported constructs within the bookmark data. \subsubsection{The \element{metadata} Element \label{element-metadata}} The \element{metadata} element is used as a container for all auxillary information related to a node which belongs to a single metadata scheme. The specific contents of \element{metadata} is highly dependent on the metadata scheme which applies; XML namespaces should be used to identify explicit markup used within the element. The DTD for XBEL specifies the content model for \element{metadata} as \code{EMPTY}, but any content should be considered acceptable so long as the XBEL document is well-formed. The use of \code{EMPTY} avoids making the DTD too loose; applications which do not validate need not be concerned. Derivative DTDs can define the parameter entity \paramentity{metadata.mix} to be the appropriate content model for the application. \element{metadata} elements are always optional. Note that an \element{info} element which contains no \element{metadata} elements must be removed. \paragraph*{Attributes} \begin{definitions} \term{\attribute{owner}, \emph{required}} CDATA value specifies the application which ``owns'' the content of the element. The value of this attribute should be a URI which refers to a definition of the application and content structure in either human- or machine-processible form. It is not required that the URI be addressable through the network. \end{definitions} It is expected that namespace attributes will be added to the element to specify the markup defined for the content of the \element{metadata} element. \paragraph*{Processing Expectations} Within an \element{info} element, each \element{metadata} element is required to have a unique value for the \attribute{owner} attribute. Programs which modify the contents of \element{metadata} elements should ensure that only one \element{metadata} exists for any \attribute{owner} value normally modified by the application within affected \element{info} elements. \element{metadata} elements for other owners should remain unaffected. Specific interpretation of \element{metadata} content is highly dependent on both the \attribute{owner} and the application, and is not otherwise within the scope of this document. \paragraph*{Rationale} The \element{metadata} element is required to support owner identification. It is entirely reasonable for multiple owners of data to share a document type for their information, but otherwise require separate processing. The Resource Description Framework provides an example of an approach which would require multiple applications to share a namespace \cite{w3c-rdf-syntax,w3c-rdf-schema}. Some additional form of ownership identification is required to ensure processors can avoid destroying each other's data. \subsection{Data Organization \label{data-organization}} The elements described in this section are used to impose organization on a collection of \element{bookmark} nodes. \element{folder} is used to support hierarchical organization and \element{separator} is used to support non-hierarchical organization. \subsubsection{The \element{folder} Element \label{element-folder}} The \element{folder} element is the element used to support hierarchical data organization. It is the only element type which is allowed to nest within itself. This element may contain optional \element{title}, \element{info} and \element{desc} elements. After this, any number of elements from \paramentity{nodes.mix} are allowed. \paragraph*{Attributes} \begin{definitions} \term{\attribute{id}} ID value to allow linking to this element; only the \element{alias} element's \attribute{ref} attribute supports a corresponding IDREF value. \term{\attribute{added}} Date/time value which records when the folder was added to the bookmark collection represented by the instance. \term{\attribute{folded}} Token which records whether the contents of the folder should be displayed by default in a user interface. The value may be \nmtoken{yes} or \nmtoken{no}. \term{\attribute{icon}} The value of this attribute is a name which identifies an icon that the user agent can use to mark the folder for the user. The value must be mapped to an actual icon; is it not a URI which points to an image file, since the names should (in theory) be usable in multiple user agents which have differing capabilities for image display, and may require different format or sizes of icon. Mechanisms to do this are outside the scope of this specification. \term{\attribute{toolbar}} Token which records whether the contents of the folder should be used for the ``Personal Toolbar'' provided by some user agents. The value may be \nmtoken{yes} or \nmtoken{no}. \end{definitions} \paragraph*{Processing Expectations} User interfaces should display \element{folder} elements as collapsing lists, allowing the user to display or hide the contents of the element on demand. Appropriate behavior outside of user interfaces is expected to be application specific. \paragraph*{Rationale} The \element{folder} element may be used to represent hierarchical relationships within a collection of bookmarks, as deployed in current Internet browsers. The \attribute{toolbar} attribute is needed to support the ``Personal Toolbar'' information from Netscape Navigator. \subsubsection{The \element{separator} Element \label{element-separator}} The \element{separator} element can be used to separate bookmarks within a collection in a non-hierarchical fashion. It may be used within a \element{folder} or the \element{xbel} element. \paragraph*{Processing Expectations} The presence of this element may be represented by displaying a horizontal line or vertical whitespace in an interactive user interface or printed representation. \paragraph*{Rationale} A simple separator is required to support the bookmark structures of existing Internet browsers. \subsection{Bookmark Data \label{bookmark-data}} Only one element type is used to encapsulate information specific to an individual bookmark. No need for alternate elements has been demonstrated. \subsubsection{The \element{bookmark} Element \label{element-bookmark}} A \element{bookmark} element is used to store information about a specific resource. This element may contain the optional elements \element{title}, \element{info} and \element{desc}. \paragraph*{Attributes} The \element{bookmark} element carries more attributes than other elements defined in XBEL. These attributes are used to carry much of the common information maintained on bookmarks by the major browsers. \begin{definitions} \term{\attribute{href}, \emph{required}} URI which specifies the resource described by the \element{bookmark} element. \term{\attribute{id}} ID value to allow linking to this element; only the \element{alias} element's \attribute{ref} attribute supports a corresponding IDREF value. \term{\attribute{icon}} This is identical to the \attribute{icon} attribute of the \element{folder} element; refer to that description for information. \term{\attribute{added}} Date/time value which indicates when the \element{bookmark} element was added to the bookmark collection. \term{\attribute{modified}} Date/time value which records the time of the last known change to the resource identified by the \element{bookmark}. \term{\attribute{visited}} Date/time value which represents the time of the user's last ``visit'' to the resource. Note that the value for \attribute{modified} may be more recent than the value for \attribute{visited} if software is used that checks for resources which have changed since the user last visited the resource. This feature is increasingly common in browsers. \end{definitions} \paragraph*{Processing Expectations} In a user interface, \element{bookmark} should typically be represented by the contents of the \element{title} element, if present. The representation of the bookmark should be ``hot,'' allowing traversal to the referenced resource by the user. Additional information on the resource, such as the description given in a \element{desc} element, should be available to the user on demand. Outside a user interface, processing may be too application-specific to discuss here. \paragraph*{Rationale} The use of a single structured element type to represent external resources simplifies processing while allowing a rich set of information to be maintained on each resource. \subsection{Internal References \label{internal-references}} A single element is provided to support internal references to other elements within an XBEL instance. \subsubsection{The \element{alias} Element \label{element-alias}} \paragraph*{Attributes} Only one attribute is needed for \element{alias}, and is required to identify the link referent. \begin{definitions} \term{\attribute{ref}, \emph{required}} IDREF value which refers to a \element{bookmark} or \element{folder} element, or the document \element{xbel} element. \end{definitions} \paragraph*{Processing Expectations} Software which presents bookmarks in a user interface should distinguish aliases from other bookmarks visually, but otherwise allow examination of the referent transparently. Netscape Navigator does this by presenting the bookmark title in an italic font; the appropriate visual distrinction is likely to be dependent on other aspects of the user interface. Outside of user interface considerations, treatment of aliases is application-specific. However, some guidance may prove useful. When encountering an \element{alias}, an application should only need to traverse the \element{alias} and process the referent if that referent would not otherwise be processed, otherwise, the \element{alias} may usually be ignored. This should become an issue only when the application is processing a portion of the bookmark hierarchy rather than the complete tree. \paragraph*{Rationale} Netscape Navigator and Microsoft Internet Explorer bookmarks can include ``aliases'' to other nodes in the hierarchical structure. Navigator supports only aliases to bookmark nodes, while Internet Explorer also supports aliases to folders. Navigator's format simply adds the attribute \attribute{aliasid} to nodes which are referred to be aliases, and the attribute \attribute{aliasof} to the actual alias. All other information is duplicated for each alias of the primary bookmark entry. XBEL uses a distinct element and the ID/IDREF mechanism provided by XML to avoid redundency and support validation. \section{DTD Structure \label{dtd-structure}} This section discusses how the DTD itself is organized. This is mostly of interest to the maintainers of XBEL and any descendent document types that may be defined in the future. \subsection{Use of Parameter Entities \label{parameter-entities}} Limited use of parameter entities is made in the XBEL DTD. The suffix-notation is adopted from the ``XMLspec'' DTD report \cite{w3c-xmlspec}. Specifically, the \samp{.mix} suffix is used for entities which define repeatable-or groups of elements, and \samp{.att} is used for entities which define attributes. \subsubsection{The \paramentity{metadata.mix} Entity \label{entity-metadata.mix}} \subsubsection{The \paramentity{nodes.mix} Entity \label{entity-nodes.mix}} The \paramentity{nodes.mix} entity lists the element types which may be used to form the nodes of the hierarchical data structure described by an XBEL instance. This entity species a mixture of \element{bookmark}, \element{folder}, \element{separator} and \element{alias} elements. \subsubsection{The \paramentity{node.att} Entity \label{entity-node.att}} This entity is used to define attributes for element types which hold the real content of the bookmark data. It is used on the \element{bookmark} and \element{folder} elements. It defines the optional \attribute{added} and \attribute{id} attributes. \subsubsection{The \paramentity{url.att} Entity \label{entity-url.att}} This entity defines the attributes which are available on elements which refer to specific resources. In XBEL 1.0 and 1.1, this is only used on the \element{bookmark} element. It defines a required \attribute{href} attribute and the optional attributes \attribute{modified} and \attribute{visited}. \subsection{Extending the DTD \label{extending}} Extensibility of XBEL relies on three foundations: XML namespaces and the acceptability of well-formed instances, localized parameters entities, and the simplicity of the DTD itself. The primary expectation for DTD extensions is that new elements and attributes will be introduced and defined using XML namespaces. Though still in the stage of a working draft within the W3C, namespaces offer the most flexible extension mechanism available for XML-based markup languages used in wide-spread deployment. Until validation requirements in the context of namespaces are more clearly defined, XBEL instances using namespaces can apply well-formedness rules as a vehicle for partial validation. More traditional document type extension uses parameter entities reserved for localization. The XBEL public text provides three such entities as ``hooks'' to allow local customization. For each of the parameter entities described in Section \ref{parameter-entities}, ``Use of Parameter Entities,'' a \paramentity{local.\var{name}} variant is declared and used in the definition of each of the entities described above. This is less flexible than the namespace approach, but allows a new document type to be created which can be used for validation with current tools without having to create a new public text from scratch. The third foundation for extensibility, the simplicity of the DTD, can be effectively used only by taking a ``steal this code'' approach to reuse. XBEL is sufficiently simple that it can easily be understood in its entirety, and a variant document type created by crafting a new public text. \subsection{General Entities \label{general-entities}} The XBEL DTD defines no general entities. \paragraph*{Rationale} Since XBEL is intended as an interchange format for software and not as an authoring format, there is no need to support typical entities used to enter special characters. Entities which do not correspond to Unicode characters are too application-specific to predict meaningfully \cite{unicode20,unicode21}. \appendix \section{Public Text \label{public-text}} This section contains the entire public text of the XBEL DTD corresponding to the Formal Public Identifier presented in Section \ref{formal-ident}. No additional external entities are referenced. \begin{longexample} \verbatiminput{../xbel.dtd} \end{longexample} \nocite{*} \bibliographystyle{alpha} \bibliography{xbel} \end{document} PyXML-0.8.2/demo/xbel/README0100644000076400001440000000156007263756175014472 0ustar martinusersThis directory contains various scripts for processing XBEL, the XML Bookmark Exchange Language proposed by Mark Hammond on the XML-SIG. Scripts are provided to convert the bookmark files for various Web browsers to XBEL, and to render an XBEL document as HTML. xbel-1.1.dtd The Document Type Definition for XBEL 1.1. xbel-1.0.dtd The Document Type Definition for XBEL 1.0. bookmark.py Contains the Bookmarks and Bookmark classes, which represent a bookmark file, and can be output in any of the browser formats, or in XBEL. ns_parse.py A class that parses Netscape bookmark files. msie_parse.py A class that parses Internet Explorer bookmark files. adr_parse.py A class that parses Opera bookmark files. lynx_parse.py A class that parses Lynx bookmark files. xbel_parse.py A class that parses an XBEL input file and can output it in any of the other formats. PyXML-0.8.2/demo/xbel/adr_parse.py0100644000076400001440000000601607517567465016131 0ustar martinusers#!/usr/bin/env python """ Small utility to parse Opera bookmark files. Written by Lars Marius Garshol """ import string,bookmark,time # --- Constants short_months={"Jan":"01","Feb":"02","Mar":"03","Apr":"04","May":"05", "Jun":"06","Jul":"07","Aug":"08","Sep":"09","Oct":"10", "Nov":"11","Dec":"12"} # --- Parsing exception class OperaParseException(Exception): pass # --- Methods def readfield(infile, fieldname, required = 1): line = infile.readline() linelength = len(line) pos = string.find(line,fieldname+"=") if pos == -1 and required: raise OperaParseException("Field '%s' missing" % fieldname) if pos == -1 and required == 0: infile.seek(-linelength, 1) return string.rstrip(line[pos+len(fieldname)+1:]) def swallow_rest(infile): "Reads input until first blank line." while 1: line=infile.readline() if line=="" or line=="\n" or line=="\015\012": break def parse_date(date): # CREATED=904923783 (Fri Sep 04 17:43:03 1998) # VISITED=0 (?) if date=="": return None lp=string.find(date,"(") rp=string.find(date,")") if lp==-1 or rp==-1: if string.find(date," ")!=-1: raise OperaParseException("Can't handle this date: %s" % `date`) t=time.localtime(string.atoi(date)) return "%s%s%s" % (t[0],string.zfill(t[1],2),string.zfill(t[2],2)) if date[lp:rp+1]=="(?)": return None month=short_months[date[lp+5:lp+8]] day=date[lp+9:lp+11] year=date[rp-4:rp] return "%s%s%s" % (year,month,day) def parse_adr(filename): bms=bookmark.Bookmarks() infile=open(filename) version=infile.readline() while 1: line=infile.readline() if line=="": break line=string.rstrip(line) if line=="#FOLDER": name=readfield(infile,"NAME") created=parse_date(readfield(infile,"CREATED")) parse_date(readfield(infile, "VISITED", 0)) # just throw this away order = readfield(infile, "ORDER", 0) swallow_rest(infile) bms.add_folder(name,created) elif line=="#URL": name=readfield(infile,"NAME") url=readfield(infile,"URL") created=parse_date(readfield(infile,"CREATED")) visited=parse_date(readfield(infile, "VISITED", 0)) order = readfield(infile, "ORDER", 0) swallow_rest(infile) bms.add_bookmark(name,created,visited,None,url) elif line=="-": bms.leave_folder() return bms # --- Test-program if __name__ == '__main__': import sys if len(sys.argv)<2 or len(sys.argv)>3: print print "A simple utility to convert Opera bookmarks to XBEL." print print "Usage: " print " adr_parse.py []" sys.exit(1) bms=parse_adr(sys.argv[1]) if len(sys.argv)==3: out=open(sys.argv[2],"w") bms.dump_xbel(out) out.close() else: bms.dump_xbel() # Done PyXML-0.8.2/demo/xbel/bookmark.py0100644000076400001440000002630607613237634015767 0ustar martinusers""" Classes to store bookmarks and dump them to XBEL. """ import sys,string,types from xml.sax.saxutils import escape # --- Class for bookmark container class Bookmarks: def __init__(self, info=None, id=None, title=None): self.folders=[] self.folder_stack=[] self.desc = "No description" self.info = info self.id = id self.title = title def add_folder(self, name, added=None): nf=Folder(name, added) if self.folder_stack==[]: self.folders.append(nf) else: self.folder_stack[-1].add_child(nf) self.folder_stack.append(nf) return nf def add_bookmark(self,name=None, added=None, visited=None, modified=None, href=None, desc = None): nb=Bookmark(name,added,visited,modified,href, desc = desc) if self.folder_stack!=[]: self.folder_stack[-1].add_child(nb) else: self.folders.append(nb) return nb def add_separator(self): s = Separator() if self.folder_stack!=[]: self.folder_stack[-1].add_child(s) else: self.folders.append(s) return s def leave_folder(self): if self.folder_stack!=[]: del self.folder_stack[-1] def update_ids(self): ids = {} aliases = [] for folder in self.folders: folder.update_ids(ids, aliases) for alias in aliases: alias.update_link(ids) def dump_xbel(self,out=sys.stdout): if self.id: ID = ' id="%s"' % self.id else: ID = "" out.write('\n' '\n' '\n' % ID ) if self.title: out.write(" %s\n" % encode(self.title)) if self.info: out.write(" %s\n" % encode(self.info)) out.write(" %s\n" % (esc_enc(self.desc),) ) for folder in self.folders: folder.dump_xbel(out) out.write("\n") def dump_adr(self,out=sys.stdout): out.write("Opera Hotlist version 2.0\n\n") for folder in self.folders: folder.dump_adr(out) def dump_netscape(self,out=sys.stdout): out.write("\n") out.write("\n") # Mozilla recognizes the content-type declaration; let's hope # Netscape 4 is not bothered by it out.write('\n') if self.title: out.write("" + encode(self.title) + "\n") else: out.write("Bookmarks\n") out.write("

" + encode(self.desc) + "

\n\n") out.write("

\n") for folder in self.folders: folder.dump_netscape(out) out.write("

\n") # Lynx uses multiple bookmark files; each folder will be written to a # different file. def dump_lynx(self, path): import os for folder in self.folders: # First, figure out a reasonable filename for this folder filename = string.replace(folder.title, ' ', '_') + '.html' # Open a file for the top-level folders output = open( os.path.join(path, filename), 'w') print 'folder title:', folder.title, filename output.write('\n%s\n\n' % (folder.title,) ) output.write('

\n

    \n') folder.dump_lynx(output) output.close() # --- Superclass for folder and bookmarks class Node: def __init__(self, name, added=None, visited=None, modified=None, id=None, desc=None): self.title = name self.added = added self.visited = visited self.modified = modified self.id = id self.desc = desc def update_ids(self, ids, aliases): if self.id: while ids.has_key(self.id): # Duplicate ID self.id = self.id + '0' ids[self.id] = self def gen_id(self, ids): self.id = 'X'+str(id(self)) self.update_ids(ids, []) # --- Class for folders class Folder(Node): def __init__(self, name, added = None, info = None, id=None, folded = 'yes', icon = None, toolbar = 'no', desc=None): Node.__init__(self, name, added=added, id=None,desc=desc) self.children=[] self.info = None self.folded = None self.icon = None self.toolbar = None def add_child(self,child): self.children.append(child) def update_ids(self, ids, aliases): Node.update_ids(self, ids, aliases) for node in self.children: node.update_ids(ids, aliases) def is_folded(self): # folded defaults to yes return self.folded is None or self.folded == 'yes' def dump_xbel(self,out): if self.id: ID = ' id="%s"' % self.id else: ID = "" if self.added: added = ' added="%s"' % self.added else: added = "" if self.folded is not None: folded = ' folded="%s"' % self.folded else: folded = "" if self.icon is not None: icon = ' icon="%s"' % self.icon else: icon = "" if self.toolbar is not None: toolbar = ' toolbar="%s"' % self.toolbar else: toolbar = "" out.write(" \n" % (ID, added, folded, icon, toolbar)) out.write(" %s\n" % esc_enc(self.title) ) if self.info: out.write(" %s\n" % encode(self.info)) if self.desc: out.write(" %s\n" % encode(self.desc)) for child in self.children: child.dump_xbel(out) out.write(" \n") def dump_adr(self,out): out.write("#FOLDER\n") out.write("\tNAME=%s\n" % self.title) out.write("\tADDED=%s\n" % "0 (?)") out.write("\tVISITED=%s\n" % "0 (?)") out.write("\tORDER=-1\n") out.write("\n") for child in self.children: child.dump_adr(out) out.write("\n") out.write("-\n") def dump_netscape(self,out): if self.id: ID = ' ID="%s"' % self.id else: ID = "" if self.is_folded(): folded = " FOLDED" else: folded = "" if self.added: added = ' ADD_DATE="%s"' % self.added else: added = "" out.write("
    %s\n" % (folded,added,ID,encode(self.title))) if self.desc: out.write("
    %s\n" % (encode(self.desc))) out.write("

    \n") for child in self.children: child.dump_netscape(out) out.write("

    \n") def dump_lynx(self, out): out.write("

    %s

    \n" % self.title) out.write("
      \n") for child in self.children: child.dump_lynx(out) # Mustn't write the closing
    , because Lynx will add it # when it reads the bookmark file. ##out.write("
\n") # --- Class for bookmarks class Bookmark(Node): def __init__(self, name, added=None, visited=None, modified=None, href=None, info=None, id = None, desc = None): Node.__init__(self,name,added,visited,modified, id=id, desc=desc) self.href = href self.info = info def dump_xbel(self,out): if self.id: ID = ' id="%s"' % self.id else: ID = "" if self.visited!=None: visited = ' visited="%s"' % escape(self.visited) else: visited = "" if self.added!=None: added = ' added="%s"' % escape(self.added) else: added = "" if self.modified!=None: modified = ' modified="%s"' % escape(self.modified) else: modified = "" out.write(' \n' % ( esc_enc(self.href), ID, added, visited, modified) ) out.write(" %s\n" % esc_enc(self.title) ) if self.info: out.write(" %s\n" % encode(self.info)) if self.desc: out.write(" %s\n" % encode(self.desc)) out.write(" \n") def dump_adr(self,out): out.write("#URL\n") out.write("\tNAME=%s\n" % self.title) out.write("\tURL=%s\n" % self.href) out.write("\tCREATED=%s\n" % "0 (?)") out.write("\tVISITED=%s\n" % "0 (?)") out.write("\tORDER=-1\n") out.write("\n") def dump_netscape(self,out): added = visited = modified = "" if self.added: added = ' ADD_DATE="%s"' % encode(self.added) if self.visited: visited = ' LAST_VISIT="%s"' % encode(self.visited) if self.modified: modified = ' LAST_MODIFIED="%s"' % encode(self.modified) out.write("
%s\n" % (encode(self.href),added,visited,modified, esc_enc(self.title))) if self.desc: out.write("
%s\n" %(encode(self.desc))) def dump_lynx(self, out): out.write("
  • %s\n" % (self.href, self.title) ) # --- Class for separators class Separator(Node): def __init__(self): Node.__init__(self, None) def dump_xbel(self, out): out.write(' \n') def dump_netscape(self, out): out.write("
    \n") # --- Class for separators class InvalidReference(Exception): pass class Alias(Node): def __init__(self, aliased_to): Node.__init__(self, None) if isinstance(aliased_to, Node): self.aliased_to = aliased_to self.ref = None else: self.aliased_to = None self.ref = aliased_to def update_ids(self, ids, aliases): aliases.append(self) def update_link(self, ids): if self.aliased_to: if self.aliased_to.id is None: self.aliased_to.gen_id(ids) self.ref = self.aliased_to.id else: try: self.aliased_to = ids[self.ref] except KeyError: raise InvalidReference, self.ref def dump_xbel(self, out): out.write(' \n' % self.ref) # --- helper functions try: types.UnicodeType except AttributeError: def encode(str, encoding = "utf-8"): # Can't do proper recoding in Python 1.5 return str else: def encode(str, encoding = "utf-8"): if type(str) == types.UnicodeType: return str.encode(encoding) return str def esc_enc(str): return encode(escape(str)) PyXML-0.8.2/demo/xbel/lynx_parse.py0100644000076400001440000000361107413602741016331 0ustar martinusers#!/usr/bin/env python # # lynx_parse.py : # Read a list of Lynx bookmark files, specified on the command line, # and outputs the corresponding XBEL document. # # Sample usage: ./lynx_parse.py ~/bookmarks/ # (The script requires the path to the directory where your bookmark files # are stored.) # import bookmark import re def parse_lynx_file(bms, input): """Convert a Lynx 2.8 bookmark file to XBEL, reading from the input file object, and write to the output file object.""" # Read the whole file into memory data = input.read() # Get the title m = re.search("(.*?)", data, re.IGNORECASE) if m is None: title = "Untitled" else: title = m.group(1) bms.add_folder( title ) hrefpat = re.compile( r"""^ \s*
  • \s* [^"]* )" \s*> (?P .*? ) """, re.IGNORECASE| re.DOTALL | re.VERBOSE | re.MULTILINE) pos = 0 while 1: m = hrefpat.search(data, pos) if m is None: break pos = m.end() url, name = m.group(1,2) bms.add_bookmark( name, href = url) bms.leave_folder() if __name__ == '__main__': import sys, glob if len(sys.argv)<2 or len(sys.argv)>3: print print "A simple utility to convert Lynx bookmarks to XBEL." print print "Usage: " print " lynx_parse.py []" sys.exit(1) bms = bookmark.Bookmarks() # Determine the owner on Unix platforms import os, pwd uid = os.getuid() t = pwd.getpwuid( uid ) bms.owner = t[4] glob_pattern = os.path.join(sys.argv[1], '*.html') file_list = glob.glob( glob_pattern ) for file in file_list: input = open(file) parse_lynx_file(bms, input) if len(sys.argv)==3: out=open(sys.argv[2],"w") bms.dump_xbel(out) out.close() else: bms.dump_xbel() # Done PyXML-0.8.2/demo/xbel/msie_parse.py0100644000076400001440000000570507534565152016312 0ustar martinusers#!/usr/bin/env python """ Small utility to convert MSIE favourites to an object structure. Originally written by Fredrik Lundh. Modified by Lars Marius Garshol 2-17-2002 tbp Now closes folder when its traverse is done. Also works with current IE shortcut format, which can differ from the format that was assumed here. """ import bookmark,os,string DIR = "Favoritter" # Norwegian version #USRDIR = os.environ["USERPROFILE"] # NT version USRDIR = r"c:\windows" # 95 version class MSIE: # internet explorer def __init__(self,bookmarks, path): self.bms=bookmarks self.root = None self.path = path self.__walk() def __walk(self, subpath=[]): # traverse favourites folder path = os.path.join(self.path, string.join(subpath, os.sep)) for file in os.listdir(path): fullname = os.path.join(path, file) if os.path.isdir(fullname): self.bms.add_folder(file,None) self.__walk(subpath + [file]) self.bms.leave_folder() else: url = self.__geturl(fullname) if url: self.bms.add_bookmark(os.path.splitext(file)[0],None, None,None,url) def __geturl(self, file): try: fp = open(file) #if fp.readline() != "[InternetShortcut]\n": # return None while 1: line=fp.readline() if not line: return None if line=="[InternetShortcut]\n": s = fp.readline() if not s: break if s[:4] == "URL=": fp.close() return s[4:-1] elif line=="[DEFAULT]\n": s = fp.readline() if not s: break if s[:8] == "BASEURL=": fp.close() return s[8:-1] except IOError: return '' fp.close() return '' # --- Testprogram if __name__ == '__main__': import sys if len(sys.argv)>1: path = sys.argv[1] else: try: import win32api, win32con except ImportError: print "The win32api module is not available on this system" print "so we can't automatically find your favorites folder." print "Please re-run this program specifiying the location of your" print "favorites folder on the command line." sys.exit(1) keyname = r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" hkey = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, keyname) path, pathtype = win32api.RegQueryValueEx(hkey, "Favorites") assert pathtype == win32con.REG_SZ msie=MSIE(bookmark.Bookmarks(), path) msie.bms.dump_xbel() PyXML-0.8.2/demo/xbel/ns_parse.py0100644000076400001440000001163307517567465016004 0ustar martinusers#!/usr/bin/env python """ Small utility that parses Netscape bookmarks. """ # TODO: # LAST_CHARSET: put in ... # H3:LAST_MODIFIED: Put in XBEL 1.2? # Cross references? # Descriptions from xml.sax import sax2exts,handler import bookmark import string, htmlentitydefs # --- SAX handler for Netscape bookmarks class NetscapeHandler(handler.ContentHandler): def __init__(self): self.bms=bookmark.Bookmarks() self.cur_elem = None self.added = None self.href = None self.visited = None self.modified = None self.latest = None self.desc = "" def startElement(self,name,attrs): name = string.lower( name ) d = {} for key, value in attrs.items(): d[ string.lower(key) ] = value ## print 'start', name, d if name=="h3": self.cur_elem="h3" if d.has_key("folded"): self.folded = "yes" else: self.folded = "no" self.id = d.get('id') self.added= d.get('add_date',"") self.modified = d.get('last_modified', "") folder = self.bms.add_folder('', None) folder.id = self.id folder.folded = self.folded folder.added = self.added self.latest = folder elif name=="a": self.cur_elem="a" self.bookmark = "" if d.has_key('add_date'): self.added=d["add_date"] else: self.added = None if d.has_key('last_visit'): self.visited=d["last_visit"] else: self.visited = None if d.has_key('last_modified'): self.modified=d["last_modified"] else: self.modified = None self.url=d["href"] elif name=='title': self.cur_elem = 'title' self.bms.title = "" elif name=='h1': self.cur_elem = 'h1' self.bms.desc = "" elif name=='hr': self.bms.add_separator() elif name=='meta': if d.has_key('http-equiv') and \ string.lower(d['http-equiv'])=='content-type': value = string.split(d['content'], "charset=") if len(value) == 2: the_parser.setProperty(handler.property_encoding, value[1]) elif name in ('dt','dl'): if self.desc and not self.latest.desc: self.latest.desc = self.desc self.desc = "" self.curr_elem = '' elif name=='dd': self.cur_elem = 'dd' self.desc = "" def characters(self,data): ## print 'char', self.cur_elem, data if self.cur_elem=="h3": self.latest.title+=data elif self.cur_elem=="a": self.bookmark = self.bookmark+data elif self.cur_elem=="title": self.bms.title = self.bms.title + data elif self.cur_elem=="h1": self.bms.desc = self.bms.desc + data elif self.cur_elem=="dd": self.desc = self.desc + data def skippedEntity(self, name): self.characters(htmlentitydefs.entitydefs[name]) def endElement(self,name): name = string.lower( name ) ## print 'end', name if name=="a": self.latest = self.bms.add_bookmark(self.bookmark, added = self.added, visited = self.visited, modified = self.modified, href = self.url) elif name=="h3": self.cur_elem=None elif name=="dl": self.bms.leave_folder() elif name == self.cur_elem: self.cur_elem=None def endDocument(self): if self.desc and not self.latest.desc: self.latest.desc = self.desc # --- Test-program if __name__ == '__main__': import sys if len(sys.argv)<2 or len(sys.argv)>3: print print "A simple utility to convert Netscape bookmarks to XBEL." print print "Usage: " print " ns_parse.py []" sys.exit(1) ns_handler=NetscapeHandler() the_parser = sax2exts.SGMLParserFactory.make_parser() the_parser.setContentHandler(ns_handler) # For Netscape 4, default to Latin-1 the_parser.setProperty(handler.property_encoding, "iso-8859-1") file = open(sys.argv[1], 'r') the_parser.parse(file) bms = ns_handler.bms if len(sys.argv)==3: out=open(sys.argv[2],"w") bms.dump_xbel(out) out.close() else: bms.dump_xbel() # Done ## ns_handler=NetscapeHandler() ## p=saxexts.SGMLParserFactory.make_parser() ## p.setDocumentHandler(ns_handler) ## p.parseFile(open(r"/home/amk/.netscape/bookmarks.html")) ## ns_handler.bms.dump_xbel() PyXML-0.8.2/demo/xbel/xbel-1.0.dtd0100644000076400001440000000525207547107337015532 0ustar martinusers PyXML-0.8.2/demo/xbel/xbel-1.1.dtd0100644000076400001440000000633007547107337015531 0ustar martinusers PyXML-0.8.2/demo/xbel/xbel2html.py0100644000076400001440000000465107517567465016075 0ustar martinusers#! /usr/bin/env python """ A simple XBEL to HTML converter written with SAX. """ # Limitations: will screw up if a folder lacks a 'title' element. # no checking of the command-line args import sys from xml.sax import make_parser,saxlib,saxutils # --- HTML templates top=\ """ %s

    %s

    """ bottom=\ """
    Converted from XBEL by xbel2html.
    """ # --- DocumentHandler class XBELHandler(saxlib.ContentHandler): def __init__(self,writer=sys.stdout,encoding='utf-8'): self.stack=[] self.writer=writer self.last_url=None self.inside_ul=0 self.level=0 self.encoding=encoding def startElement(self,name,attrs): self.stack.append(name) self.data = '' if name=="bookmark": self.last_url=attrs["href"].encode(self.encoding) def characters(self,data): self.data += data.encode(self.encoding) def endElement(self,name): data = self.data if self.stack[-1]=="title" and self.stack[-2]=="xbel": self.writer.write(top % (data,self.encoding,data)) self.state=None if self.stack[-1]=="desc" and self.stack[-2]=="xbel": self.writer.write("

    %s

    \n" % data) if self.stack[-1]=="title" and self.stack[-2]=="bookmark": if not self.inside_ul: self.inside_ul=1 self.writer.write("
      \n") self.writer.write('
    • %s. \n' % (self.last_url,data)) if self.stack[-1]=="desc" and self.stack[-2]=="bookmark": self.writer.write(data+"\n\n") if self.stack[-1]=="title" and self.stack[-2]=="folder": self.writer.write("
    • %s\n" % data) self.writer.write("
        \n") self.inside_ul=1 del self.stack[-1] if name=="folder": self.writer.write("
      \n") def endDocument(self): self.writer.write("
    \n") self.writer.write(bottom) # --- Main program if __name__ == '__main__': p=make_parser() p.setContentHandler(XBELHandler()) p.setErrorHandler(saxutils.ErrorPrinter()) p.parse(sys.argv[1]) PyXML-0.8.2/demo/xbel/xbel_parse.py0100644000076400001440000000750107517567465016315 0ustar martinusers#!/usr/bin/env python """ A class to parse an XBEL file and produce a Bookmarks instance. If executed as a script, this module will read an XBEL file from standard input, produce the corresponding Bookmarks instance, and dump it to standard output in a selected format. """ import bookmark import string from xml.sax import saxlib,make_parser class XBELHandler(saxlib.ContentHandler): def __init__(self): self.bms = bookmark.Bookmarks() self.entered_folder = self.entered_bookmark = 0 def startElement(self, name, attrs): self.cur_elem = name # print name, attrs if name == 'folder': self.entered_folder = 1 self.id = attrs.get('id') self.added = attrs.get('added') self.folded = attrs.get('folded') self.icon = attrs.get('icon') self.toolbar = attrs.get('toolbar') elif name == 'title': self.title = "" elif name == 'desc': self.desc = "" elif name == 'bookmark': self.entered_bookmark = 1 self.title = self.href = "" self.added = self.visited = self.modified = "" if attrs.has_key('href'): self.href = attrs['href'] if attrs.has_key('added'): self.added = attrs['added'] if attrs.has_key('visited'): self.visited = attrs['visited'] if attrs.has_key('modified'): self.modified = attrs['modified'] def characters(self, data): if self.cur_elem in ['title', 'desc']: attr = string.lower(self.cur_elem) value = getattr(self, attr) setattr(self, attr, value + data) def endElement(self, name): self.cur_elem = None if name == 'folder': self.bms.leave_folder() self.entered_folder = 0 elif name == 'desc': self.bms.desc = self.desc elif name == 'title': if self.entered_folder: folder = self.bms.add_folder(self.title) folder.id = self.id folder.added = self.added folder.folded = self.folded folder.icon = self.icon folder.toolbar = self.toolbar self.entered_folder = 0 elif not self.entered_bookmark: self.bms.title = self.title elif name == 'bookmark': self.entered_folder = 0 self.entered_bookmark = 0 if self.added == "": self.added = None if self.visited == "": self.visited = None if self.modified == "": self.modified = None self.bms.add_bookmark(self.title, self.added, self.visited, self.modified, self.href) elif name == 'separator': self.bms.add_separator() if __name__ == '__main__': import sys, getopt opts, args = getopt.getopt(sys.argv[1:], '', ['opera', 'netscape', 'lynx=', 'msie', 'xbel'] ) if len(args): print 'xbel_parse only reads from standard input' sys.exit(1) if len(opts)>1 or len(opts)==0: print 'You must specify a single output format when running xbel_parse' print 'Available formats: --opera, --netscape, --msie, --lynx, --xbel' print ' --lynx : For Lynx, a path to the directory where' print ' the output bookmark files should be written' sys.exit(1) xbel_handler = XBELHandler() p=make_parser() p.setContentHandler( xbel_handler ) p.parse( sys.stdin ) bms = xbel_handler.bms mode, arg = opts[0] if mode == '--opera': bms.dump_adr() elif mode == '--lynx': bms.dump_lynx(arg) elif mode == '--netscape': bms.dump_netscape() elif mode == '--msie': bms.dump_msie() elif mode == '--xbel': bms.dump_xbel() PyXML-0.8.2/demo/xmlproc/0040755000076400001440000000000007614726123014333 5ustar martinusersPyXML-0.8.2/demo/xmlproc/dtds/0040755000076400001440000000000007614726123015271 5ustar martinusersPyXML-0.8.2/demo/xmlproc/dtds/xbel-1.0.dtd0100644000076400001440000000524706660162333017216 0ustar martinusers PyXML-0.8.2/demo/xmlproc/dtds/xsa.dtd0100644000076400001440000000116306660162333016554 0ustar martinusers PyXML-0.8.2/demo/xmlproc/catalog.soc0100644000076400001440000000105606660162324016447 0ustar martinusers -- DEMO CATALOG for xmlproc This is just a demonstration catalog file that resolves the public identifiers of the DTDs that come with the parser -- PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML" "dtds/xsa.dtd" PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML" "dtds/xbel-1.0.dtd" -- If we can't find a system identifier for the public identifier here, then go to James Tauber's public catalog -- DELEGATE "" "http://www.schema.net/public-text/catalog.soc"PyXML-0.8.2/demo/xmlproc/doctree.py0100644000076400001440000000362307413602741016327 0ustar martinusers""" A very simple tree model for XML documents. Elements are represented as triples (name, attribute dictionary, content list), and the entire document is represented by the document element. """ import types from xml.parsers.xmlproc import xmlproc # --- Tree-building functions def build_tree(sysid): "Builds a doctree and returns it." class BuilderApp(xmlproc.Application): "The actual tree builder." def __init__(self): self.root=None self.current_stack=[] def handle_start_tag(self,name,attrs): if self.root==None: self.current_stack.append([]) self.root=(name,attrs,self.current_stack[-1]) else: list=[] self.current_stack[-1].append(name,attrs,list) self.current_stack.append(list) def handle_data(self,data,start,end): if self.root!=None: self.current_stack[-1].append(data[start:end]) def handle_end_tag(self,name): del self.current_stack[-1] builder=BuilderApp() parser=xmlproc.XMLProcessor() parser.set_application(builder) parser.parse_resource(sysid) return builder.root # --- Utility functions def get_element(parent,child_type_name): "Locates the first child element with the given name inside an element." for child in parent[2]: if type(child)==types.TupleType and child[0]==child_type_name: return child def get_elements(parent,child_type_name): "Locates the child elements with the given name inside an element." list=[] for child in parent[2]: if type(child)==types.TupleType and child[0]==child_type_name: list.append(child) return list def get_pcdata(parent): """Picks out the PCDATA contents of the element, under the assumption that all the contents are PCDATA.""" return parent[2][0] PyXML-0.8.2/demo/xmlproc/dtd2schema.py0100644000076400001440000002236607534565152016735 0ustar martinusers#!/usr/bin/python """ This script converts DTDs to XML Schemas, according to the 20000407 WD. It can do simple reverse-engineering of attribute groups. """ # Todo # - make better names for attrgroups? # - make a SchemaWriter class (to hold common references) # - start doing reverse engineering to create modelGroups? from xml.parsers.xmlproc import xmldtd import sys, types, os.path, string usage = \ """ Usage: python dtd2schema.py [] Input file names can be URLs. If the output file name is omitted, it will be inferred from the input file name. Note that this inference does not work for URLs. """ version = "0.2" # ===== UTILITY FUNCTIONS class CountingDict: def __init__(self): self._items = {} def count(self, item): try: self._items[item] = self._items[item] + 1 except KeyError: self._items[item] = 1 def clear(self): self._items = {} def keys(self): return self._items.keys() def __getitem__(self, item): return self._items[item] def __delitem__(self, item): del self._items[item] class AttributeInfo: """This class holds information about reverse-engineered attribute groupings.""" def __init__(self): self._shared_attrs = {} self._shared_attrs_on_elem = {} self._count = CountingDict() self._groupnames = {} def count(self, attrname): self._count.count(attrname) def new_attr(self, elemname, attr): attrname = attr.get_name() self._count.count(attrname) if self._shared_attrs.has_key(attrname): shared = self._shared_attrs[attrname] if shared != None and not compare_attrs(shared, attr): self._shared_attrs[attrname] = None else: self._shared_attrs[attrname] = attr def remove_single_attributes(self): "Removes attributes that only occurred once." for attrname in self._shared_attrs.keys(): if self._shared_attrs.get(attrname) != None: if self._count[attrname] < 2: self._shared_attrs[attrname] = None self._count.clear() def find_groups(self, elem): shared = tuple(filter(self._shared_attrs.get, elem.get_attr_list())) self._shared_attrs_on_elem[elem.get_name()] = shared if shared: self._count.count(shared) def remove_single_groups(self): "Removes groups that only occurred once." for group in self._count.keys(): if self._count[group] < 2: del self._count[group] def get_groups(self): return self._count.keys() def get_attribute(self, name): return self._shared_attrs[name] def get_shared_attrs_on_elem(self, elemname): return self._shared_attrs_on_elem[elemname] def make_name(self, group): name = "group" + str(len(self._groupnames) + 1) self._groupnames[group] = name return name def get_group_name(self, group): return self._groupnames[group] def escape_attr_value(value): value = string.replace(value, '&', '&') value = string.replace(value, '"', '"') return string.replace(value, '<', '<') # ===== REVERSE ENGINEERING def compare_attrs(attr1, attr2): return attr1.get_name() == attr2.get_name() and \ attr1.get_type() == attr2.get_type() and \ attr1.get_decl() == attr2.get_decl() and \ attr1.get_default() == attr2.get_default() def find_attr_groups(dtd): # first pass: find attributes that occur more than once attrinfo = AttributeInfo() for elemname in dtd.get_elements(): elem = dtd.get_elem(elemname) for attrname in elem.get_attr_list(): attrinfo.new_attr(elemname, elem.get_attr(attrname)) attrinfo.remove_single_attributes() # second pass: group the recurring attributes for elemname in dtd.get_elements(): elem = dtd.get_elem(elemname) attrinfo.find_groups(elem) attrinfo.remove_single_groups() return attrinfo # ===== COMPONENT FUNCTIONS def write_attribute_group(out, group, attrinfo): groupname = attrinfo.make_name(group) out.write(' \n' % groupname) for attrname in group: write_attr(out, attrinfo.get_attribute(attrname)) out.write(' \n') declmap = {"#REQUIRED" : "required", "#IMPLIED" : "optional", "#DEFAULT" : "default", "#FIXED" : "fixed" } def write_attr(out, attr): value = attr.get_default() if value == None: value = '' else: value = ' value="%s"' % escape_attr_value(value) attrtype = attr.get_type() if type(attrtype) == types.ListType: out.write(' \n' % (attr.get_name(), declmap[attr.get_decl()], value)) out.write(' \n') for token in attrtype: out.write(' \n' % token) out.write(' \n') out.write(' \n') else: out.write(' \n' % (attr.get_name(), attrtype, declmap[attr.get_decl()], value)) def write_attributes(out, elem, attrinfo): attrnames = elem.get_attr_list() shared = attrinfo.get_shared_attrs_on_elem(elem.get_name()) or [] for attrname in attrnames: if not attrname in shared: write_attr(out, elem.get_attr(attrname)) if shared: out.write(' \n' % attrinfo.get_group_name(group)) def write_element_type(out, elem, attrinfo): cm = elem.get_content_model() if cm == ('', [('#PCDATA', '')], ''): if elem.get_attr_list() == []: out.write(' \n') else: out.write(' \n') write_attributes(out, elem, attrinfo) out.write(' \n') return content = '' if cm == ("", [], ""): content = ' content="empty"' elif cm != None and cm[1][0][0] == "#PCDATA": content = ' content="mixed"' out.write(' \n' % content) if cm == None: out.write(' \n') elif cm != ("", [], ""): write_cm(out, cm) write_attributes(out, elem, attrinfo) out.write(' \n') def write_cm(out, cm): (sep, cps, mod) = cm out.write(' \n') if sep == '' or sep == ',': wrapper = 'sequence' elif sep == '|': wrapper = 'choice' out.write(' <%s>\n' % wrapper) for cp in cps: if len(cp) == 2: (name, mod) = cp if name == "#PCDATA": continue if mod == '?': occurs = ' minOccurs="0" maxOccurs="1"' elif mod == '*': occurs = ' minOccurs="0" maxOccurs="*"' elif mod == '+': occurs = ' minOccurs="1" maxOccurs="*"' else: occurs = '' out.write(' \n' % (name, occurs)) elif len(cp) == 3: write_cm(out, cp) else: out.write(' \n' % (cp,)) out.write(' \n' % wrapper) out.write(' \n') # ===== MAIN PROGRAM # --- Interpreting command-line if len(sys.argv) < 2 or len(sys.argv) > 3: print usage sys.exit(1) infile = sys.argv[1] if len(sys.argv) == 3: outfile = sys.argv[2] else: ext = os.path.splitext(infile)[1] outfile = os.path.split(infile)[1] outfile = outfile[ : -len(ext)] + ".xsd" # --- Doing the job print "\ndtd2schema.py\n" # Load DTD print "Loading DTD..." dtd = xmldtd.load_dtd(infile) # Find attribute groups print "Doing reverse-engineering..." attrinfo = find_attr_groups(dtd) # Write out schema print "Writing out schema" out = open(outfile, "w") out.write('\n') out.write('\n\n') out.write('\n\n') if attrinfo: out.write('\n\n') for group in attrinfo.get_groups(): write_attribute_group(out, group, attrinfo) out.write("\n") out.write('\n\n') for elemname in dtd.get_elements(): elem = dtd.get_elem(elemname) out.write(' \n' % elemname) write_element_type(out, elem, attrinfo) out.write(' \n\n') notations = dtd.get_notations() if notations != []: out.write('\n\n\n\n') for notname in notations: (pubid, sysid) = dtd.get_notation(notname) if sysid == None: sysid = '' else: sysid = ' system="%s"' out.write(' \n' % (notname, pubid, sysid)) out.write('\n') out.close() PyXML-0.8.2/demo/xmlproc/dtdcheck.py0100644000076400001440000000304207413602741016446 0ustar martinusersfrom xml.parsers.xmlproc import xmlproc import sys class DTDReporter(xmlproc.DTDConsumer): "A simple class that just prints out the events it receives." def __init__(self,parser,out=sys.stdout): xmlproc.DTDConsumer.__init__(self,parser) self.out=out def new_general_entity(self,name,val): self.out.write("ENTITY: %s [%s]\n" % (name,val)) def new_external_entity(self,ent_name,pub_id,sys_id,ndata): self.out.write("EXTERNAL ENTITY: %s P: [%s] S: [%s] N: %s\n" %\ (ent_name,pub_id,sys_id,ndata)) def new_parameter_entity(self,name,val): self.out.write("PE: %s [%s]\n" % (name,val)) def new_external_pe(self,name,pubid,sysid): self.out.write("EXTERNAL PE: %s P: [%s] S: [%s]\n" % (name,pubid,sysid)) def new_notation(self,name,pubid,sysid): self.out.write("NOTATION: %s P: [%s] S: [%s]\n" % (name,pubid,sysid)) def new_attribute(self,elem,attr,a_type,a_decl,a_def): self.out.write("ATTLIST: %s %s %s %s [%s]\n" % (elem,attr,a_type,a_decl,a_def)) def new_element_type(self,elem_name,elem_cont): self.out.write("ELEMENT: %s %s\n" % (elem_name,`elem_cont`)) # --- Client methods def close(self): self.out.close() # --- Main program if __name__ == '__main__': t=xmlproc.DTDParser() t.set_dtd_consumer(DTDReporter(t)) t.parse_resource(sys.argv[1]) #t.parse_resource("c:\\minedo~1\\data\\sgml\\xml\\xbel-1.0.dtd") #t.parse_resource("c:\\minedo~1\\programmering\\python\\xml\\stddirs\\petest.dtd") PyXML-0.8.2/demo/xmlproc/dtdcmd.py0100644000076400001440000000331407413602741016136 0ustar martinusers#!/usr/bin/python """ A simple command-line interface to the DTD parser. Intended for those rare cases when one wants to just parse a DTD and nothing more. """ import sys, getopt from xml.parsers.xmlproc import xmlproc,dtdparser,utils,xmldtd # --- Doco usage=\ """ Usage: python dtdcmd.py [--list] + ---Options: --list: List all declarations after parsing. """ # --- Utilities def paired_list_to_hash(list): hash = {} for (name, value) in list: hash[name] = value return hash # --- Functionality def listdecls(dtd): print print "=== DECLARATIONS" print print "---Elements" elems = dtd.get_elements() elems.sort() for elem in elems: print elem print print "---Entities" ents = dtd.get_general_entities() ents.sort() for ent in ents: print ent print print "---Notations" nots = dtd.get_notations() if nots == []: print "No notations declared." else: nots.sort() for notation in nots: print notation # --- Head print print "xmlproc version %s" % xmlproc.version # --- Argument interpretation try: (options,sysids)=getopt.getopt(sys.argv[1:],"",["list"]) except getopt.error,e: print "Usage error: "+e print usage sys.exit(1) options = paired_list_to_hash(options) list = options.has_key("--list") # --- Initialization parser=dtdparser.DTDParser() if list: dtd = xmldtd.CompleteDTD(parser) parser.set_dtd_consumer(dtd) parser.set_error_handler(utils.ErrorPrinter(parser)) # --- Parsing for sysid in sysids: print "Parsing",sysid parser.parse_resource(sysid) print "Parsing complete" # --- Reporting if list: listdecls(dtd) PyXML-0.8.2/demo/xmlproc/dtddoc.py0100644000076400001440000000561107413602741016142 0ustar martinusersfrom xml.parsers.xmlproc import dtdparser,xmlapp,xmldtd,utils import sys # --- Utility functions def print_cm(out,cm): if cm==None: out.write("ANY") return elif cm[1]==[]: out.write("EMPTY") return (sep,cont,mod)=cm out.write("(") for item in cont[:-1]: if len(item)==2: out.write('%s%s %s ' % (item[0],item[0],item[1], sep)) else: print_cm(out,item) out.write(sep+" ") item=cont[-1] if len(item)==2: out.write('%s%s' % (item[0],item[0],item[1])) else: print_cm(out,item) out.write(sep+" ") out.write(")%s " % mod) # --- Main program if len(sys.argv) != 2: print "Usage: dtddoc.py [file name of DTD file]" sys.exit(1) # Parsing the DTD print "Parsing DTD" dp=dtdparser.DTDParser() dp.set_error_handler(utils.ErrorPrinter(dp)) dtd=xmldtd.CompleteDTD(dp) #dtd.compile_content_models(0) dp.set_dtd_consumer(dtd) dp.parse_resource(sys.argv[1]) # Processing the DTD print "Processing DTD" parents={} def traverse_cm(cur,cm): if cm==None: return for item in cm[1]: if len(item)==2: try: parents[item[0]][cur]=1 except KeyError: print "ERROR: Undeclared element '%s'" % item[0] else: traverse_cm(cur,item) parents["#PCDATA"]={} for elem_name in dtd.get_elements(): parents[elem_name]={} for elem_name in dtd.get_elements(): elem=dtd.get_elem(elem_name) traverse_cm(elem_name,elem.get_content_model()) # Printing documentation print "Printing documentation" out=open("out.html","w") out.write( """ DTD Documentation

    DTD Documentation

    """) elems=dtd.get_elements() elems.sort() for elem_name in elems: out.write('

    %s

    ' % (elem_name,elem_name)) out.write("

    Parents

    ") out.write("

    ") ps=parents[elem_name].keys() ps.sort() for p in ps: out.write('%s ' % (p,p)) out.write("

    ") elem=dtd.get_elem(elem_name) out.write("

    Content model

    ") print_cm(out,elem.get_content_model()) out.write("

    Attributes

    ") out.write("") out.write("
    Name Type Declaration Default") attrs=elem.get_attr_list() attrs.sort() for attr_name in attrs: attr=elem.get_attr(attr_name) out.write("
    %s %s %s " % (attr_name,attr.get_type(),attr.get_decl())) if attr.get_default()!=None: out.write("'%s'" % attr.get_default()) out.write("
    ") out.write( """
    Produced by dtddoc.py, using xmlproc.
    """) out.close() PyXML-0.8.2/demo/xmlproc/nstest1.xml0100644000076400001440000000117206660162325016452 0ustar martinusers
    NameOriginDescription
    Huntsman Bath, UK
    BitterFuggles Wonderful hop, light alcohol, good summer beer Fragile; excessive variance pub to pub
    PyXML-0.8.2/demo/xmlproc/outputters.py0100644000076400001440000000321407413602741017134 0ustar martinusers# This module contains common functionality used by xvcmd.py and xpcmd.py import sys,string from xml.parsers.xmlproc import xmlapp, utils # Backwards compatibility declarations ESISDocHandler = utils.ESISDocHandler Canonizer = utils.Canonizer DocGenerator = utils.DocGenerator # Error handler class MyErrorHandler(xmlapp.ErrorHandler): def __init__(self, locator, parser, warnings, entstack, rawxml): xmlapp.ErrorHandler.__init__(self,locator) self.show_warnings=warnings self.show_entstack=entstack self.show_rawxml=rawxml self.parser=parser self.reset() def __show_location(self,prefix,msg): print "%s:%s: %s" % (prefix,self.get_location(),msg) if self.show_entstack: print " Document entity" for item in self.parser.get_current_ent_stack(): print " %s: %s" % item if self.show_rawxml: raw=self.parser.get_raw_construct() if len(raw)>50: print " Raw construct too big, suppressed." else: print " '%s'" % raw def get_location(self): return "%s:%d:%d" % (self.locator.get_current_sysid(),\ self.locator.get_line(), self.locator.get_column()) def warning(self,msg): if self.show_warnings: self.__show_location("W",msg) self.warnings=self.warnings+1 def error(self,msg): self.fatal(msg) def fatal(self,msg): self.__show_location("E",msg) self.errors=self.errors+1 def reset(self): self.errors=0 self.warnings=0 PyXML-0.8.2/demo/xmlproc/urls.xml0100644000076400001440000001040406660162325016034 0ustar martinusers Pyhoo! This is a collection of useful pointers to Python-related material of various sorts. It grew out of my personal bookmarks collection, and is now maintained in XBEL, the XML Bookmark Exchange Language, partly as an experiment, partly as a demo for xmlproc and partly as a service for the public and myself. Introductions Introduction pointers @ python.org A set of pointers to Python introductions. The Python FAQ Comparisons of Python and other languages The Quick Python Book An online draft of an upcoming Python tutorial book by Ken McDonald. Python in the press Python: It's not just for laughs An article in WebReview about Python. References Python 1.5 Quick Reference A very concise and useful reference of Python minutiae. Tips and tricks Python Performance Tips Some hints on which style and constructs to use to achieve the best Python performance. Topic guides Sockets A guide to socket programming with Python. Tkinter guides and documentation An introduction to Tkinter, a class reference and the Tk manual pages, all linked to from the Pythonware library page. The Python CGI FAQ Topic Guides @ python.org This is a collection of topic guides as a part of the Python language website. Among the topics are XML, databases, Tkinter and web programming. HOWTOs @ python.org A collection of HOWTO guides, covering Medusa, Curses, Qt, regular expressions and XML, among other things. Development environments Emacs modes for Python This site contains some useful elisp packages such as a Python mode, a debugger mode etc. PTUI A Tkinter-based IDE by Zachary Roadhouse. CoolEdit A text editor with Python scripting internally. XWindows-only. UltraEdit A general text editor for Windows. Python syntax support can be downloaded separately. Miscellaneous The Python Journal A web journal devoted to Python. Python-Friendly ISPs A list of web host providers that also provide Python access for CGI and suchlike. PyXML-0.8.2/demo/xmlproc/wxValidator.py0100644000076400001440000001764707413602741017221 0ustar martinusersimport os, cStringIO, string from wxPython.wx import * from xml.parsers.xmlproc import xmlval,xmlapp,xcatalog,catalog,errors, utils # Todo: # - bookmarks or something for sysid entry (make general bm and last-used?) # - radio group for Output: None, Canonical XML, ESIS # - tick box: namespace processing # - File | About # - File | Help # --- Constants XML_WILDCARD = "XML documents (*.xml)|*.xml|RDF documents (*.rdf)|*.rdf|XSL stylesheets (*.xsl)|*.xsl|All files|*.*" CAT_WILDCARD = "SGML Open catalogs (*.soc)|*.soc|XCatalogs (*.xml)|*.xml|All files|*.*" # --- Application class Validator(wxApp): def OnInit(self): frame = MainWindow(NULL, -1, "wxValidator") frame.Show(true) self.SetTopWindow(frame) return true # --- ErrorHandler class ErrorRecorder(xmlapp.ErrorHandler): def __init__(self,locator,warnings=1): xmlapp.ErrorHandler.__init__(self,locator) self.show_warnings=warnings self.reset() def warning(self,msg): if self.show_warnings: self.__add_error(msg) def error(self,msg): self.__add_error(msg) def fatal(self,msg): self.__add_error(msg) def reset(self): self.errors=[] def __add_error(self,msg): self.errors.append((self.locator.get_current_sysid(), self.locator.get_line(), self.locator.get_column(), msg)) # --- Output window class OutputWindow(wxFrame): def __init__(self, parent, output): wxFrame.__init__(self, parent, -1, "Output") wxTextCtrl(self, -1, output, wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE) # --- Main window ID_DOCUMENT = NewId() ID_CATALOG = NewId() ID_EXIT = NewId() class MainWindow(wxFrame): def __init__(self, parent, ID, title): wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(550, 450)) self.SetAutoLayout(true) self.CreateStatusBar(1) # --- Menu menu = wxMenu() menu.Append(ID_DOCUMENT, "&Find document", "Find a document to validate") menu.Append(ID_CATALOG, "Find &catalog", "Find a catalog to resolve public identifiers with") menu.Append(ID_EXIT, "E&xit", "Terminate the program") menuBar = wxMenuBar() menuBar.Append(menu, "&File"); self.SetMenuBar(menuBar) EVT_MENU(self, ID_DOCUMENT, self.FindDocument) EVT_MENU(self, ID_CATALOG, self.FindCatalog) EVT_MENU(self, ID_EXIT, self.TimeToQuit) # --- Field: XML document location loc=wxTextCtrl(self,-1,"") lc=wxLayoutConstraints() lc.top.SameAs(self, wxTop, 5) lc.height.AsIs() lc.left.SameAs(self, wxLeft, 5) lc.right.SameAs(self, wxRight, 5) loc.SetConstraints(lc) # --- Field: Catalog file location cat_loc="" if os.environ.has_key("XMLXCATALOG"): cat_loc=os.environ["XMLXCATALOG"] elif os.environ.has_key("XMLSOCATALOG"): cat_loc=os.environ["XMLSOCATALOG"] cat=wxTextCtrl(self,-1,cat_loc) lc=wxLayoutConstraints() lc.top.SameAs(loc, wxBottom, 5) lc.height.AsIs() lc.left.SameAs(self, wxLeft, 5) lc.right.SameAs(self, wxRight, 5) cat.SetConstraints(lc) # --- A containing panel for a row of controls panel=wxPanel(self,-1) lc=wxLayoutConstraints() lc.top.SameAs(cat, wxBottom) lc.height.AsIs() lc.left.SameAs(self, wxLeft) lc.right.SameAs(self, wxRight) panel.SetConstraints(lc) # --- Buttons parse_id=NewId() parse_btn=wxButton(panel,parse_id,"Parse") lc=wxLayoutConstraints() lc.top.SameAs(panel, wxTop, 5) lc.height.AsIs() lc.left.SameAs(panel, wxLeft, 5) lc.width.AsIs() parse_btn.SetConstraints(lc) EVT_BUTTON(self, parse_id, self.Parse) # --- Field: Language lang=wxComboBox(panel,-1) # FIXME: want to set style lc=wxLayoutConstraints() lc.top.SameAs(panel, wxTop, 5) lc.height.AsIs() lc.left.SameAs(parse_btn, wxRight, 5) lc.width.AsIs() lang.SetConstraints(lc) for lang_name in errors.get_language_list(): lang.Append(lang_name) lang.SetSelection(0) # --- Field: Warnings warn=wxCheckBox(panel, -1, "Warnings") lc=wxLayoutConstraints() lc.top.SameAs(panel, wxTop, 5) lc.height.AsIs() lc.left.RightOf(lang, 5) lc.width.AsIs() warn.SetConstraints(lc) # --- Field: Output? output = wxCheckBox(panel, -1, "Show output") lc = wxLayoutConstraints() lc.top.SameAs(panel, wxTop, 5) lc.height.AsIs() lc.left.RightOf(warn, 5) lc.width.AsIs() output.SetConstraints(lc) # --- Error list list_id = NewId() list = wxListCtrl(self, list_id, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxSUNKEN_BORDER) list.InsertColumn(0,"System identifier") list.InsertColumn(1,"Line") list.InsertColumn(2,"Column") list.InsertColumn(3,"Message") lc=wxLayoutConstraints() lc.top.SameAs(panel, wxBottom, 5) lc.bottom.SameAs(self, wxBottom, 5) lc.left.SameAs(self, wxLeft, 5) lc.right.SameAs(self, wxRight, 5) list.SetConstraints(lc) # --- Global data self.loc=loc self.cat=cat self.list=list self.parser=xmlval.XMLValidator() self.errors=ErrorRecorder(self.parser) self.lang=lang self.warn=warn self.output = output def Parse(self, *args): sysid = string.strip(self.loc.GetValue()) if sysid == "": self.SetStatusText("Nothing to parse") return self.parser.reset() self.errors.reset() self.errors.show_warnings = self.warn.GetValue() if self.cat.GetValue != "": self.SetStatusText("Parsing catalog...") pf=xcatalog.FancyParserFactory() cat=catalog.xmlproc_catalog(self.cat.GetValue(),pf,self.errors) self.parser.set_pubid_resolver(cat) self.SetStatusText("Parsing...") if self.output.GetValue(): output = cStringIO.StringIO() self.parser.set_application(utils.DocGenerator(output)) self.parser.set_error_handler(self.errors) self.parser.set_error_language(self.lang.GetValue()) self.parser.parse_resource(sysid) self.list.DeleteAllItems() ix=0 for (sysid,line,col,msg) in self.errors.errors: self.list.InsertStringItem(ix, sysid) self.list.SetStringItem(ix, 1, `line`) self.list.SetStringItem(ix, 2, `col`) self.list.SetStringItem(ix, 3, msg) ix=ix+1 self.list.SetColumnWidth(0, wxLIST_AUTOSIZE) self.list.SetColumnWidth(1, wxLIST_AUTOSIZE) self.list.SetColumnWidth(2, wxLIST_AUTOSIZE) self.list.SetColumnWidth(3, wxLIST_AUTOSIZE) if self.output.GetValue(): self.CreateOutputWindow(output) self.SetStatusText("Parse completed (%s error(s))" % ix) def CreateOutputWindow(self, output): win = OutputWindow(self, output.getvalue()) win.Show(true) def FindDocument(self, event): file = wxFileSelector("Find document", ".", "", "", XML_WILDCARD, wxOPEN | wxHIDE_READONLY) if file: self.loc.SetValue(file) def FindCatalog(self, event): file = wxFileSelector("Find catalog", ".", "", "", CAT_WILDCARD, wxOPEN | wxHIDE_READONLY) if file: self.cat.SetValue(file) def TimeToQuit(self, event): self.Close(true) # --- Main program app = Validator(0) app.MainLoop() PyXML-0.8.2/demo/xmlproc/xbel2html.py0100644000076400001440000000405107413602741016577 0ustar martinusers""" An XBEL to HTML converter useful for publishing XBEL bookmark lists on the web. """ import doctree,sys # --- Configuring out=sys.stdout inf=sys.argv[1] if len(sys.argv)>2: stylesheet=sys.argv[2] else: stylesheet=None # --- Templates top=\ """ %s %s

    %s

    """ bottom=\ """
    Converted by xbel2html.py, using xmlproc.
    """ # --- Conversion code # Writing document top root=doctree.build_tree(inf) title=doctree.get_pcdata(doctree.get_element(root,"title")) if stylesheet!=None: stylesheet=' \n' % \ stylesheet else: stylesheet="" out.write(top % (title,stylesheet,title)) desc=doctree.get_element(root,"desc") if desc!=None: out.write("

    \n%s\n

    \n\n" % doctree.get_pcdata(desc)) # Writing folder tree def output(folder,level): title=doctree.get_pcdata(doctree.get_element(folder,"title")) desc=doctree.get_element(folder,"desc") if desc!=None: desc=doctree.get_pcdata(desc) if level<3: out.write("\n%s\n" % (level+1,title,level+1)) if desc!=None: out.write("\n

    %s

    \n" % desc) else: a=2/0 bookmarks=doctree.get_elements(folder,"bookmark") if bookmarks!=[]: out.write("\n
      \n") for bookmark in bookmarks: url=bookmark[1]["href"] title=doctree.get_pcdata(doctree.get_element(bookmark,"title")) desc=doctree.get_element(bookmark,"desc") if desc!=None: desc=doctree.get_pcdata(desc) else: desc="" out.write("
    • %s. %s\n" % (url,title,desc)) out.write("
    \n") for child in doctree.get_elements(folder,"folder"): output(child,level+1) folders=doctree.get_elements(root,"folder") for folder in folders: output(folder,1) # Writing document bottom out.write(bottom) PyXML-0.8.2/demo/xmlproc/xpcmd.py0100644000076400001440000000607207413602741016016 0ustar martinusers#!/usr/bin/python """ A command-line interface to the xmlproc parser. It continues parsing even after fatal errors, in order to be find more errors, since this does not mean feeding data to the application after a fatal error (which would be in violation of the spec). """ usage=\ """ Usage: xpcmd.py [options] [urltodoc] ---Options: -l language: ISO 3166 language code for language to use in error messages -o format: Format to output parsed XML. 'e': ESIS, 'x': canonical XML and 'n': normalized XML. No data will be output if this option is not specified. urltodoc: URL to the document to parse. (You can use plain file names as well.) Can be omitted if a catalog is specified and contains a DOCUMENT entry. -n: Report qualified names as 'URI name'. (Namespace processing.) --nowarn: Don't write warnings to console. --entstck: Show entity stack on errors. --extsub: Read the external subset of documents. """ # --- INITIALIZATION import sys,outputters,getopt from xml.parsers.xmlproc import xmlproc # --- Interpreting options try: (options,sysids)=getopt.getopt(sys.argv[1:],"l:o:n", ["nowarn","entstck","rawxml","extsub"]) except getopt.error,e: print "Usage error: "+e print usage sys.exit(1) pf=None namespaces=0 app=xmlproc.Application() warnings=1 entstack=0 rawxml=0 extsub=0 p=xmlproc.XMLProcessor() for option in options: if option[0]=="-l": try: p.set_error_language(option[1]) except KeyError: print "Error language '%s' not available" % option[1] elif option[0]=="-o": if option[1]=="e" or option[1]=="E": app=outputters.ESISDocHandler() elif option[1]=="x" or option[1]=="X": app=outputters.Canonizer() elif option[1]=="n" or option[1]=="N": app=outputters.DocGenerator() else: print "Error: Unknown output format "+option[1] print usage elif option[0]=="-n": namespaces=1 elif option[0]=="--nowarn": warnings=0 elif option[0]=="--entstck": entstack=1 elif option[0]=="--rawxml": rawxml=1 elif option[0]=="--extsub": extsub=1 # Acting on option settings err=outputters.MyErrorHandler(p, p, warnings, entstack, rawxml) p.set_error_handler(err) if namespaces: from xml.parsers.xmlproc import namespace nsf=namespace.NamespaceFilter(p) nsf.set_application(app) p.set_application(nsf) else: p.set_application(app) if len(sysids)==0: print "You must specify a file to parse" print usage sys.exit(1) if extsub: p.set_read_external_subset(extsub) # --- Starting parse print "xmlproc version %s" % xmlproc.version for sysid in sysids: print print "Parsing '%s'" % sysid p.set_data_after_wf_error(0) p.parse_resource(sysid) print "Parse complete, %d error(s)" % err.errors, if warnings: print "and %d warning(s)" % err.warnings else: print err.reset() p.reset() PyXML-0.8.2/demo/xmlproc/xvcmd.py0100644000076400001440000001010607413602741016015 0ustar martinusers#!/usr/bin/python """ A command-line interface to the validating xmlproc parser. Prints error messages and can output the parsed data in various formats. """ usage=\ """ Usage: xvcmd.py [options] [urlstodocs] ---Options: -c catalog: path to catalog file to use to resolve public identifiers -l language: ISO 3166 language code for language to use in error messages -o format: Format to output parsed XML. 'e': ESIS, 'x': canonical XML and 'n': normalized XML. No data will be output if this option is not specified. urlstodocs: URLs to the documents to parse. (You can use plain file names as well.) Can be omitted if a catalog is specified and contains a DOCUMENT entry. -n: Report qualified names as 'URI name'. (Namespace processing.) --nowarn: Suppress warnings. --entstck: Show entity stack on errors. --rawxml: Show raw XML string where error occurred. Catalog files with URLs that end in '.xml' are assumed to be XCatalogs, all others are assumed to be SGML Open Catalogs. If the -c option is not specified the environment variables XMLXCATALOG and XMLSOCATALOG will be used (in that order). """ from xml.parsers.xmlproc import xmlval,catalog,xcatalog,xmlproc import outputters import sys, getopt, os, string # --- Utilities def print_usage(message): print message print usage sys.exit(1) # --- Initialization print "xmlproc version %s" % xmlval.version p=xmlval.XMLValidator() # --- Interpreting options try: (options,sysids)=getopt.getopt(sys.argv[1:],"c:l:o:n", ["nowarn","entstck","rawxml"]) except getopt.error,e: print_usage("Usage error: "+e) warnings=1 entstack=0 rawxml=0 cat=None pf=None namespaces=0 app=xmlproc.Application() err_lang=None for option in options: if option[0]=="-c": cat=option[1] elif option[0]=="-l": try: p.set_error_language(option[1]) err_lang=option[1] except KeyError: print "Error: Language '%s' not available" % option[1] elif option[0]=="-o": if string.lower(option[1]) == "e": app = outputters.ESISDocHandler() elif string.lower(option[1]) == "x": app = outputters.Canonizer() elif string.lower(option[1]) == "n": app = outputters.DocGenerator() else: print_usage("Error: Unknown output format " + option[1]) elif option[0]=="-n": namespaces=1 elif option[0]=="--nowarn": warnings=0 elif option[0]=="--entstck": entstack=1 elif option[0]=="--rawxml": rawxml=1 # Acting on option settings err = outputters.MyErrorHandler(p, p.parser, warnings, entstack, rawxml) p.set_error_handler(err) if namespaces: from xml.parsers.xmlproc import namespace nsf=namespace.NamespaceFilter(p) nsf.set_application(app) p.set_application(nsf) else: p.set_application(app) if cat!=None: pf=xcatalog.FancyParserFactory(err_lang) elif cat==None and os.environ.has_key("XMLXCATALOG"): cat=os.environ["XMLXCATALOG"] pf=xcatalog.XCatParserFactory(err_lang) elif cat==None and os.environ.has_key("XMLSOCATALOG"): cat=os.environ["XMLSOCATALOG"] pf=catalog.CatParserFactory(err_lang) if cat!=None: print "Parsing catalog file '%s'" % cat cat=catalog.xmlproc_catalog(cat,pf,err) p.set_pubid_resolver(cat) if len(sysids)==0: if cat==None: print_usage("You must specify a system identifier if no catalog is " "used") elif cat.get_document_sysid()==None: print_usage("You must specify a system identifier if the catalog has " "no DOCUMENT entry") sysids=[cat.get_document_sysid()] print "Parsing DOCUMENT '%s' from catalog" % sysids[0] # --- Parsing for sysid in sysids: print print "Parsing '%s'" % sysid p.parse_resource(sysid) print print "Parse complete, %d error(s)" % err.errors, if warnings: print "and %d warning(s)" % err.warnings else: print err.reset() p.reset() PyXML-0.8.2/demo/README0100644000076400001440000000124407165177647013541 0ustar martinusersThe various subdirectories here contain demo programs that show how to use various XML processing interfaces. The subdirectories are: dom Sample code that uses the DOM interface [demos not up to date, see xml/dom/demo] genxml Demonstration of generating XML from non-XML data, using DOM, SAX, and simply writing to a file. quotes A simple application which processes an XML markup for maintaining a list of quotations. sax Sample code that uses the SAX interface. sgmlop Benchmark example for the sgmlop parser [currently broken] xbel Code for XBEL, an XML markup for Web browser bookmark files. xmlproc Sample code for the xmlproc parser PyXML-0.8.2/doc/0040755000076400001440000000000007614726123012470 5ustar martinusersPyXML-0.8.2/doc/4DOM/0040755000076400001440000000000007614726123013173 5ustar martinusersPyXML-0.8.2/doc/4DOM/4DOM.web0100644000076400001440000002167407202313475014377 0ustar martinusers 4DOM Standards-Based XML and HTML manipulation using Python Fourthought, Inc. http://4Suite.org 2025-11-01 4Suite 0.9.2 released. 2025-10-11 4Suite 0.9.1 released. 2025-09-20 4Suite 0.9.0 released. 4DOM is now bundled therein 2025-07-24 4DOM 0.10.2 released 2025-06-06 4DOM 0.10.1 released 2025-05-24 4DOM 0.10.0 released 2025-03-16 4DOM 0.9.3 released 2025-01-25 4DOM 0.9.2 released 2025-01-03 4DOM 0.9.1 released 2025-12-19 4DOM 0.9.0 released 2025-10-21 4DOM 0.8.2 released 2025-09-14 4DOM 0.8.1 released 2025-08-31 4DOM 0.8.0 released 2025-02-07 4DOM 0.7.0 released 2025-11-20 4DOM 0.6.1 released 2025-11-04 4DOM 0.6.0 released 4DOM is a Python implementation of the document object model (DOM), a standard interface for manipulating XML and HTML documents developed by the World-Wide Web Consortium. 4DOM implements DOM Level 2 Core, Level 2 HTML and Document Traversal, and a few extensions. 4DOM is designed to allow developers rapidly design applications that read, write or manipulate HTML and XML. The current version is bundled with 4Suite . See the ChangeLog for notes on the current version. Download 4Suite install one of the binary packages. Alternatively, you can download the source instead and install using Python distutils as follows: python setup.py install See PACKAGES for more information about the available 4Suite packages. Be sure to check the README in the 4Suite package for more details. xml/dom Core DOM components (including XML classes) xml/dom/html HTML components xml/dom/ext Extensions and proprietary components xml/dom/docs (currently minimal) documentation DOCUMENTATION_PATH/4Suite/4DOM/demo Small scripts demonstrating some uses of 4DOM. See the README in this directory. DOCUMENTATION_PATH/4Suite/4DOM/test_suite Test scripts. Accessors/Mutators for Attributes Following discussion on the Python XML SIG mailing list, 4DOM provides two ways to access DOM interface attributes. As an example, the DOM IDL definition for the Node interface contains readonly attribute DOMString childNodes. This can be accessed as a simple Python attribute: node.childNodes, or as a method call using the Python/CORBA mapping for attributes: node._get_childNodes() [if childNodes were a read/write attribute, there would also be a node._set_childNodes()]. There is a slight speed advantage to using the latter convention. Document._get_ownerDocument() Document._get_ownerDocument() returns a pointer to itself. Creating HTML Element Nodes HTMLDocument.createElement() overrides the Document.CreateElement() method, looking up the specified tag and returning an instance of the propriate HTML node. For instance: # html_doc is an instance of HTMLDocument table_elem = html_doc.createElement("TABLE") # table_elem is an instance of HTMLTableElement 4DOM does not implement DOMString. Instead, the interfaces use a plain Python string instead. Note that Python strings do not have length limitations, and unicode is still in beta. The DOM Spec section on the removeAttribute method of the Element interface has some rules for Attribute removal with respect to default values. 4DOM only follows these rules if you remove attributes using the removeAttribute method, and the default attribute will not be properly set if you use removeNamedItem to remove an attribute from the NamedNodeMap returned by Element.getAttributes. The DOM ambiguously specifies that if the given name in the removeNamedItem method of NamedNodeMap not found, None is returned and an exception is raised. This isn't possible in most languages. 4DOM chooses to return None. 4DOM does not implement HTMLElement features strictly for browser environment, for example, blur and focus properties of HTMLSelectElement. Some methods of the DOM spec for HTML do not allow for errors associated with missing nodes. So, for example, HTMLDocument::setTitle() does not allow for the return of an error if the HTMLDocument does not have an HTMLHeadElement child. 4DOM, in these cases, will automatically add in needed elements in order to strictly follow the DOM interface spec. The methods for which 4DOM provides automatic document completion are: HTMLDocument::getDocumentElement() HTMLDocument::setTitle() HTMLDocument::getBody() HTMLDocument::setBody() HTMLTableElement::insertRow() HTMLTableRowElement::insertCell() See 4DOM Extensions for documentation of proprietary extensions and helper functions provided by 4DOM. For release notes and news, see http://4Suite.org The 4Suite users and support mailing list can be subscribed to, and archives viewed at http://lists.fourthought.com/mailman/listinfo/4suite 4Suite developers monitor the above list, and prefer for support to come thereby, but you can also contact them directly at support@4suite.org with questions and comments. You might also post messages to or check the archives of the Python xml-sig mailing list. PyXML-0.8.2/doc/4DOM/Extensions.api0100644000076400001440000005140207244607163016025 0ustar martinusers 4DOM Extensions 4DOM Extensions DOM Documentation on 4DOM extensions and deviations from the DOM specification. These are utility classes and functions that provide capabilities not yet specified in the DOM spec. Some of these facilities, such as factories and readers are expected to be specified in later levels of the DOM, so we try to keep our proprietary interfaces simple for now so that you can more painlessly migrate when relevant standards emerge. See the demo directory for examples exercising many of these extensions. Reading The Reader package allows you to parse source strings in XML and HTML into DOM trees. You select a reader module according to the nature of your input. The readers that come with 4DOM are as follows: PyExpat Read XML using pyexpat from PyXML. Does not support validation. HtmlLib Read HTML using Python's htmllib. Sax2 Read XML using the PyXML SAX2 package. DTD validation is option. Sax (deprecated) Read XML using the PyXML SAX package. DTD validation is option. Sgmlop Read XML using Sgmlop from PyXML. Does not support validation. The following two examples illustrate using PyExpat and HtmlLib readers. Replace with the appropriate module and use in your own code. # Parse XML using pyexpat from xml.dom.ext.reader import PyExpat reader = PyExpat.Reader() xml_doc = reader.fromStream(stream) #Parse HTML using htmllib from xml.dom.ext.reader import HtmlLib reader = HtmlLib.Reader() html_doc = reader.fromStream(stream) PyExpat Parse XML using pyexpat Reader Reusable utility to read XML documents. fromStream return a 4DOM node from the given stream streamPython file objectThe stream to be read for XML text ownerDocxml.dom.Document.DocumentA document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None. xml.dom.Document.Document or xml.dom.DocumentFragment.DocumentFragmenta new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created XML tree. fromString return a 4DOM node from the given string xmlStringstring or unicode objectThe string to be parsed for XML text ownerDocxml.dom.Document.DocumentA document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None. xml.dom.Document.Document or xml.dom.DocumentFragment.DocumentFragmenta new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created XML tree. fromUri return a 4DOM node from the given uri uriPython file objectThe uri from which XML text is to be retrieved ownerDocxml.dom.Document.DocumentA document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None. xml.dom.Document.Document or xml.dom.DocumentFragment.DocumentFragmenta new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created XML tree. HtmlLib Parse HTML using htmllib Reader Reusable utility to read HTML documents. fromStream return a 4DOM node from the given stream streamPython file objectThe stream to be read for HTML text ownerDocxml.dom.Document.DocumentA document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None. charsetstringThe character set of the HTML text. If None or empty string, the default is ISO-8859-1. Default is empty string. xml.dom.Document.Document or xml.dom.DocumentFragment.DocumentFragmenta new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created HTML tree. fromString return a 4DOM node from the given string htmlStringstring or unicode objectThe string to be parsed for HTML text ownerDocxml.dom.Document.DocumentA document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None. charsetstringThe character set of the HTML text. If None or empty string, the default is ISO-8859-1. Default is empty string. xml.dom.Document.Document or xml.dom.DocumentFragment.DocumentFragmenta new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created HTML tree. fromUri return a 4DOM node from the given uri uriPython file objectThe uri from which HTML text is to be retrieved ownerDocxml.dom.Document.DocumentA document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None. charsetstringThe character set of the HTML text. If None or empty string, the default is ISO-8859-1. Default is empty string. xml.dom.Document.Document or xml.dom.DocumentFragment.DocumentFragmenta new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created HTML tree. Printing/Writing The Printer module allows you to write a text representation of DOM nodes to an output stream, including stdout. Note that limitations in the SAX interface used to parse in XML files, and in the DOM spec itself make it impossible at this point to handle an unchanged "round trip". That is, if you use the builder to build a DOM node from text and then use the Printer to turn it back to text, there may be differences; some may be significant. The easiest way to use the Printer module is through the front-end functions in the xml.dom.ext package. xml.dom.ext.Print Render the DOM tree to text with no special formatting. rootxml.dom.NodeThe node to be printed, with all its children recursively. streamoutput streamThe output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout. encodingstringThe character encoding to use for output. Default is 'UTF-8'. xml.dom.ext.PrettyPrint Render the DOM tree to text, with added indentation and new-lines for enhanced readability. rootxml.dom.NodeThe node to be pretty-printed, with all its children recursively. streamoutput streamThe output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout. encodingstringThe character encoding to use for output. Default is 'UTF-8'. indentstringThe amount by which nested constructs are indented when printed on a fresh line. Default is '\t'. widthpositive integerThe width of the output console. Used to make line-break decisions. Default is 80. preserveElementslist of strings, each of which is an SGML generic identifier.Specifes elements in which white-space shouldn't be added. Note that white-space is never added to in-line elements in an HTMLDocument. Default is None. xml.dom.ext.XHtmlPrint Render an HTML DOM tree as XHTML with no special indentation or formatting. rootxml.dom.NodeThe HTML node to be printed, with all its children recursively. streamoutput streamThe output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout. encodingstringThe character encoding to use for output. Default is 'UTF-8'. xml.dom.ext.XHtmlPrettyPrint Render an HTML DOM tree to text, with added indentation and new-lines for enhanced readability. rootxml.dom.NodeThe node to be pretty-printed, with all its children recursively. streamoutput streamThe output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout. encodingstringThe character encoding to use for output. Default is 'UTF-8'. indentstringThe amount by which nested constructs are indented when printed on a fresh line. Default is '\t'. widthpositive integerThe width of the output console. Used to make line-break decisions. Default is 80. preserveElementslist of strings, each of which is an SGML generic identifier.Specifes elements in which white-space shouldn't be added. Note that white-space is never added to in-line elements in an HTMLDocument. Default is None. Miscellaneous xml.dom.ext.NodeTypeToInterface Look up a node type (as returned from getNodeType()) and returns a corresponding interface name. nodeTypeOne of the integers defined as node types in xml.dom.NodeThe node type to look up. stringName of corresponding DOM interface from spec. xml.dom.ext.StripHtml Strips extraneous white-space from an HTML DOM tree. startNodexml.dom.NodeThe node to be stripped, with all its children recursively. preserveElementslist of strings, each of which is an SGML generic identifier, or None to indicate an empty list.Specifes elements from which white-space shouldn't be stripped. Note that white-space is never stripped from in-line elements in an HTMLDocument. Default is None. xml.dom.NodeThe startNode with descendant ignorable white-space stripped. xml.dom.ext.StripXml Strips extraneous white-space from an XML DOM tree. Takes xml:space attributes into account. startNodexml.dom.NodeThe node to be stripped, with all its children recursively. preserveElementslist of strings, each of which is an SGML generic identifier, or None to indicate an empty list.Specifes elements from which white-space shouldn't be stripped. Default is None. xml.dom.NodeThe startNode with descendant ignorable white-space stripped. xml.dom.ext.GetElementById Returns the element node whose "ID" attribute is as given. startNodexml.dom.NodeThe node whose descendants are to be searched. targetIdstring conforming to XML ID typeThe XML ID to find. xml.dom.ElementThe elemtn with the given ID, or None to indicate no match. xml.dom.ext.GetAllNs Returns all the namespaces in effect on the given node, including the default namespace and the xml namespace. nodexml.dom.NodeThe node for which all in-scope namespaces are returned. doctionaryDictionary mapping all in-scope namespaces to URIs, with '' as prefix for the default namespace. xml.dom.ext.XmlSpaceState Determines whether the xml:space state at a given node is "preserve" or "default" (See the XML 1.0 spec). nodexml.dom.NodeThe node whose space state is to be found. string"preserve" or "default". xml.dom.ext.SplitQName Splits a valid QName from the XML Namespaces 1.0 spec into prefix and suffix (the local name in the case of element and attribute names, and the declared prefix in the case of namespace declarations. qnamestring matching QName production in XML Namespaces 1.0 specThe name to be split. tuple with 2 items.a tuple of the form (prefix, suffix). If there is exactly one colon in the qname, prefix is the part before and suffix the part after the colon. Otherwise prefix is '' and suffix is the entire input string. PyXML-0.8.2/doc/4DOM/Extensions.html0100644000076400001440000007302107244607163016221 0ustar martinusers 4DOM Extensions

    4DOM Extensions


    These are utility classes and functions that provide capabilities not yet specified in the DOM spec. Some of these facilities, such as factories and readers are expected to be specified in later levels of the DOM, so we try to keep our proprietary interfaces simple for now so that you can more painlessly migrate when relevant standards emerge.

    See the demo directory for examples exercising many of these extensions.

    Reading

    The Reader package allows you to parse source strings in XML and HTML into DOM trees. You select a reader module according to the nature of your input. The readers that come with 4DOM are as follows:

    PyExpat
    Read XML using pyexpat from PyXML. Does not support validation.
    HtmlLib
    Read HTML using Python's htmllib.
    Sax2
    Read XML using the PyXML SAX2 package. DTD validation is option.
    Sax (deprecated)
    Read XML using the PyXML SAX package. DTD validation is option.
    Sgmlop
    Read XML using Sgmlop from PyXML. Does not support validation.

    The following two examples illustrate using PyExpat and HtmlLib readers. Replace with the appropriate module and use in your own code.

    # Parse XML using pyexpat
    from xml.dom.ext.reader import PyExpat
    reader = PyExpat.Reader()
    xml_doc = reader.fromStream(stream)
    #Parse HTML using htmllib
    from xml.dom.ext.reader import HtmlLib
    reader = HtmlLib.Reader()
    html_doc = reader.fromStream(stream)
    

    Module PyExpat

    Parse XML using pyexpat

    Module Summary

    Classes

    Class Summary
    Reader Reusable utility to read XML documents. 

     

    Class Reader

    Reusable utility to read XML documents.

    Method Summary
    fromStream return a 4DOM node from the given stream 
    fromString return a 4DOM node from the given string 
    fromUri return a 4DOM node from the given uri 

     

    Method Details

    fromStream

    fromStream(stream, ownerDoc)
          

    return a 4DOM node from the given stream

    Parameters
    stream of type Python file object

    The stream to be read for XML text

    ownerDoc of type xml.dom.Document.Document

    A document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None.

    Return Value

    a new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created XML tree.



    fromString

    fromString(xmlString, ownerDoc)
          

    return a 4DOM node from the given string

    Parameters
    xmlString of type string or unicode object

    The string to be parsed for XML text

    ownerDoc of type xml.dom.Document.Document

    A document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None.

    Return Value

    a new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created XML tree.



    fromUri

    fromUri(uri, ownerDoc)
          

    return a 4DOM node from the given uri

    Parameters
    uri of type Python file object

    The uri from which XML text is to be retrieved

    ownerDoc of type xml.dom.Document.Document

    A document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None.

    Return Value

    a new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created XML tree.



    Module HtmlLib

    Parse HTML using htmllib

    Module Summary

    Classes

    Class Summary
    Reader Reusable utility to read HTML documents. 

     

    Class Reader

    Reusable utility to read HTML documents.

    Method Summary
    fromStream return a 4DOM node from the given stream 
    fromString return a 4DOM node from the given string 
    fromUri return a 4DOM node from the given uri 

     

    Method Details

    fromStream

    fromStream(stream, ownerDoc, charset)
          

    return a 4DOM node from the given stream

    Parameters
    stream of type Python file object

    The stream to be read for HTML text

    ownerDoc of type xml.dom.Document.Document

    A document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None.

    charset of type string

    The character set of the HTML text. If None or empty string, the default is ISO-8859-1. Default is empty string.

    Return Value

    a new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created HTML tree.



    fromString

    fromString(htmlString, ownerDoc, charset)
          

    return a 4DOM node from the given string

    Parameters
    htmlString of type string or unicode object

    The string to be parsed for HTML text

    ownerDoc of type xml.dom.Document.Document

    A document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None.

    charset of type string

    The character set of the HTML text. If None or empty string, the default is ISO-8859-1. Default is empty string.

    Return Value

    a new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created HTML tree.



    fromUri

    fromUri(uri, ownerDoc, charset)
          

    return a 4DOM node from the given uri

    Parameters
    uri of type Python file object

    The uri from which HTML text is to be retrieved

    ownerDoc of type xml.dom.Document.Document

    A document to be used as owner of all the created nodes. If None, a new document instance is created for the nodes. Default is None.

    charset of type string

    The character set of the HTML text. If None or empty string, the default is ISO-8859-1. Default is empty string.

    Return Value

    a new document instance, or if the ownerDoc argument was not None, a document fragment. In either case, the returned node roots the created HTML tree.



    Printing/Writing

    The Printer module allows you to write a text representation of DOM nodes to an output stream, including stdout. Note that limitations in the SAX interface used to parse in XML files, and in the DOM spec itself make it impossible at this point to handle an unchanged "round trip". That is, if you use the builder to build a DOM node from text and then use the Printer to turn it back to text, there may be differences; some may be significant.

    The easiest way to use the Printer module is through the front-end functions in the xml.dom.ext package.

    xml.dom.ext.Print

    xml.dom.ext.Print(root, stream, encoding)
          

    Render the DOM tree to text with no special formatting.

    Parameters
    root of type xml.dom.Node

    The node to be printed, with all its children recursively.

    stream of type output stream

    The output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout.

    encoding of type string

    The character encoding to use for output. Default is 'UTF-8'.

    Return Value
    None


    xml.dom.ext.PrettyPrint

    xml.dom.ext.PrettyPrint(root, stream, encoding, indent, width, preserveElements)
          

    Render the DOM tree to text, with added indentation and new-lines for enhanced readability.

    Parameters
    root of type xml.dom.Node

    The node to be pretty-printed, with all its children recursively.

    stream of type output stream

    The output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout.

    encoding of type string

    The character encoding to use for output. Default is 'UTF-8'.

    indent of type string

    The amount by which nested constructs are indented when printed on a fresh line. Default is '\t'.

    width of type positive integer

    The width of the output console. Used to make line-break decisions. Default is 80.

    preserveElements of type list of strings, each of which is an SGML generic identifier.

    Specifes elements in which white-space shouldn't be added. Note that white-space is never added to in-line elements in an HTMLDocument. Default is None.

    Return Value
    None


    xml.dom.ext.XHtmlPrint

    xml.dom.ext.XHtmlPrint(root, stream, encoding)
          

    Render an HTML DOM tree as XHTML with no special indentation or formatting.

    Parameters
    root of type xml.dom.Node

    The HTML node to be printed, with all its children recursively.

    stream of type output stream

    The output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout.

    encoding of type string

    The character encoding to use for output. Default is 'UTF-8'.

    Return Value
    None


    xml.dom.ext.XHtmlPrettyPrint

    xml.dom.ext.XHtmlPrettyPrint(root, stream, encoding, indent, width, preserveElements)
          

    Render an HTML DOM tree to text, with added indentation and new-lines for enhanced readability.

    Parameters
    root of type xml.dom.Node

    The node to be pretty-printed, with all its children recursively.

    stream of type output stream

    The output stream. Note: can be a StringIO object if you want to generate a string instead. Default is sys.stdout.

    encoding of type string

    The character encoding to use for output. Default is 'UTF-8'.

    indent of type string

    The amount by which nested constructs are indented when printed on a fresh line. Default is '\t'.

    width of type positive integer

    The width of the output console. Used to make line-break decisions. Default is 80.

    preserveElements of type list of strings, each of which is an SGML generic identifier.

    Specifes elements in which white-space shouldn't be added. Note that white-space is never added to in-line elements in an HTMLDocument. Default is None.

    Return Value
    None


    Miscellaneous

    xml.dom.ext.NodeTypeToInterface

    xml.dom.ext.NodeTypeToInterface(nodeType)
          

    Look up a node type (as returned from getNodeType()) and returns a corresponding interface name.

    Parameters
    nodeType of type One of the integers defined as node types in xml.dom.Node

    The node type to look up.

    Return Value
    string

    Name of corresponding DOM interface from spec.



    xml.dom.ext.StripHtml

    xml.dom.ext.StripHtml(startNode, preserveElements)
          

    Strips extraneous white-space from an HTML DOM tree.

    Parameters
    startNode of type xml.dom.Node

    The node to be stripped, with all its children recursively.

    preserveElements of type list of strings, each of which is an SGML generic identifier, or None to indicate an empty list.

    Specifes elements from which white-space shouldn't be stripped. Note that white-space is never stripped from in-line elements in an HTMLDocument. Default is None.

    Return Value
    xml.dom.Node

    The startNode with descendant ignorable white-space stripped.



    xml.dom.ext.StripXml

    xml.dom.ext.StripXml(startNode, preserveElements)
          

    Strips extraneous white-space from an XML DOM tree. Takes xml:space attributes into account.

    Parameters
    startNode of type xml.dom.Node

    The node to be stripped, with all its children recursively.

    preserveElements of type list of strings, each of which is an SGML generic identifier, or None to indicate an empty list.

    Specifes elements from which white-space shouldn't be stripped. Default is None.

    Return Value
    xml.dom.Node

    The startNode with descendant ignorable white-space stripped.



    xml.dom.ext.GetElementById

    xml.dom.ext.GetElementById(startNode, targetId)
          

    Returns the element node whose "ID" attribute is as given.

    Parameters
    startNode of type xml.dom.Node

    The node whose descendants are to be searched.

    targetId of type string conforming to XML ID type

    The XML ID to find.

    Return Value
    xml.dom.Element

    The elemtn with the given ID, or None to indicate no match.



    xml.dom.ext.GetAllNs

    xml.dom.ext.GetAllNs(node)
          

    Returns all the namespaces in effect on the given node, including the default namespace and the xml namespace.

    Parameters
    node of type xml.dom.Node

    The node for which all in-scope namespaces are returned.

    Return Value
    doctionary

    Dictionary mapping all in-scope namespaces to URIs, with '' as prefix for the default namespace.



    xml.dom.ext.XmlSpaceState

    xml.dom.ext.XmlSpaceState(node)
          

    Determines whether the xml:space state at a given node is "preserve" or "default" (See the XML 1.0 spec).

    Parameters
    node of type xml.dom.Node

    The node whose space state is to be found.

    Return Value
    string

    "preserve" or "default".



    xml.dom.ext.SplitQName

    xml.dom.ext.SplitQName(qname)
          

    Splits a valid QName from the XML Namespaces 1.0 spec into prefix and suffix (the local name in the case of element and attribute names, and the declared prefix in the case of namespace declarations.

    Parameters
    qname of type string matching QName production in XML Namespaces 1.0 spec

    The name to be split.

    Return Value
    tuple with 2 items.

    a tuple of the form (prefix, suffix). If there is exactly one colon in the qname, prefix is the part before and suffix the part after the colon. Otherwise prefix is '' and suffix is the entire input string.



    PyXML-0.8.2/doc/4DOM/Ranges.api0100644000076400001440000000340307244607163015103 0ustar martinusers 4DOM Ranges 4DOM Ranges DOM Documentation on 4DOM implementation of the Ranges Level II and the deviations from the specification. The implementation of Ranges in 4DOM supports all of the interfaces defined at http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ It does not support section 2.12, "Range modification under document mutation". The implementation of Ranges is written such that any Python compliant DOM implementation should be able to take advantage of them. The additional methods that an implementation needs to support are defined below. See the 4DOM test_suite directory for the file test_ranges.py to see examples of using ranges Range Creation To create a range from a document, simple call the createRange method. This is the only method that a DOM implementatio needs to add to allow range support. An implementation of this method will create a new instance of the xml.dom.Range.Range class passing the document into the constructor. For a complete listing of the interfaces on the Range instances, see the specification at http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ PyXML-0.8.2/doc/4DOM/Ranges.html0100644000076400001440000000405007244607163015275 0ustar martinusers 4DOM Ranges

    4DOM Ranges


    The implementation of Ranges in 4DOM supports all of the interfaces defined at http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ It does not support section 2.12, "Range modification under document mutation". The implementation of Ranges is written such that any Python compliant DOM implementation should be able to take advantage of them. The additional methods that an implementation needs to support are defined below.

    See the 4DOM test_suite directory for the file test_ranges.py to see examples of using ranges

    Range Creation

    To create a range from a document, simple call the createRange method. This is the only method that a DOM implementatio needs to add to allow range support. An implementation of this method will create a new instance of the xml.dom.Range.Range class passing the document into the constructor.

    For a complete listing of the interfaces on the Range instances, see the specification at http://www.w3.org/TR/DOM-Level-2-Traversal-Range/

    PyXML-0.8.2/doc/4DOM/index.html0100644000076400001440000001741007244607163015171 0ustar martinusers 4DOM version 0.10.2

    4DOM version 0.10.2

    4Suite http://FourThought.com/4Suite

    Copyright (c) 2000 Fourthought, Inc., USA

    http://lists.fourthought.com/mailman/listinfo/4suite or send mail too support@4suite.com

    Current version: 0.10.2

    License/Copyright

    4Suite is copyright Fourthought, Inc. (http://FourThought.com). Please read the file COPYRIGHT for the complete copyright andterms of license.

    Description

    4Suite is a collection of Python tools for XML processing and object-databases.

    The current version is 0.10.2. See the ChangeLog for notes on the current version.

    4Suite is an integrated packaging of several formerly separately-distributed components. These are as follows.

    2025-01-16: 4Suite 0.10.1 released.
    2025-11-30: 4Suite 0.10.0 released.
    2025-11-14: 4Suite 0.9.2 released, including first public release of DbDom and 4XLink.
    2025-10-11: 4Suite 0.9.1 released, including first public release of 4XPointer.
    2025-09-20: 4Suite 0.9.0 released. 4DOM, 4XPath, 4XSLT, and 4RDF are now bundled therein. Including first public release of 4ODS.

    Installation

    Download 4Suite install one of the binary packages. Alternatively, you can download the source instead and install using Python distutils as follows:

    python setup.py install

    See PACKAGES for more information about the available 4Suite packages.

    If you have difficulty installing this software, send a problem report to 4Suite@lists.fourthought.com describing the problem.

    For a complete installation instructions see the HOWTOs.

    4DOM

    4DOM is an implementation of the World-Wide Web Consortium recommended standard document object model for Python. 4DOM implements DOM Core level 2, HTML level 2 and Level 2 Document Traversal.

    4DOM is designed to allow developers rapidly design applications that read, write or manipulate HTML and XML.

    4DOM follows the Python DOM binding, for which there is some documentation in the development version of the Python 2.0 docs.

    Directory Structure

    xml/dom - Core DOM components (including XML classes)
    xml/dom/html - HTML components
    xml/dom/ext - Extensions and proprietary components
    xml/dom/docs - (currently minimal) documentation
    DOCUMENTATION_PATH/4Suite-0.10.2/demo/4DOM - Small scripts demonstrating some uses of 4DOM. See the README in this directory.
    DOCUMENTATION_PATH/4Suite-0.10.2/test_suite/4DOM - Test scripts.

    Accessors/Mutators for Attributes

    Following discussion on the Python XML SIG mailing list, 4DOM provides two ways to access DOM interface attributes. As an example, the DOM IDL definition for the Node interface contains readonly attribute DOMString childNodes. This can be accessed as a simple Python attribute: node.childNodes, or as a method call using the Python/CORBA mapping for attributes: node._get_childNodes() [if childNodes were a read/write attribute, there would also be a node._set_childNodes()]. There is a slight speed advantage to using the latter convention.

    Document._get_ownerDocument()

    Document._get_ownerDocument() returns a pointer to itself.

    Creating HTML Element Nodes

    HTMLDocument.createElement() overrides the Document.CreateElement() method, looking up the specified tag and returning an instance of the propriate HTML node. For instance:

              # html_doc is an instance of HTMLDocument
              table_elem = html_doc.createElement("TABLE")
              # table_elem is an instance of HTMLTableElement
            

    Deviations

    4DOM does not implement DOMString. Instead, the interfaces use a plain Python string or unicode object instead. Note that Python strings do not have particular length limitations, and Python 2.0 is required for unicode support.

    The DOM Spec sections on the removeAttribute, removeAttributeNS and removeAttributeNode method of the Element interface has some rules for Attribute removal with respect to default values. 4DOM only follows these rules if you remove attributes using the removeAttribute method, and the default attribute will not be properly set if you use removeNamedItem to remove an attribute from the NamedNodeMap returned by Element.getAttributes.

    4DOM does not implement HTMLElement features strictly for browser environment, for example, blur and focus properties of HTMLSelectElement.

    Some methods of the DOM spec for HTML do not allow for errors associated with missing nodes. So, for example, HTMLDocument::setTitle() does not allow for the return of an error if the HTMLDocument does not have an HTMLHeadElement child. 4DOM, in these cases, will automatically add in needed elements in order to strictly follow the DOM interface spec. The methods for which 4DOM provides automatic document completion are:

    HTMLDocument::getDocumentElement()
    HTMLDocument::setTitle()
    HTMLDocument::getBody()
    HTMLDocument::setBody()
    HTMLTableElement::insertRow()
    HTMLTableRowElement::insertCell()

    See 4DOM Extensions for documentation of proprietary extensions and helper functions provided by 4DOM.

    Quick Start

    There are demo files and test suites for each component in the documentation directories set up by Distutils. These should provide useful examples.

    Known Bugs

    See the TODO file

    Contact and Support

    For release notes and news, see http://4Suite.org

    Please consider joining the 4Suite users and support mailing list

    http://lists.fourthought.com/mailman/listinfo/4suite

    4Suite developers monitor the above list, and prefer for support requests to come thereby so that others can benefit from the discussion. If this is unsuitable, you can address the 4Suite developers directly:

    support@4suite.org PyXML-0.8.2/doc/xmlproc/0040755000076400001440000000000007614726123014154 5ustar martinusersPyXML-0.8.2/doc/xmlproc/artikler.css0100644000076400001440000000337506660162333016505 0ustar martinusers /* --- COMMON TO ALL ARTICLES --- */ BODY { margin-left: 15%; margin-right: 15%; margin-top: 5%; text-align: justify; background: white none; color: black } DFN { font-style: italic } CODE { color: #0000AA; background: white none; } H1,H2,H3,H4,H5,H6 { font-family: Arial, Helvetica, Sans-Serif; text-align: left } H1 { text-align: center } /* Overrides above rule as it appears below it */ .subtitle { text-align: center; font-size: 60% } H2 { padding-top: 2em } DT { font-weight: bold } .uferdig { color: #AA0000 } /* Used for parts not yet finished */ P.center { text-align: center } P.author { text-align: center } P.contents { text-align: center; padding-bottom: 2em } P.note { background: white none; color: #AA0000; font-weight: bold } DL { margin-left: 5% } DT { font-weight: bold } DD { padding-bottom: 0.7em } PRE { background: white none; color: #0000AA } A:link { background: white none; color: #0000EE } A:visited { background: white none; color: #551A8B } HR { padding-top: 1em } ADDRESS { font-size: small; font-style: italic } DIV.partof { font-size: small; text-align: right } #problemstilling { margin-left: 4%; margin-right: 4%; font-style: italic } BLOCKQUOTE { margin-left: 5%; font-style: italic; font-size: small } P.origin { text-align: right; margin-left: 10% } P.termdef { margin-left: 10%; margin-right: 10%; background-color: #f5dcb3; border-width: 1px; padding: 15px } UL { text-align: left } /* --- ONLY FOR THE CSS INTRO --- */ LI.serif { font-family: serif } LI.sans-serif { font-family: sans-serif } LI.fantasy { font-family: fantasy } LI.monospace { font-family: monospace } LI.cursive { font-family: cursive } PyXML-0.8.2/doc/xmlproc/basicapi.gif0100644000076400001440000001041407377133276016422 0ustar martinusersGIF87au,uI8g`(z#hln($mx͵p^'(1ŤtjL\Zz'(x=mLVn\[\NLvs.yDa6l'wZz\j"Ay5N_N;UG͢\(5*Vx> -Bn@'"(bwb'b $LWʕ' E^#k-4Dw"ͅ0ͥL:&Sө+15SU[2 a1q=/2l=26"]@w-W.2HۈEcvї,S 9$+DY3U@ ~RkP{NahMx {/ĵof;wDّ/y%d>Nm |J)\ϝ3lnsxQ3>*G>ǘ (!-LnCǵJ7 xXnm-WNE7z/} \ :@k5ƒJA`-x-Hb%8J0V;8N&NxlW>82Xjwf!1$PagRXEirY@Z(afSZeDA&B'N47LjyؔQA!`anad8 (*9%ERd{`@ƣ*&CSP,X`d 2tZ+[E)kfTj3!bP=1鬛p7h0*`_꯺-6=:,Q찫!KyF *.,A ʤh oz]1#ÑHCܠ1p6CLj}`=2`?rȢ)s+&vF-() ʡ(믪ۦ-kעM$]Ȋ;&I1 E68jzj@2Ps]oC ɮ8ɮ Ŷz+;ٮ7PoqҞ)Mvz4^x~&l!m{}w E|d2ֹDp2w)+n8G p֏"m\Oֹ 4Y6jI廿CBHPgH_$Cȥx;̀62WχbXHnja•dYXlbHcYʦ'>.`BOSk;3`W6  Q#/)b7<aܟD,/qkeAbv * WqD|.ҵsàtW #qЍ  9B1/udD%d-yAhƻL1c1s6–l51(>р:p4ynY`d xJ,,` È^`d)viIJDraFYa6ͭ)bzEh!g3p4M#1&nLwA\--%:wv~t|j~XvE w d>IFi B:ϥD`TD8j5G"9`U f/ٌi$]t%~ 24)o]Ii/i'ŪG-d}#>dEAfk8̴Rk3gѳXr U$*O`DJ%QXݏ.AiqPc4df nf5G6lY d]-2.֢/I D&J3v?#" R "2L/=$baץ) sa(.ˌqb*Sqz8.70b" )K><$ʐ,eo2bڄCfvMd&i&ЛWgm+sfn;ce-&aSŴ<)4o<<;{"`T+U>z4U47mI+`10:l%)^PKY`3>d eRժfbյF'c;vu¹UkNS- 5k۱8'}<5 (XYTavmMȺ{CwxN5p\2Mvȼs.( nzc>^G"L!A3܇D<A:f{A`mWpcݸkn1W'+Cgl}u15"]"f'*wA\˶4K [.y=f~ɸ>L0EO'?)1oh[M|/?ruSX=y/>3|g4o|{g*(iܑ3e tV)dzhoj~} g 'x.1 3k/x 5t ;xz!:=l@x9l GdL8aB=v Vb\8gQb]h{=Fj!hXAVpȆX7sxtv $nho/ևYBHH^vrxxo8HȈ A3NQyh}ix ዠ'7Q!E8]8ӕSטߨ~ang!،Vg((XQ`EcȏS wt(XV ɐ Ix&Wa qYi$%9,)b-'W}3Y# U9ɐ5i?yCx~aGJ DٔlȔKI%9EZ%i|-ɕR1f9bjoٖ#i*Ie8ғcz9Dhx)_Q遇ٔh ؘ?.sɗI NљI (9F`Yؚys)2ٖ9`ٛ{8jсYkĩy=ќX y)8ǝW ihiɎ ɞ׹)Y) ibUY) ʠ *.ڛ9eÀy3 ~H%j-y)+/1jء7~٣ڙ@Z) IxHʨmM SevYi=ȣ_OzPJieʠH`k*8q]`whp}znJh :xpQ 9Y!mHz` qjz:iڣ {+}{jKhD[FȇLLY'SRѲPVY7Fad ji[k jc۶+)}Jvh!zGS KHڷ7ǵ"ʸ+ʂ$+ef $ʹ;Ee$k.>3)(={eZM+&CE@#mieATVT%t˞$c7PoGUTIROUe8l8 Ees=ѓm{Ȃ;b!{H!% 뤪Su ^ +k ,{p1쉮W,!̦%,Lf),o~',j6dì0r:ܸ18ãwqD\ʍLj0:.?'ٳ% x<{lDyszS^9G[60­f0IHKw-eDy ^àGw)Eԩo,[h7!wh6b7MYp6)~~nJ?kqqK-wRs:ۼ 339O#/˜<㈻JKi_KN9Os MOTc@ p) DhQrM_ I8F8!3 C6~Jx:Ƒ# ͡) vT@ h[ĤEPId7i$( 26.{eV/20o)w `&eĤ1)br1ͳ<Ŭ& / i,#7(3)р!is.2)@S$HOy!@½5Hs2T }A2^F9bQs"A(R@5IIQv/5hLFqPftM-́t%H?j" @R]*ҩ44GKZӟ>';zdh5)SJĒLIRY'/$b'h'S80IX*QmK#3P1Zg^2P'fjLϦ'(\ bg'vXLF7[grʣ87 :po@l!XF$Ynm;-ӛEIy&dFBOh+%1.o5 , iۂl ѧcq`s=(w $rƤn>q0F&>ꁬ٩siA&fI|oY#%uŁz+>A0 ԃD8\yLOM)=J"ǶHq9-Y : .pf4Ru)s=qO"7 NjqQ!@7>2)e<;/1"t笹AL;MZHτFvGHȌA~@R' b`HdRdd,$".$u ^LcO'RG~Fб3W|I$<ziC6wy&;ً<6h=u8ɔ{=QcڒU&3/H?X's?qez1Vd!w?uC#_R)?X ?sZXp~1[y~@e PJw 񁑷zi5qеp(tpGQ`H6 Dq;@zdz1fH@M0l-,zgU:Qp`*2"p2,e@ǡ^ARQfBa&DU :GENmQFqG91tu%1eWyDާwmel WruaI;PyXML-0.8.2/doc/xmlproc/standard.css0100644000076400001440000000125407107047706016465 0ustar martinusers /* CSS style sheet for my web pages. */ BODY { margin-left: 10%; margin-right: 10%; margin-top: 24pt; margin-bottom: 12pt; } H1 { background: navy; color: white; padding: 3pt; padding-left: 7pt; font-family: Tahoma, Helvetica, sans-serif; margin-bottom: 24pt } H2, H3, H4, H5, H6 { font-family: Tahoma, Helvetica, sans-serif } ADDRESS { background: navy; color: white; padding: 3pt; font-size: small; font-style: italic; } .warning { font-weight: bold; color: red } .warning:before { content: "Warning: "; font-weight: bold; color: red } ADDRESS A:link { color: white; } ADDRESS A:visited { color: #DDD; }PyXML-0.8.2/doc/xmlproc/wxval.gif0100644000076400001440000001260307377133276016012 0ustar martinusersGIF89a& ????@?@@@P!,&????@?@@@PPI8ͻ`(dihlp (Lmx|pH,Ȥrl:Шtj,Dvr0x,.4zn8|.<~~yV41X   ݱBΠ VVW4D4R5hi!(2GŋsۀO:u/0"jىć3ɳg:*H-d($)׭_ {JƖGgUNIBނ7zY_WV!Wav!)HC Hj&&9h:|3לqs}4b8e"G$ LVPF)%7 Y%fWxPU:7d) 8kxN4MYti+N: f9\y砄n f袌6T"餔Vj饘fi#^駠*ꨤ3ꪬt j뭸:i8C&6˫m6+V [v<ݸm覫.f[Pkߊd'jۖxl G,ēKERp ,2 o'(rY0[`q4<6%:@CMF'J7NG RWMVgZw^ bMfjֈJsMvz~N'7GWNgw*onz騟z꬯z밿.{k/{.|o||?/}Oo}_=q+7/#-觯,,}x3o HD4'H Z̠7z GH( "׮YH gH8̡wbPv+_CHL&:1+4\VX̢.zч@F+~hL%FhݣH:xq81z IBCb^XDC:򑐌$G̤&7."2q\dR򔨜a%/H3򕰌,%IE ̥.wU2|0IAֲc1f~їB(]jZ=iMm~'?JP^,BK&H DKyPhS|h Gl} HGJҒ(MJW,0CԨLg +)y8]Nsӝ@PJT1{HݞRԥ:P}TYgˡZXVխz`5QJ֨h=Zֵv_kX*׺v+^ wI?]K)M:d'KZͬ8Hẃ h!YQIsMm (~lXڄ"k vS`pB  n2w4ssڞַt]W(s] :HgΒ`fNI[RR%>Oa}+!ٲ0A_O>`X%nG! 3{oj]7>KgXʓ1'#% ;ZuK<?_| bs_) w b;s =F#X}./[w#?ǽ&u) {"O@W> zd\'`{;!}]I_$CmaW|~g200C~bdz!GgB/~znQ(h0''W{ tv7}mƅ"zR{ Q308{NOh4PH7vW-\,Ԅ_/xÅZ([~*؆Qpc8xX ؅@~a8.3g}fx\CWdȄ2|lGX؇jH$8c%j=~]9_yH9eqwh.,-8HM-oٖ8b|sfX,)HB—薔By*p))Jp)*B~)/Y [yVL!dH1r~i#.'و)w8yrNٛiyUȖWX)i1hjY6w9MT%Nȉ2X(ɚɹy21v7epr*XHˉIX )IwTԖyٜJ b~ڗ9:2Zwvɛ %xǗx*)ٛIڃ3j,)Z~WUso5X; j*iZ*kg=v?zOK9wom:*y**{:} {!Pj(:Zzēr g*٩^דZPPzRd jjZĚNZ Nڪڬ6Ye:uqԚtڭ:J)䚮Χ:I ທ8ZGjLj[tj {FEz;G԰{M{C۱ M:![F&4*۲;.#2[d6T$˳@A0DKK#pE4J۴HR ʬS4\kL۵<˲`۵_;5f;e.+lk)rq[!xKwK~8k[ z[6۷1- +{&k˯۹y;s{J%˹ 뭭{ kۻ˻묹;+Ƌ+:˼ Fk;[JkỾ kJ+ۋkX˿+E kھ \ p |jo $|*).f0,"<6\5ø*J$A& .A0~->*8Ͻ`>AC5N{J1NPR>R>X1e\]^`a=f^h~jlnU9bp>r^eUkmz|[nN>^=Y+Su-:*1.02n/$~ꬎ.5:-h">-hBN-vľ,^+(Ў+N+.^>&NN)N훑ڮT~n+t. kw __ !#"$&,._013246@X:D_FHO;PyXML-0.8.2/doc/xmlproc/xmlproc-catalog-doco.html0100644000076400001440000003222607107047706021062 0ustar martinusers Documentation: Catalog support in xmlproc

    Documentation: Catalog support in xmlproc

    Contents:

    This page consists of the following sections:

    What are catalog files?

    What they do

    Catalog files are a means of telling a parser how to map public identifiers to system identifiers. One simple example of this would be to use a catalog file to tell an SGML parser that the DTD with the public identifier "-//W3C//DTD HTML 4.0 Transitional//EN" can be found at the location "file:///usr/pub/sgml/dtds/html40.dtd".

    In other words: a public identifier is a well-known name for something that is not site-dependent, while a system identifier tells applications how to find this thing on the local system. A catalog file can be used to find out where to find something at a particular site given its public identifier.

    In addition to this, catalog files can affect the parsing of documents in other ways as well.

    Where they come from?

    Catalog files come from the SGML community, but are not part of the SGML standard itself. The catalog file format and semantics are defined in SGML Open Technical Resolution TR9401:1997, and have since been implemented in the SP SGML parser, the DXP XML parser and xmlproc.

    The format used by SP (which extends the original format somewhat) has become the de facto standard for catalog files. xmlproc supports a subset of this format.

    The catalog file format

    Catalog files consist of entries: which start with a keyword, followed by arguments separated by whitespace. Arguments which contain spaces must be quoted. Entries are separated by whitespace and comments (which start with "--" and end with "--") can appear anywhere whitespace can appear.

    An example catalog file:

    -- DSSSL --
    PUBLIC "-//James Clark//DTD DSSSL Flow Object Tree//EN" "c:\programfiler\apps\jade\fot.dtd"
    PUBLIC "ISO/IEC 10179:1996//DTD DSSSL Architecture//EN" "c:\programfiler\apps\jade\dsssl.dtd"
    PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" "c:\programfiler\apps\jade\style-sheet.dtd"
    -- HTML 2 --
    PUBLIC  "-//IETF//DTD HTML//EN"                           html2.dtd
    PUBLIC  "-//IETF//DTD HTML 2.0//EN"                       html2.dtd
    

    Catalog file support in xmlproc

    Level of support

    The support for catalog files has not been thoroughly tested and xmlproc probably will not handle the cases where there are conflicts between entries correctly. This part of xmlproc should be considered to be of demonstration quality.

    xmlproc supports the following keywords:

    PUBLIC pubid sysid
    Specifies that the pubid should be mapped to sysid whenever it occurs.
    SYSTEM sysid1 sysid2
    Specifies that whenever sysid1 appears as the explicit system identifier sysid2 should be used instead.
    DOCUMENT sysid
    Specifies that if no document entity is supplied to the parser, this document should be parsed.
    CATALOG sysid
    Includes the catalog file at sysid.
    BASE sysid
    Uses sysid as the base system identifier to resolve relative system identifiers against below this point.
    DELEGATE pubid-prefix sysid
    Resolves public identifiers that begin with pubid-prefix with the catalog file at sysid.

    How to make xmlproc use a catalog file

    This is easily done. Here is some code that parses the catalog file referred to by the XMLSOCATALOG environment variable:

    
    import os
    from xml.parsers.xmlproc import xmlval,catalog
    p=xmlval.XMLValidator()
    cat=catalog.xmlproc_catalog(os.environ["XMLSOCATALOG"],\
                                catalog.CatParserFactory())
    p.set_pubid_resolver(cat)
    p.parse_resource(sysid)
    

    Using the catalog file parser

    The xmlproc implementation contains both a general catalog file parser and a general catalog file implementation, to which the xmlproc PubIdResolver is just one of many possible clients. This means that you can use this catalog file parser in your own applications.

    If you just want to make xmlproc use a catalog file you should look at the xmlproc_catalog class.

    The catalog module has the following classes and interfaces:

    The CatalogParser class

    The CatalogParser class is mainly useful if you want to develop your own catalog file support completely from scratch. It only parses the file and passes information to you, without doing anything with it. If you just want to query the parsed information you should probably look at the catalog manager below.

    The CatalogParser class has these methods:

    def __init__(self,error_lang=None):
    This creates a parser ready for parsing. The error language can be set if desired, and accepts the same values as xmlproc itself.
    def set_application(self,app):
    This tells the parser where to send parse events. The application object must conform to the CatalogApp interface.
    def set_error_handler(self,err):
    This tells the parser where to send error events. The error handler must conform to the usual ErrorHandler interface.
    def parse_resource(self,sysid):
    Parses the catalog file with the given system identifier, passing error and data events.

    The CatalogApp interface

    This is the definition of the interface used by applications that wish to receive catalog file parsing events. No attempt is made to interpret the entries or their parameters in any way. These methods are required:

    def handle_public(self,pubid,sysid):
    This notifies the application of a PUBLIC entry in the catalog file.
    def handle_delegate(self,prefix,sysid):
    This notifies the application of a DELEGATE entry in the catalog file.
    def handle_document(self,sysid):
    This notifies the application of a DOCUMENT entry in the catalog file.
    def handle_system(self,sysid1,sysid2):
    This notifies the application of a SYSTEM entry in the catalog file.
    def handle_base(self,sysid):
    This notifies the application of a BASE entry in the catalog file.
    def handle_catalog(self,sysid):
    This notifies the application of a CATALOG entry in the catalog file.

    The CatalogManager class

    The CatalogManager is a central class in the catalog implementation. Users that want to work with catalog files should instantiate a CatalogManager and let it parse and keep track of the catalog information for them, and only query it when information is needed.

    The CatalogManager class has these methods:

    def __init__(self):
    This creates an empty CatalogManager, ready for use.
    def set_error_handler(self,err):
    This tells the CatalogManager where to send error messages from parsing.
    def set_parser_factory(self,parser_fact):
    This gives the CatalogManager an object it can use to create catalog parsers. The parser_fact object must conform to the CatParserFactory interface.
    def parse_catalog(self,sysid):
    Makes the CatalogManager parse the given catalog file and store the information in it internally.
    def report(self,out=sys.stdout):
    Makes the CatalogManager write a badly formatted report of its internal information to the out file object.
    def get_document_sysid(self):
    Returns the contents of the DOCUMENT entry in the catalog file.
    def remap_sysid(self,sysid):
    Returns the system identifier after remapping it according to the SYSTEM entries in the catalog file. (This should only be used for system identifiers occurred alone, without an accompanying public identifier.)
    def resolve_sysid(self,pubid,sysid):
    Returns the correct system identifier for this combination of system and public identifiers. If there was no public identifier the pubid parameter should be None.
    def get_public_ids(self):
    Returns a list of all declared public indentifiers in this catalog and delegates.

    The CatParserFactory interface

    This class is used by the CatalogManager to create catalog parsers for parsing catalog files. It is mainly interesting if you want to control which parser the CatalogManager uses for parsing its catalog files, such as if you want to use your own subclass of CatalogParser instead of the usual class.

    The CatParserFactory has these methods:

    def make_parser(self,sysid):
    This method must return an object conforming to the CatalogParser interface.

    The xmlproc_catalog class

    This class is a client to the CatalogManager that conforms to the PubIdResolver interface, and so can be used to make xmlproc use a catalog file. The xmlproc_catalog class has these methods:

    def __init__(self,sysid,pf,error_handler=None):

    Creates an xmlproc_catalog object, ready to be given to the xmlproc parser with the set_pubid_resolver method. The sysid parameter holds the system identifier of the catalog file to use and the pf parameter holds the CatParserFactory used to create catalog file parsers.

    The error_handler can be a reference to an error handler which can receive notification of errors.

    The SAX_catalog class

    This class is a client to the CatalogManager that conforms to the SAX EntityResolver interface, and so can be used to make a SAX use a catalog file for resolving entity public identifiers. The SAX_catalog class has these methods:

    def __init__(self,sysid,pf):
    Creates an SAX_catalog object, ready to be given to the SAX parser with the setEntityResolver method. The sysid parameter holds the system identifier of the catalog file to use and the pf parameter holds the CatParserFactory used to create catalog file parsers.

    Support for XCatalog 0.1

    Just before xmlproc 0.50 was released John Cowan proposed the XCatalog 0.1 standard for catalog files in XML format. This proposal has an XML DTD which can be used to mark up catalog files instead of the special syntax used by SGML Open Catalogs. The XCatalog DTD only has a subset of the catalog file functionality implemented by xmlproc for SGML Open Catalogs.

    The xmlproc XCatalog implementation is found in the xcatalog module and consists of three classes:

    • XCatalogParser: a CatalogParser that parses XCatalogs instead of SGML Open Catalogs.
    • XCatParserFactory: a CatParserFactory that always creates XCatalogParser objects.
    • FancyParserFactory: a CatParserFactory that creates XCatalogParsers for catalog files with system identifiers ending in ".xml", and CatalogParsers for all other catalog files.

    The support for XCatalog should be considered an experimental feature.


    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc-doco.html0100644000076400001440000002610107107047706017445 0ustar martinusers Documentation: the xmlproc APIs

    Documentation: the xmlproc APIs

    Using the API

    Ordinary XML parsing

    An application that uses the xmlproc API has to import the xmlproc module (non-validating parsing) or the xmlval module (validating parsing). A parser object is created by instantiating an object of the XMLProcessor class (non-validating) or XMLValidator (validating). Both classes have the same interface.

    If you want to receive information about the document being parsed you must implement an object conforming to the Application interface, and tell the parser about it with the set_application method.

    If you want to receive error events and react to them you must implement an object conforming to the ErrorHandler interface, and tell the parser to use your error handler with the set_error_handler method.

    It is also possible to control the way the parser interprets system identifiers, by implementing an object conforming to the InputSourceFactory interface and giving it to the parser with the set_inputsource_factory method.

    Working with DTDs and catalog files

    See the DTD API documentation and the catalog file documentation.

    List of interfaces

    These are the classes of interest to xmlproc application writers:

    The Parser interface

    This is the interface implemented by the two XML parser objects and is used to control parsing.

    def __init__(self):
    Instantiates a parser.
    def set_application(self,app):
    Tells the parser where to send data events.
    def set_error_handler(self,err):
    Tells the parser where to send error events.
    def set_inputsource_factory(self,isf):
    Tells the parser which object to use to map system identifiers to file-like objects.
    def set_pubid_resolver(self,pubres):
    Tells the parser which object to use to map public identifiers to system identifiers.
    def set_dtd_listener(self, dtd_listener):
    Tells the parser where to send DTD parse events. The dtd_listener object must implement the DTDConsumer interface.
    def parse_resource(self,sysID,bufsize=16384):
    Makes the parser parse the XML document with the given system identifier.
    def reset(self):
    Resets the parser to process another file, losing all unparsed data.
    def feed(self,new_data):
    Makes the parser parse a chunk of data.
    def close(self):
    Closes the parser, making it process all remaining data. The effects of calling feed after close and before the first reset are undefined.
    def get_current_sysid(self):
    Returns the system identifier of the current entity being parsed.
    def get_offset(self):
    Returns the current offset (in characters) from the start of the entity.
    def get_line(self):
    Returns the current line number.
    def get_column(self):
    Returns the current column position.
    def get_dtd(self):
    Returns the object holding information about the DTD of the document. This object conforms to the DTD interface. (Note that the DTD object returned by XMLProcessor will have much less information, since the XMLProcessor does not keep as much DTD information.)
    def set_error_language(self,language):
    Tells the parser which language to report errors in. 'language' must be an ISO 3166 language code (case does not matter). A KeyError will be thrown if the language is not supported.
    def set_data_after_wf_error(self,stop_on_error):
    Tells the parser whether to report data events to the application after a well-formedness error (0) or whether to stop reporting data (which is the default, 1).
    def set_read_external_subset(self, read):
    Tells the parser whether to read the external DTD subset of documents (including external parameter entities). Note that XMLValidator will ignore this method and always read the external subset.
    def deref(self):
    The parser creates circular data structures during parsing. When the parser object is no longer to be used and you wish to free the memory it has allocated, call this method. The parser object will be non-functional afterwards.
    def get_elem_stack(self):
    This method returns the list that holds the stack of open elements. Note that this list is live and must not be modified by the application.
    def get_raw_construct(self):
    Returns the raw XML string that triggered the current callback event.
    def get_current_ent_stack(self):
    Returns a snapshot of the current stack of open entities as a list of (entity name, entity sysid) tuples.

    Application

    This is the interface of the objects that data events from the parsed document.

    def set_locator(self,locator):
    Called by the parser to give the application an object to query for the current location. The object conforms to the parser interface.
    def doc_start(self):
    Called at the start of the document, first of all method calls, except set_locator.
    def doc_end(self):
    Called at the end of the document, last of all method calls.
    def handle_comment(self,data):
    Notifies the application of comments. (Note that it is improper for applications to let information in comments affect their operation.)
    def handle_start_tag(self,name,attrs):
    Called by the parser for each start tag. 'name' is the name of the element, 'attrs' a attribute name to attribute value hash.
    def handle_end_tag(self,name):
    Called by the parser for each end tag. 'name' is the name of the element.
    def handle_data(self,data,start,end):
    Called by the parser whenever it encounters textual data. (This callback does not distinguish between character entity references, entity references, CDATA marked sections or plain text.)
    def handle_ignorable_data(self,data,start,end):
    The validating parser calls this method instead of handle_data for whitespace that does not appear in elements which allow mixed content (ie: #PCDATA content).
    def handle_pi(self,target,data):
    Called to notify the application of processing instructions.
    def handle_doctype(self,root,pubID,sysID):
    Called to notify the application of the contents of the DOCTYPE declaration.
    def set_entity_info(self,xmlver,enc,sddecl):
    Called to notify the application of the contents of the XML declaration (and also for text declarations in external parsed entities). The values of the parameters will be None if the PI attributes were not present in the document.

    The ErrorHandler interface

    This interface is used to receive information about errors encountered during the parsing of the document.

    def __init__(self,locator):
    Creates a new error handler, and gives it the locator to use to locate error events.
    def set_locator(self,loc):
    Tells the error handler where to find location information for the error events. The object given in the 'loc' parameter conforms to the Parser interface.
    def get_locator(self):
    Returns the locator of this error handler.
    def warning(self,msg):
    Called to handle a warning message.
    def error(self,msg):
    Called to handle a non-fatal error.
    def fatal(self,msg):
    Called to handle a fatal error.

    The PubIdResolver interface

    This interface is used by the parser to resolve any public identifiers used in the document to their corresponding system identifiers. The default implementation always returns the given system identifier, but the interface has been included mainly to allow support for catalog files.

    def resolve_pe_pubid(self,pubid,sysid):
    Called to resolve the system identifier at which this external parameter entity can be found.
    def resolve_doctype_pubid(self,pubid,sysid):
    Called to resolve the system identifier at which this document type definition can be found. (Called from the DOCTYPE declaration.)
    def resolve_entity_pubid(self,pubid,sysid):
    Called to resolve the system identifier of an external entity.

    The InputSourceFactory interface

    This interface is used to allow users to control the way in which the parser interprets system identifiers. This is especially useful for embedding the parser in a larger document system, which may want to use system identifiers to refer to other documents inside the document system and not just to be ordinary URLs. It is also useful to allow the application to interpret system identifiers that are URIs, but not URLs, such as URNs.

    The default implementation interprets system identifiers as URLs.

    def create_input_source(self,sysid):
    This method returns a file-like object from which the document referred to by the system identifier can be read.

    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc-dtd-doco.html0100644000076400001440000002255407107047706020226 0ustar martinusers Documentation: the xmlproc DTD APIs

    Documentation: the xmlproc DTD APIs

    Working with DTDs

    Accessing DTD information

    The complete DTD information is only available from the validating parser, although both parsers implement a get_dtd method, which can be used to get an object conforming to the DTD interface, containing information about the DTD.

    Parsing a DTD without parsing a document

    This is now supported through the dtdparser module.

    List of interfaces

    These are the interfaces used to discover information about the DTD of the parsed document:

    The DTD interface

    This is the interface of the object that holds information about the DTD of the current document. This object can be queried to discover information about the DTD.

    def get_root_elem(self):
    Returns the name of the element declared as the root element (as a string), or None if none were declared.
    def get_elem(self,name):
    Returns the element object of the element with the given name. Throws a KeyError if no such element has been declared.
    def get_elements(self):
    Returns a list of all declared element names.
    def get_notation(self,name):
    Returns a (pubid, sysid) tuple representing the named notation. If no such notation has been declared a KeyError is thrown.
    def get_notations(self):
    Returns a list of the names of all declared notations.
    def get_general_entities(self):
    Returns a list of all declared general entity names.
    def get_parameter_entities(self):
    Returns a list of all declared parameter entity names.
    def resolve_pe(self,name):
    Returns the entity object (either InternalEntity or ExternalEntity) of the parameter entity with the given name. If no parameter entity with this name has been declared a KeyError is thrown.
    def resolve_ge(self,name):
    Returns the entity object (either InternalEntity or ExternalEntity) of the general entity with the given name. If no general entity with this name has been declared a KeyError is thrown.

    The ElementType interface

    This class encapsulates information about an element type.

    def get_name(self):
    Returns the name of the element type.
    def get_attr_list(self):
    Returns a list of the names of the declared attributes for this element (as strings).
    def get_attr(self,name):
    Returns the attribute object of the given attribute or throws a KeyError if none has been declared.
    def get_start_state(self):
    Returns the start state of the content model of the element. (No guarantees is made as to the type of this value; just think of it as a magic cookie instead.)
    def final_state(self,state):
    Returns true if the given state (as returned by get_start_state or next_state) is a final state, ie: one in which the element is allowed to end.
    def next_state(self,state,elem_name):
    Returns the next state of the element (again in an unspecified type) when the an element with the given name is encountered in the given state. Character data is represented as the element name '#PCDATA'. If the element is not allowed in this state the value 0 will be returned.
    def get_valid_elements(self,state):
    Returns a list of the valid elements in the given state, or the empty list if none are valid (or if the state is unknown).
    def get_content_model(self):
    Returns the element content model in (sep,cont,mod) format, where cont is a list of (name,mod) and (sep,cont,mod) tuples. ANY content models are represented as None, and EMPTYs as ("",[],"").

    The Attribute interface

    This class encapsulates information about an attribute.

    def get_name(self):
    Returns the name of the attribute.
    def get_type(self):
    Returns the declared type of the attribute. (ID, CDATA etc.)
    def get_decl(self):
    Returns the default declaration of the attribute. (#IMPLIED, #REQUIRED, #FIXED or #DEFAULT.)
    def get_default(self):
    Return the default value of the attribute, or None if none has been declared.
    def validate(self,value,err):
    Takes an attribute value ('value') and an ErrorHandler ('err') and validates the attribute value for correctness, reporting errors to 'err'.

    The Entity interface

    This class encapsulates information about entities. It is implemented by two classes: InternalEntity and ExternalEntity. InternalEntity only implements a subset of the interface.

    def is_internal(self):
    True if the entity is internal, false otherwise.
    def is_parsed(self):
    True if the entity is parsed, false otherwise. (Not implemented by InternalEntity.)
    def get_pubid(self):
    Returns the public identifier of the entity. (Not implemented by InternalEntity.)
    def get_sysid(self):
    Returns the system identifier of the entity. (Not implemented by InternalEntity.)
    def get_notation(self):
    Return the name of the notation associated with the entity or None if there is None. (Not implemened by InternalEntity.)

    The DTDConsumer interface

    This interface is used to receive parse events from the DTD parser.

    def set_error_handler(self,err):
    Sets the error handler of the DTDConsumer. The error handler does not have to be used, but the DTDConsumer must accept this method call.
    def dtd_start(self):
    Called before any DTD events arrive. (Note: This will be called once for the internal DTD subset (if any) and once for the external DTD subset (if parsed).)
    def dtd_end(self):
    Called when the DTD is completely parsed. (Note: This will be called once for the internal DTD subset (if any) and once for the external DTD subset (if parsed).)
    def new_general_entity(self,name,val):
    Called when an internal general entity declaration is encountered. 'val' contains the entity replacement text.
    def new_external_entity(self,ent_name,pub_id,sys_id,ndata):
    Called when an external general entity declaration is encountered. 'ndata' is the name of the associated notation, or None if none was associated.
    def new_parameter_entity(self,name,val):
    Called when an internal parameter entity declaration is encountered. 'val' contains the entity replacement text.
    def new_external_pe(self,name,pubid,sysid):
    Called when an external parameter entity declaration is encountered.
    def new_notation(self,name,pubid,sysid):
    Called when a notation declaration is encountered.
    def new_element_type(self,elem_name,elem_cont):
    Called when an element type declaration is encountered. 'elem_cont' is a tuple, as returned by the get_content_model method of the ElementType interface.
    def new_attribute(self,elem,attr,a_type,a_decl,a_def):
    Called when an attribute declaration is encountered. 'elem' is the name of the element, 'attr' the name of the attribute, 'a_type' the name of the attribute type (ID, CDATA...), 'a_decl' the name of the declared default type (#REQUIRED, #IMPLIED...) and 'a_def' the declared default value (or None if none were declared).
    def handle_comment(self,contents):
    Called when a comment is encountered inside the DTD.
    def handle_pi(self,target,data):
    Called when a processing instruction is encountered inside the DTD.

    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc-license.html0100644000076400001440000000275407107047706020153 0ustar martinusers The xmlproc license

    The xmlproc license

    Copyright 1998-2000 by Lars Marius Garshol, Oslo, Norway.

    All Rights Reserved

    Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that modified copies are clearly marked as such.

    LARS MARIUS GARSHOL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL LARS MARIUS GARSHOL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc.html0100644000076400001440000001174707452522426016535 0ustar martinusers xmlproc: An XML parser in Python

    xmlproc: An XML parser in Python

    Version: 0.70
    Author: Lars Marius Garshol - larsga@garshol.priv.no.
    Last release: 2025-05-11

    What is xmlproc?

    xmlproc is an XML parser written in Python. It is a nearly complete validating parser, with only minor deviations from the specification (listed below). It supports both SGML Open Catalogs and XCatalog 0.1, as well as error messages in different languages. xmlproc also supports namespaces. Access to DTD information is provided, as is a separate DTD parser. SAX drivers are provided with the parser.

    Additional utilities are command-line tools for validating and non-validating parsing as well as DTD parsing and also a GUI tool for parsing documents. A DTD to XML Schema converter is also included.

    Licence?

    xmlproc is free and you can do as you like with it. If you change it, please let me know. A formal BSD-ish license is available.

    Documentation

    At the moment the following topics are documented:

    Note that it is recommended to use xmlproc through the SAX API rather than directly, since this provides much greater freedom in the choice of parsers. (For example, you can switch to using Pyexpat which is written in C without changing your code.)

    Getting xmlproc

    You can download xmlproc here.

    Feedback

    Any and all feedback is welcome, from suggestions for improvements or new features to bug reports. And I really mean it! If you have some opinions on this program, please let me hear them.

    Deviations from the XML specification

    xmlproc does not follow the XML specification in these respects:

    • External parameter entities are not allowed inside markup declarations.
    • No attempt is made to deal with different character sets or encodings.
    • The parser does not check for the illegal characters.
    • The parser allows some syntactic constructs to cross entity boundaries in ways that are not allowed.

    All other deviations from the specification are unintentional bugs and should be reported to me via email. Hopefully, xmlproc will be 100% compliant in version 1.00.

    xmlproc users

    This is a list of other software projects that use xmlproc in some manner. If you know of one that isn't listed, please let me know.

    • TTX.
    • My.Netscape.Com.
    • Robofog.

    Release notification

    If you want to be notified when a new version appears you can fill in your name and email address in this form and submit it. I guarantee that I won't ever give away the email addresses on this list and that if this service dies you'll receive notification.

    Your full name:
    Your email address:

    As an alternative, an XSA document is provided here.


    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc_cmdline.html0100644000076400001440000000577307107047706020232 0ustar martinusers Using xmlproc from the command-line

    Using xmlproc from the command-line

    The command-line parser is in xpcmd.py for well-formedness parsing and xvcmd.py for validating parsing.

    xpcmd.py

    xpcmd.py is a command-line interface to the parser. It continues parsing after even fatal errors, in order to be find more errors, since this does not mean feeding data to the application after a fatal error (which would be in violation of the spec).

    Usage:
      xpcmd.py [options] [urltodoc]
      ---Options:  
      -l language: ISO 3166 language code for language to use in error messages
      -o format:   Format to output parsed XML. 'e': ESIS, 'x': canonical XML
                   and 'n': normalized XML. No data will be output if this
                   option is not specified.
      urltodoc:    URL to the document to parse. (You can use plain file names
                   as well.) Can be omitted if a catalog is specified and contains
                   a DOCUMENT entry.
      -n:          Report qualified names as 'URI name'. (Namespace processing.)
      --nowarn:    Don't write warnings to console.
      --entstck:   Show entity stack on errors.
      --extsub:    Read the external subset of documents.
    

    xvcmd.py

    xvcmd.py validates and has more options:

    Usage:
      xvcmd.py [options] [urlstodocs]
      ---Options:  
      -c catalog:   path to catalog file to use to resolve public identifiers
      -l language:  ISO 3166 language code for language to use in error messages
      -o format:    Format to output parsed XML. 'e': ESIS, 'x': canonical XML
                    and 'n': normalized XML. No data will be output if this
                    option is not specified.
      urlstodocs:   URLs to the documents to parse. (You can use plain file names
                    as well.) Can be omitted if a catalog is specified and contains
                    a DOCUMENT entry.
      -n:           Report qualified names as 'URI name'. (Namespace processing.)
      --nowarn:     Suppress warnings.
      --entstck:    Show entity stack on errors.
      --rawxml:     Show raw XML string where error occurred.
      Catalog files with URLs that end in '.xml' are assumed to be XCatalogs,
      all others are assumed to be SGML Open Catalogs.
      If the -c option is not specified the environment variables XMLXCATALOG
      and XMLSOCATALOG will be used (in that order).
    

    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc_dtdparser.html0100644000076400001440000000706707107047706020605 0ustar martinusers Documentation: the xmlproc DTDParser APIs

    Documentation: the xmlproc DTDParser APIs

    The DTD parser is the module xmlproc uses to read XML DTDs. It has been separated out as a separate module in order to make it possible to use it for other things than merely parsing and validating XML documents.

    Applications that wish to use the DTD parser should implement the DTDConsumer interface and use it to receive parse events.

    The DTDParser interface

    The DTDParser is in the xml.parsers.xmlproc.dtdparser module and implements the following interface:

    def __init__(self):
    Instantiates a DTD parser.
    def set_dtd_consumer(self,consumer):
    Tells the DTD parser where to send DTD parse events. The consumer object must implement the DTDConsumer interface.
    def set_error_handler(self,err):
    Tells the parser where to send error events.
    def set_internal(self,yesno):
    Tells the parser whether to consider this an internal (1) or external (0) DTD subset. The default is to consider it an external subset.
    def set_inputsource_factory(self,isf):
    Tells the parser which object to use to map system identifiers to file-like objects.
    def parse_resource(self,sysID,bufsize=16384):
    Makes the parser parse the XML document with the given system identifier.
    def reset(self):
    Resets the parser to process another file, losing all unparsed data.
    def feed(self,new_data):
    Makes the parser parse a chunk of data.
    def close(self):
    Closes the parser, making it process all remaining data. The effects of calling feed after close and before the first reset are undefined.
    def get_current_sysid(self):
    Returns the system identifier of the current entity being parsed.
    def get_offset(self):
    Returns the current offset (in characters) from the start of the entity.
    def get_line(self):
    Returns the current line number.
    def get_column(self):
    Returns the current column position.
    def set_error_language(self,language):
    Tells the parser which language to report errors in. 'language' must be an ISO 3166 language code (case does not matter). A KeyError will be thrown if the language is not supported.
    def deref(self):
    The parser creates circular data structures during parsing. When the parser object is no longer to be used and you wish to free the memory it has allocated, call this method. The parser object will be non-functional afterwards.

    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc_ns.html0100644000076400001440000000507007107047706017225 0ustar martinusers xmlproc and namespaces

    xmlproc and namespaces

    xmlproc now supports XML namespaces through the addition of the xml.parsers.xmlproc.namespace module. In this module there is a NamespaceFilter class which is implemented as a parser filter. This means that it is registered with the parser as an application, and that your application then registers with the filter as the real application.

    The parser will then parse as normal and send parse events to the NamespaceFilter, which will do namespace transformations and pass the events on to your application.

    An example

    This is an example of how namespace processing can be set up:

    
    from xml.parsers.xmlproc import xmlproc,namespace
    class MyApplication(xmlproc.Application):
        pass # Add some useful stuff here
    p=xmlproc.XMLProcessor()
    nsf=namespace.NamespaceFilter(p)
    nsf.set_application(MyApplication())
    # register error handlers and all other handlers with the parser,
    # not the filter
    p.set_application(nsf)
    p.parse_resource("foo.xml")
    

    MyApplication will now receive parse events where all prefixed names have been processed into names consisting of the namespace URI, followed by a space and then the local part of the name. If this isn't clear to you, try using the -n option to xvcmd.py and xpcmd.py and -o x to see what the filter does.

    The NamespaceFilter interface

    This is the complete NamespaceFilter interface:

    def __init__(self,parser):
    Creates the filter and gives it a reference to the parser.
    def set_application(self,app):
    Gives the filter an object to send filtered events to.
    def set_report_ns_attributes(self,action):
    If action is set to true xmlns attributes are reported to the application. If it is set to false they are silently removed.

    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xmlproc/xmlproc_tut.html0100644000076400001440000001343207107047706017422 0ustar martinusers An overview of xmlproc

    An overview of xmlproc

    xmlproc has been designed in a highly modular fashion, with the intention that it should be possible to reuse the modules in different contexts and applications. Emphasis has been placed on flexibility, leading to a rather large and perhaps bewildering interface. This document attempts to explain the different pieces and how they fit together.

    The command-line parsers

    xmlproc ships with two command-line parser applications for XML parsing. They are not useful for incorporating xmlproc in your own applications, but can be used to check that xmlproc is working, to verify documents and also to see how the parser interprets documents, by making them output canonical XML or ESIS.

    The diagram below shows how these applications use the xmlproc APIs.

    As the diagram shows one application (xpcmd.py) uses the object called XMLProcessor. This is the well-formedness parser that does not read the external DTD and which does not validate. The second application (xvcmd.py) uses an object called XMLValidator, which again uses the well-formedness parser XMLProcessor for basic parsing, but provides full validation on top of this.

    The command-line interfaces are documented here.

    The DTD parser

    The xmlproc distribution also includes a command-line application dtdcmd.py, which only uses the DTD parsing APIs of xmlproc and can parse DTD files directly. The command-line interface is as follows:

      python dtdcmd.py [--list] +
    

    Here --list makes the parser list all declarations after parsing a DTD, and urltodtd is a list of one or more DTD file names or URLs.

    The DTD to XML Schema converter

    The command-line application dtd2schema.py converts DTDs into equivalent XML Schema documents. The application takes one mandatory argument (the system identifier of the DTD) and one optional argument (the file name of the output document). If no output file name is specified, one is inferred from the input file name.

    The converter tries to do some naive inference of attribute groups and will produce output with attribute groups inferred from the DTD structure.

    The parsing API

    If you want to use xmlproc in an application of your own what you do is basically what I did with xpcmd.py and xvcmd.py: you use the xmlproc modulse in an application to provide it with XML parsing functionality. On top of that you must build whatever you want to use xmlproc for yourself. (In the case of xvcmd.py and xpcmd.py this is simply outputting parse results to the console and interpreting command-line options.

    The diagram below shows the main objects involved in this API:

    The central object is the Parser object, which can be either an XMLProcessor or an XMLValidator (they have the same interface, but only the latter validates and the former is faster). When it is created the Parser creates the four objects shown in the diagram. It also provides methods that can be used to make it use objects that you provide instead of these objects. (See the documentation for details.)

    The roles of these four objects are:

    Application
    This object receives all data events from the parsing of the document such as handle_start_tag, handle_end_tag, handle_data and so on.
    ErrorHandler
    This object receives all error events.
    PubIdResolver
    Whenever an entity reference is encountered, this object will be given the public identifier and system identifier (file name/URL) of the entity and asked to supply the system identifier to be used.
    InputSourceFactory
    Once the PubIdResolver has returned the correct file name/URL for the entity, the InputSourceFactory will be asked to create a file-like object from which the entity contents can be read.

    So, to act on the document content, make an Application object and tell the parser to use it. To control error reporting, make an ErrorHandler. To control the resolution of public identifiers (and also to remap system identifiers), make a PubIdResolver. To add support for new kinds of URLs or to provide your own support for a class of URLs, make an InputSourceFactory.

    Example

    
    from xml.parsers.xmlproc import xmlproc
    class MyApplication(xmlproc.Application):
        pass # Add some useful stuff here
    p=xmlproc.XMLProcessor()  # Make this xmlval.XMLValidator if you want to validate
    p.set_application(MyApplication())
    p.parse_resource("foo.xml")
    

    The GUI parser frontend

    xmlproc includes a GUI application that can be used to parse XML documents in the wxValidator.py application. This application uses wxPython to create a more user-friendly interface, as shown below:


    Last update 2025-05-11 14:20, by Lars Marius Garshol.
    PyXML-0.8.2/doc/xml-howto.tex0100644000076400001440000016534707550506744015171 0ustar martinusers\documentclass{howto} % $Id: xml-howto.tex,v 1.23 2025/09/30 21:49:07 akuchling Exp $ % TODO: % XXX not covered: DOM extensions, scripts \newcommand{\element}[1]{\code{#1}} \newcommand{\attribute}[1]{\code{#1}} \title{Python/XML HOWTO} \release{0.7.1} \author{A.M. Kuchling} \authoraddress{\email{akuchlin@mems-exchange.org}} \begin{document} \maketitle \begin{abstract} \noindent XML is the eXtensible Markup Language, a subset of SGML intended to allow the creation and processing of application-specific markup languages. Python makes an excellent language for processing XML data. This document is a tutorial for the Python/XML package. It assumes you're already somewhat familiar with the structure and terminology of XML, though a brief introduction is supplied. \end{abstract} \tableofcontents %========================================================================== \section{Introduction to XML\label{section-introduction}} XML, the eXtensible Markup Language, is a simplified dialect of SGML, the Standardized General Markup Language. XML is intended to be reasonably simple to implement and use, and is already being used for specifying markup languages for various new standards: MathML for expressing mathematical equations, Synchronized Multimedia Integration Language for multimedia presentations, and so forth. SGML and XML represent a document by tagging the document's various components with their function or meaning. For example, a book contains several parts: it has a title, one or more authors, the text of the book, perhaps a preface or an index, and so forth. A markup languge for writing books would therefore have elements indicating what the contents of the preface are, what the title is, and so forth. This logical structure should not be confused with the physical details of how the document is actually printed on paper. The index might be printed with narrow margins in a smaller font than the rest of the book, but markup usually isn't (or shouldn't be, anyway) concerned with details such as this. Instead, other software will translate from the markup language to a typeset format, handling the presentation details. This section will provide a brief overview of XML and a few related standards, but it's far from being complete because making it complete would require a full-length book and not a short HOWTO. There's no better way to get a completely accurate (if rather dry) description than to read the original W3C Recommendations; you can find links to them below. If you already know what XML is, you can skip the rest of this section. Later sections of this HOWTO assume that you're familiar with XML terminology. Most sections will use XML terms such as \emph{element} and \emph{attribute}. Section~\ref{SAX} does not require that you have experience with any of the various Java SAX implentations. \begin{seealso} \seetitle[http://www.w3.org/TR/REC-xml] {Extensible Markup Language (XML) 1.0 (Second Edition)} {For the full details of XML's syntax, the definitive source is the XML 1.0 specification. However, like all specifications it's quite formal and isn't intended to be a friendly introduction or a tutorial. An annotated version of the standard, is also available, and there are many more informal tutorials and books available to introduce you to XML at greater (or lesser) length.} \seetitle[http://www.xml.com/xml/pub/a/axml/axmlintro.html] {The Annotated XML Specification} {This annotated version of the XML specification, produced by Tim Bray, is quite helpful in clarifying the specification's intent. It is presented as a richly-hyperlinked document that makes navigation easy, and evokes a sense of what hypertext was meant to be.} \seetitle[http://xml.coverpages.org/]{The XML Cover Pages} {An extensive collection of links to XML and SGML resources, including a news page that's updated every few days. If you can only remember one XML-related URL, remember this one. \citetitle[http://www.ibiblio.org/xml/]{Cafe con Leche} is another good resource.} \seetitle[http://www.xml.org/xml/xmldev.shtml] {xml-dev mailing list} {This is a high-traffic list for implementation and development of XML standards. Be warned: Some people might find the discussion too focused on vague theorizing about information representation, and not on inventing new standards and tools or applying existing standards.} \end{seealso} \subsection{Elements, Attributes and Entities} A markup language specified using XML looks a lot like HTML; a document consists of a single \dfn{element}, which contains sub-elements, which can have further sub-elements inside them. Elements are indicated by \dfn{tags} in the text. Tags are always inside angle brackets \code{<}~\code{>}. Elements can either contain content, or they can be empty. An element can contain content between opening and closing tags, as in \code{Euryale}, which is a \element{name} element containing the data \samp{Euryale}. This content may be text data, other XML elements, or a mixture of both. Elements can also be empty, containing nothing, and are represented as a single tag ended with a slash. For example, \code{} is an empty \element{stop} element. Unlike HTML, XML element names are case-sensitive; \element{stop} and \element{Stop} are two different elements. Opening and empty tags can also contain attributes, which specify values associated with an element. For example, in the XML text \code{Herakles}, the \element{name} element has a \attribute{lang} attribute which has a value of \samp{greek}. In \code{Hercules}, the attribute's value is \samp{latin}. XML also includes \dfn{entities} as a shorthand for including a particular character or a longer string. Entity references always begin with a \samp{\&} and end with a \samp{;}. For example, a particular Unicode character can be written as \code{\&\#4660;} using its character code in decimal, or as \code{\&\#x1234;} using hexadecimal. It's also possible to define your own entities, making \code{\&title;} expand to ``The Odyssey'', for example. If you want to include the \samp{\&} character in XML content, it must be written as \code{\&}. \subsection{Well-Formed XML} A legal XML document must, as a minimum, be \dfn{well-formed}: each opening tag must have a corresponding closing tag, and tags must nest properly. For example, \code{text} is not well-formed because the \element{i} element should be enclosed inside the \element{b} element, but instead the closing \code{} tag is encountered first. This example can be made well-formed by swapping the order of the closing tags, resulting in \code{text}. If you've ever written HTML by hand, you may have acquired the habit of being a bit sloppy about this. Strictly speaking HTML has exactly the same rules about nesting tags as XML, but most Web browsers are very forgiving of errors in HTML. This is convenient for HTML authors, but it makes it difficult to write programs to parse HTML input because the programs have to cope with all sorts of malformed input. The authors of the XML specification didn't want XML to fall into the same trap, because it would make XML processing software much harder to write. Therefore, all XML parsers have to be strict and must report an error if their input isn't well-formed. The Expat parser includes an executable program named \program{xmlwf} that parses the contents of files and reports any well-formedness violations; it's very handy for checking XML data that's been output from a program or written by hand. \subsection{DTDs} Well-formedness just says that all tags nest properly and that every opening tag is matched by a closing tag. It says nothing about the order of elements or about which elements can be contained inside other elements. The following XML, apparently representing a book, is well-formed but it doesn't match the structure expected for a book: \begin{verbatim} ... ... ... ... ... ... \end{verbatim} Prefaces don't come at the end of books, the index doesn't belong at the front, and the abstract doesn't belong in the middle. Well-formedness alone doesn't provide any way of enforcing that order. You could write a Python program that took an XML file like this and checked whether all the parts are in order, but then someone wanting to understand what documents are legal would have to read your program. Document Type Definitions, or \dfn{DTDs} for short, are a more concise way of enforcing ordering and nesting rules. A DTD declares the element names that are allowed, and how elements can be nested inside each other. To take an example from HTML, the \element{LI} element, representing an entry in a list, can only occur inside certain elements which represent lists, such as \element{OL} or \element{UL}. The DTD also specifies the attributes that can be provided for each element, the default value for each attribute, and whether the attribute can be omitted. A \dfn{validating parser} can take a document and a DTD, and check whether the document is legal according to the DTD's rules. (The PyXML package includes a validating parser called xmlproc.) DTDs are therefore an example of a \dfn{schema language}, a language for specifying a set of legal XML documents. Other applications want even stricter control over which documents are legal, and there are therefore stricter schema languages. XML Schema provides a type system and a number of basic types, so you can say that the value of an attribute must be a number or a date. RELAX NG is another schema language that provides more power and flexibility than XML Schema, but is simpler to read and implement. Note that it's quite possible to get useful work done without using any schema language at all. You might decide that just writing well-formed XML and checking it with a Python program is all you need. There's no reason to drag in a schema language if it won't be useful. Let's return to DTDs. A DTD lists the supported elements, the order in which elements must occur, and the possible attributes for each element. Here's a fragment from an imaginary DTD for writing books: \begin{verbatim} \end{verbatim} The first line declares the \element{book} element, and specifies the elements that can occur inside it and the order in which the subelements must be provided. DTDs borrow from regular expression notation in order to express how elements can be repeated; \samp{?} means an element must occur 0 or 1 times, \samp{*} is 0 or more times, and \samp{+} means the element must occur 1 or more times. For example, the above declarations imply that the \element{abstract} and \element{appendix} elements are optional inside a \element{book} element. Exactly one \element{preface} element has to be present, and it can be followed by any number of \element{chapter} elements; having no chapters at all would be legal. The \code{ATTLIST} declaration specifies attributes for the \element{chapter} element. Chapters can have two attributes, \attribute{id} and \attribute{title}. \attribute{title} contains character data (CDATA) and is optional (that's what \samp{\#IMPLIED} means, for obscure historical reasons). \attribute{id} must contain an ID value, and it's required and not optional. A validating parser could take this DTD and a sample document, and report whether the document is \dfn{valid} according to the rules of the DTD. A document is valid if all the elements occur in the right order, and in the right number of repetitions. %========================================================================== \section{XML-Related Standards\label{section-standards}} XML 1.0 is the basic standard, but people have built many, \emph{many} additional standards and tools on top of XML or to be used with XML. This section will quickly introduce some of these related technologies, paying particular attention to those that are supported by the Python/XML package. \begin{definitions} \term{SAX} The Simple API for XML isn't a standard in the formal sense that XML or ANSI C are. Rather, SAX is an informal specification originally designed by David Megginson with input from many people on the xml-dev mailing list. SAX defines an event-driven interface for parsing XML. To use SAX, you must create Python class instances which implement a specified interface, and the parser will then call various methods on those objects. See section~\ref{section-SAX}. \term{DOM} The Document Object Model specifies a tree-based representation for an XML document, as opposed to the event-driven processing provided by SAX. See section~\ref{section-DOM}. \term{Namespaces} One XML document can refer to elements from more than one DTD. (Such documents can no longer be validated using DTDs, though other schema languages such as RELAX NG can handle namespaces.) For example, a document might contain both some text and a diagram. The text might be represented using some elements from the HTML DTD, and the diagram might use elements from the Scalable Vector Graphics DTD. All the relevant modules in the PyXML module can be used for namespace-aware processing. \term{XPath and XPointer} XPath is a language for referring to parts of an XML document. With XPath you can refer to paragraph number N, or ``all paragraphs of class \samp{warning}'', or all chapters that have one or more subsections. XPointer defines a way to use XPath declarations as the fragment identifier in a URL to point at a part of an XML document. See section~\ref{section-XPath}. \term{XSLT} XSLT is a general tool for transforming one XML document into another document, specifying the transformation using another XML document called a \dfn{stylesheet}. \begin{comment} See section~\ref{section-XSLT}. \end{comment} \term{RDF} The Resource Description Format is for describing metadata about other resources. The PyXML package doesn't contain any support for RDF, but a Python library called Redfoot (\url{http://redfoot.sf.net}) is available. \end{definitions} %========================================================================== \section{Installing the XML Toolkit\label{section-install}} Releases are available from \url{http://sourceforge.net/projects/pyxml/}. Windows users should download the appropriate precompiled version. Linux users can either download an RPM, or install from source. Users on other platfoms have no choice but to install from source. To compile from source on a \UNIX{} platform, simply perform the following steps. \begin{enumerate} \item Download the latest version of the source distribution from \url{http://sourceforge.net/projects/pyxml}. Unpack it with the following command. \begin{verbatim} gzip -dc xml-package.tgz | tar -xvf - \end{verbatim} \item Run \code{python setup.py install}. In order to run this, you'll need to have a C compiler installed, and it should be the same one that was used to build your Python installation. On a Unix system, this operation may require superuser permissions. \code{setup.py} supports a number of different commands and options; invoke \code{setup.py} without any arguments to see a help message. \end{enumerate} If you have difficulty installing this software, send a problem report to the XML-SIG mailing list describing the problem, or submit a bug report at \url{http://sourceforget.net/projects/pyxml}. One possible problem that some people encounter is a general issue of managing a Python installation with 3rd-party compiled extensions: If, when importing any of the C extensions provided with PyXML, you get an error message saying \samp{undefined symbol: PyUnicodeUCS2_}\ldots, then you are using a version of Python built using a 4-byte representation for Unicode characters, and PyXML was built with a Python that used a 2-byte Unicode character. Conversely, if the error message give a symbol name starting with \code{PyUnicodeUCS4_} (note the different digit near the end), the extension was built using a 4-byte Unicode character, and Python was built using a 2-byte Unicode character. The Python interpreter and all extension code need to be built using the same size Unicode character representation. There are various demonstration programs in the \file{demo/} directory of the Python/XML source distribution. You may wish to look at them to get an idea of what's possible with the XML tools, and as a source of example code. \begin{seealso} \seetitle[http://pyxml.sourceforge.net/topics/]{Python/XML Topic Guide} {This Guide is the starting point for Python-related XML topics, and includes links to software, mailing lists, documentation, and other useful resources.} \end{seealso} %========================================================================== \section{Package Overview} The PyXML package contains over 200 individual modules, some intended for public use and some not. Many of these modules often perform similar tasks, making it difficult to figure out which is the right one to use in any given situation, and this can make it confusing. Here's a list of the 30-odd packages and modules that are considered public, along with brief descriptions to help you choose the right one. \begin{itemize} \item[\module{xml.dom}] The Python DOM interface. The full interface support DOM Levels 1 and 2. \module{xml.dom} contains the implementation for DOM trees built from XML documents. (This implementation is called 4DOM, and was written by Fourthought Inc.) \item[\module{xml.dom.html}] DOM trees built from HTML documents are also supported. \item[\module{xml.dom.javadom}] An adaptor for using Java DOM implementations with Jython. \item[\module{xml.dom.minidom}] A lightweight DOM implementation that's also included in the Python standard library. \item[\module{xml.dom.minitraversal}] Offers traversal and ranges on top of \module{xml.dom.minidom}, using the 4DOM traversal implementation. \item[\module{xml.dom.pulldom}] Provides a stream of DOM elements. This module can make it easy to write certain types of DTD-specific processing code. \item[\module{xml.dom.xmlbuilder}] General support for the experimental \citetitle[http://www.w3.org/TR/DOM-Level-3-LS]{Document Object Model (DOM) Level 3 Load and Save Specification}. This currently only supports the \module{xml.dom.minidom} DOM implementation. \item[\module{xml.dom.ext}] Various DOM-related extensions for pretty-printing DOM trees as XML or XHTML. \item[\module{xml.dom.ext.Dom2Sax}] A parser to generate SAX events from a DOM tree. \item[\module{xml.dom.ext.c14n}] Takes a DOM tree and outputs a text stream containing the Canonical XML representation of the document. \item[\module{xml.dom.ext.reader}] Classes for building DOM trees from various input sources: SAX1 and SAX2 parsers, \module{htmllib}, and directly using Expat. \item[\module{xml.marshal.generic}] Marshals simple Python data types into an XML format. The \class{Marshaller} and \class{Unmarshaller} classes can be subclassed in order to implement marshalling into a different XML DTD. \item[\module{xml.marshal.wddx}] Marshals Python objects into WDDX. (This module is built on top of the preceding generic module.) \item[\module{xml.ns}] Contains constants for the namespace URIs for various XML-related standards. \item[\module{xml.parsers.sgmllib}] A version of the \module{sgmllib} module that's part of the standard Python library, rewritten to run on top of the \module{sgmlop} accelerator module. \item[\module{xml.parsers.xmlproc}] A validating XML parser. Usually you'll want to use xmlproc via SAX or some other higher-level interface. \item[\module{xml.sax}] SAX1 and SAX2 support for Python. \item[\module{xml.sax.drivers}] SAX1 drivers for various parsers: \module{htmllib}, LT, Expat, \module{sgmllib}, \module{xmllib}, xmlproc, and XML-Toolkit. \item[\module{xml.sax.drivers2}] SAX2 drivers for various parsers: \module{htmllib}, Java SAX parsers (for Jython), Expat, \module{sgmllib}, xmlproc. \item[\module{xml.sax.handler}] Contains the core SAX2 handler classes \class{ContentHandler}, \class{DTDHandler}, \class{EntityResolver}, and \class{ErrorHandler}. Also contains symbolic names for the various SAX2 features and properties. \item[\module{xml.sax.sax2exts}] SAX2 extensions. This contains various factory classes that create parser objects, and is how SAX2 parsers are used. \item[\module{xml.sax.saxlib}] Contains two SAX2 handler classes, \class{DeclHandler} and \class{LexicalHandler}, and the \class{XMLFilter} interface. Also contains the deprecated SAX1 handler classes. \item[\module{xml.sax.saxutils}] Various utility classes, such as \class{DefaultHandler}, a default base class for SAX2 handlers, \class{ErrorPrinter} and \class{ErrorRaiser}, two default error handlers, and \class{XMLGenerator}, which generates XML output from a SAX2 event stream. \item[\module{xml.sax.xmlreader}] Contains the \class{XMLReader}, the base interface for implementing SAX2 parsers. \item[\module{xml.schema.trex}] A Python implementation of TREX, a schema language. \item[\module{xml.utils.characters}] Contains the legal XML character ranges as specified in the XML 1.0 Recommendation, and regular expressions that match various XML tokens. \item[\module{xml.utils.iso8601}] Parses ISO-8601 date/time specifiers, which look like \samp{2002-05-09T20:40Z}. \item[\module{xml.utils.qp_xml}] A simple tree-based XML parsing interface. \item[\module{xml.xpath}] An XPath parser and evaluator. (This implementation is called 4XPath, and was written by Fourthought Inc.) \begin{comment} \item[\module{xml.xslt}] An implementation of the XSLT transformation language. (This implementation is called 4XSLT, and was written by Fourthought Inc.) \end{comment} \end{itemize} %========================================================================== \section{SAX: The Simple API for XML\label{section-SAX}} This HOWTO describes version 2 of SAX (also referred to as SAX2). Support is still present for SAX version 1, which is now only of historical interest; SAX1 will not be documented here. SAX is most suitable for purposes where you want to read through an entire XML document from beginning to end, and perform some computation such as building a data structure or summarizing the contained information (computing an average value of a certain element, for example). SAX is not very convenient if you want to modify the document structure by changing how elements are nested, though it would be straightforward to write a SAX program that simply changed element contents or attributes. For example, you wouldn't want to re-order chapters in a book using SAX, but you might want to extract the contents of all \element{name} elements with the attribute \attribute{lang} set to 'greek'. One advantage of SAX is speed and simplicity. Let's say you've defined a complicated DTD for listing comic books, and you wish to scan through your collection and list everything written by Neil Gaiman. For this specialized task, there's no need to expend effort examining elements for artists and editors and colourists, because they're irrelevant to the search. You can therefore write a class instance which ignores all elements that aren't \element{writer}. Another advantage of SAX is that you don't have the whole document resident in memory at any one time, which matters if you are processing really huge documents. SAX defines 4 basic interfaces. A SAX-compliant XML parser can be passed any objects that support these interfaces, and will call various methods as data is processed. Your task, therefore, is to implement those interfaces that are relevant to your application. The SAX interfaces are: \begin{tableii}{l|p{4in}}{class}{Interface}{Purpose} \lineii{ContentHandler}{Called for general document events. This interface is the heart of SAX; its methods are called for the start of the document, the start and end of elements, and for the characters of data contained inside elements. } \lineii{DTDHandler}{Called to handle DTD events required for basic parsing. This means notation declarations (XML spec section 4.7) and unparsed entity declarations (XML spec section 4). } \lineii{EntityResolver}{Called to resolve references to external entities. If your documents will have no external entity references, you don't need to implement this interface.} \lineii{ErrorHandler}{Called for error handling. The parser will call methods from this interface to report all warnings and errors.} \end{tableii} Python doesn't support the concept of interfaces, so the interfaces listed above are implemented as Python classes. The default method implementations are defined to do nothing---the method body is just a Python \code{pass} statement---so usually you can simply ignore methods that aren't relevant to your application. Pseudo-code for using SAX looks something like this: \begin{verbatim} # Define your specialized handler classes from xml.sax import ContentHandler, ... class docHandler(ContentHandler): ... # Create an instance of the handler classes dh = docHandler() # Create an XML parser parser = ... # Tell the parser to use your handler instance parser.setContentHandler(dh) # Parse the file; your handler's methods will get called parser.parse(sys.stdin) \end{verbatim} \begin{seealso} \seetitle[http://www.saxproject.org/]{The SAX Home Page} {This website has the most recent copy of the specification, and lists SAX implementations for various languages and platforms. Much of the information is somewhat Java-centric, though.} \end{seealso} \subsection{Starting Out} Let's follow the earlier example of a comic book collection, using a simple DTD-less format. Here's a sample document for a collection consisting of a single issue: \begin{verbatim} Neil Gaiman Glyn Dillon Charles Vess \end{verbatim} An XML document must have a single root element; this is the \samp{collection} element. It has one child \element{comic} element for each issue; the book's title and number are given as attributes of the \element{comic} element. The \element{comic} element can in turn contain several other elements such as \element{writer} and \element{penciller} listing the writer and artists responsible for the issue. There may be several artists or writers for a single issue. Let's start off with something simple: a document handler named \class{FindIssue} that reports whether a given issue is in the collection. \begin{verbatim} from xml.sax import saxutils class FindIssue(saxutils.DefaultHandler): def __init__(self, title, number): self.search_title, self.search_number = title, number \end{verbatim} The \class{DefaultHandler} class inherits from all four interfaces: \class{ContentHandler}, \class{DTDHandler}, \class{EntityResolver}, and \class{ErrorHandler}. This is what you should use if you want to just write a single class that wraps up all the logic for your parsing. You could also subclass each interface individually and implement separate classes for each purpose. Neither of the two approaches is always ``better'' than the other; mostly it's a matter of taste. Since this class is doing a search, an instance needs to know what it's searching for. The desired title and issue number are passed to the \class{FindIssue} constructor, and stored as part of the instance. Now let's override some of the parsing methods. This simple search only requires looking at the attributes of a given element, so only the \method{startElement} method is relevant. \begin{verbatim} def startElement(self, name, attrs): # If it's not a comic element, ignore it if name != 'comic': return # Look for the title and number attributes (see text) title = attrs.get('title', None) number = attrs.get('number', None) if (title == self.search_title and number == self.search_number): print title, '#' + str(number), 'found' \end{verbatim} The \method{startElement()} method is passed a string giving the name of the element, and an instance containing the element's attributes. Attributes are accessed using methods from the \class{AttributeList} interface, which includes most of the semantics of Python dictionaries. To summarize, the \method{startElement()} method looks for \element{comic} elements and compares the specified \attribute{title} and \attribute{number} attributes to the search values. If they match, a message is printed out. \method{startElement()} is called for every single element in the document. If you added \code{print 'Starting element:', name} to the top of \method{startElement()}, you would get the following output. \begin{verbatim} Starting element: collection Starting element: comic Starting element: writer Starting element: penciller Starting element: penciller \end{verbatim} To actually use the class, we need top-level code that creates instances of a parser and of \class{FindIssue}, associates the parser and the handler, and then calls a parser method to process the input. \begin{verbatim} from xml.sax import make_parser from xml.sax.handler import feature_namespaces if __name__ == '__main__': # Create a parser parser = make_parser() # Tell the parser we are not interested in XML namespaces parser.setFeature(feature_namespaces, 0) # Create the handler dh = FindIssue('Sandman', '62') # Tell the parser to use our handler parser.setContentHandler(dh) # Parse the input parser.parse(file) \end{verbatim} The \function{make_parser} class can automate the job of creating parsers. There are already several XML parsers available to Python, and more might be added in future. \file{xmllib.py} is included as part of the Python standard library, so it's always available, but it's also not particularly fast. A faster version of \file{xmllib.py} is included in \module{xml.parsers}. The \module{xml.parsers.expat} module is faster still, so it's obviously a preferred choice if it's available. \function{make_parser} determines which parsers are available and chooses the fastest one, so you don't have to know what the different parsers are, or how they differ. (You can also tell \function{make_parser} to try a list of parsers, if you want to use a specific one). Once you've created a parser instance, calling the \method{setContentHandler()} method tells the parser what to use as the content handler. There are similar methods for setting the other handlers: \method{setDTDHandler()}, \method{setEntityResolver()}, and \method{setErrorHandler()}. If you run the above code with the sample XML document, it'll print \code{Sandman \#62 found.} \subsection{Error Handling} Now, try running the above code with this file as input: \begin{verbatim} &foo; \end{verbatim} The \code{\&foo;} entity is unknown, and the \element{comic} element isn't closed (if it was empty, there would be a \samp{/} before the closing \samp{>}. As a result, you get a \exception{SAXParseException}, e.g. \begin{verbatim} xml.sax._exceptions<.SAXParseException: undefined entity at None:2:2 \end{verbatim} The default code for the \class{ErrorHandler} interface automatically raises an exception for any error; if that is what you want, you don't need to implement an error handler class at all. Otherwise, you can provide your own version of the \class{ErrorHandler} interface, at minimum overriding the \method{error()} and \method{fatalError()} methods. The minimal implementation for each method can be a single line. The methods in the \class{ErrorHandler} interface---\method{warning()}, \method{error()}, and \method{fatalError()}---are all passed a single argument, an exception instance. The exception will always be a subclass of \exception{SAXException}, and calling \code{str()} on it will produce a readable error message explaining the problem. For example, if you just want to continue running if a recoverable error occurs, simply define the \method{error()} method to print the exception it's passed: \begin{verbatim} def error(self, exception): import sys sys.stderr.write("\%s\n" \% exception) \end{verbatim} With this definition, non-fatal errors will result in an error message, whereas fatal errors will continue to produce a traceback. \subsection{Searching Element Content} Let's tackle a slightly more complicated task: printing out all issues written by a certain author. This now requires looking at element content, because the writer's name is inside a \element{writer} element: \code{Peter Milligan}. The search will be performed using the following algorithm: \begin{enumerate} \item The \method{startElement} method will be more complicated. For \element{comic} elements, the handler has to save the title and number, in case this comic is later found to match the search criterion. For \element{writer} elements, it sets a \code{inWriterContent} flag to true, and sets a \code{writerName} attribute to the empty string. \item Characters outside of XML tags must be processed. When \code{inWriterContent} is true, these characters must be added to the \code{writerName} string. \item When the \element{writer} element is finished, we've now collected all of the element's content in the \code{writerName} attribute, so we can check if the name matches the one we're searching for, and if so, print the information about this comic. We must also set \code{inWriterContent} back to false. \end{enumerate} Here's the first part of the code; this implements step 1. \begin{verbatim} from xml.sax import ContentHandler import string def normalize_whitespace(text): "Remove redundant whitespace from a string" return ' '.join(text.split()) class FindWriter(ContentHandler): def __init__(self, search_name): # Save the name we're looking for self.search_name = normalize_whitespace(search_name) # Initialize the flag to false self.inWriterContent = 0 def startElement(self, name, attrs): # If it's a comic element, save the title and issue if name == 'comic': title = normalize_whitespace(attrs.get('title', "")) number = normalize_whitespace(attrs.get('number', "")) self.this_title = title self.this_number = number # If it's the start of a writer element, set flag elif name == 'writer': self.inWriterContent = 1 self.writerName = "" \end{verbatim} The \method{startElement()} method has been discussed previously. Now we have to look at how the content of elements is processed. The \function{normalize_whitespace()} function is important, and you'll probably use it in your own code. XML treats whitespace very flexibly; you can include extra spaces or newlines wherever you like. This means that you must normalize the whitespace before comparing attribute values or element content; otherwise the comparison might produce an incorrect result due to the content of two elements having different amounts of whitespace. \begin{verbatim} def characters(self, ch): if self.inWriterContent: self.writerName = self.writerName + ch \end{verbatim} The \method{characters()} method is called for characters that aren't inside XML tags. \var{ch} is a string of characters. It is not necessarily a byte string; parsers may also provide a buffer object that is a slice of the full document, or they may pass Unicode objects. You also shouldn't assume that all the characters are passed in a single function call. In the example above, there might be only one call to \method{characters()} for the string \samp{Peter Milligan}, or it might call \method{characters()} once for each character. Another, more realistic example: if the content contains an entity reference, as in \samp{Wagner \& Seagle}, the parser might call the method three times; once for \samp{Wagner\ }, once for \samp{\&}, represented by the entity reference, and again for \samp{\ Seagle}. For step 2 of the algorithm, \method{characters()} only has to check \code{inWriterContent}, and if it's true, add the characters to the string being built up. Finally, when the \element{writer} element ends, the entire name has been collected, so we can compare it to the name we're searching for. \begin{verbatim} def endElement(self, name): if name == 'writer': self.inWriterContent = 0 self.writerName = normalize_whitespace(self.writerName) if self.search_name == self.writerName: print 'Found:', self.this_title, self.this_number \end{verbatim} To avoid being confused by differing whitespace, the \function{normalize_whitespace()} function is called. This can be done because we know that leading and trailing whitespace are insignificant for this application. End tags can't have attributes on them, so there's no \var{attrs} parameter to the \method{endElement()} method. Empty elements with attributes, such as \samp{}, will result in a call to \method{startElement()}, followed immediately by a call to \method{endElement()}. \subsection{Enabling Namespace Processing} SAX2 supports XML namespaces. If namespace processing is active, parsers won't call \method{startElement()}, but instead will call a method named \method{startElementNS()}. The default of this setting varies from parser to parser, so you should always set it to a safe value (unless your handler supports both namespace-aware and -unaware processing). For example, our \class{FindIssue} content handler described in previous section doesn't implement the namespace-aware methods, so we should request that namespace processing is deactivated before beginning to parse XML: \begin{verbatim} from xml.sax import make_parser from xml.sax.handler import feature_namespaces # Create a parser parser = make_parser() # Disable namespace processing parser.setFeature(feature_namespaces, 0) \end{verbatim} The second argument to \method{setFeature()} is the desired state of the feature, mostly commonly a Boolean. You would call \code{parser.setFeature(feature_namespaces, 1)} to enable namespace processing. Namespaces in XML work by first defining a namespace prefix that maps to a given URI specified by the relevant DTD, and then using that prefix to mark elements and attributes that come from that DTD. For example, the XLink specification says that the namaspace URI is \samp{http://www.w3.org/1999/xlink}. The following XML snippet includes some XLink attributes: \begin{verbatim} \end{verbatim} The \attribute{xmlns:xlink} attribute on the \element{root} element declares that the prefix \samp{xlink} maps to the given URL. The \element{elem} element therefore has one attribute named \attribute{href} that comes from the XLink namespace. Namespace-aware methods expect \code{(\var{URI}, \var{name})} tuples instead of just element and attribute names; instead of \samp{xlink:href}, they would receive \code{('http://www.w3.org/1999/xlink', 'href')}. Note that the actual value of the prefix is immaterial, and software shouldn't make assumptions about it. The XML document would have exactly the same meaning if the root element said \samp{xmlns:pref1="http://..."} and the attribute name was given as \samp{pref1:href}. If namespace processing is turned on, you would have to write \method{startElementNS()} and \method{endElementNS()} methods that looked like this: \begin{verbatim} def startElementNS(self, (uri, localname), qname, attrs): ... def endElementNS(self, (uri, localname, qname): ... \end{verbatim} The first argument is a 2-tuple containing the URI and the name of the element within that namespace. \var{qname} is a string containing the original qualified name of the element, such as \samp{xlink:a}, and \var{attrs} is a dictionary of attributes. The keys of this dictionary will be \code{(\var{URI}, \var{attribute_name})} pairs. If no namespace is specified for an element or attribute, the URI will given given as \code{None}. %========================================================================== \section{DOM: The Document Object Model} \label{section-DOM} With SAX you write a class which then gets the entire document poured through it as a sequence of method calls. An alternative approach is that taken by the Document Object Model, or DOM, which turns an XML document into a tree that's fully resident in memory. A top-level \class{Document} instance is the root of the tree, and has a single child which is the top-level \class{Element} instance; this \class{Element} has child nodes representing the content and any sub-elements, which may in turn have further children and so forth. There are different classes for everything that can be found in an XML document, so in addition to the \class{Element} class, there are also classes such as \class{Text}, \class{Comment}, \class{CDATASection}, \class{EntityReference}, and so on. Nodes have methods for accessing the parent and child nodes, accessing element and attribute values, insert and delete nodes, and converting the tree back into XML. The DOM is often useful for modifying XML documents, because you can create a DOM tree, modify it by adding new nodes and moving subtrees around, and then produce a new XML document as output. On the other hand, while the DOM doesn't require that the entire tree be resident in memory at one time, the Python DOM implementation currently keeps the whole tree in RAM. This means you may not have enough memory to process very large documents as a DOM tree. A SAX handler, on the other hand, can potentially churn through amounts of data far larger than the available RAM. This HOWTO can't be a complete introduction to the Document Object Model, because there are lots of interfaces and lots of methods. Luckily, the DOM Recommendation is quite readable, so I'd recommend that you read it to get a complete picture of the available interfaces. This section will only be a partial overview. \begin{seealso} \seetitle[http://www.w3.org/TR/REC-DOM-Level-1/] {Document Object Model (DOM) Level 1} {The first version of the DOM endorsed by the W3C. Unlike most standards, this one is actually pretty readable, particularly if you're only interested in the Core XML interfaces.} \seetitle[http://www.w3.org/DOM/DOMTR] {Document Object Model (DOM) Technical Reports} {Level 2 of the DOM has been defined, adding more specialized features such as support for XML namespaces, events, and ranges. DOM Level 3 is still being worked on, and will add yet more features. This overview provides a concise summary of the current status of each specification, and links to the latest version of each.} \end{seealso} \subsection{Getting A DOM Tree} The easiest way to get a DOM tree is to have it built for you. PyXML offers two alternative implementations of the DOM, \module{xml.dom.minidom} and \code{4DOM}. \module{xml.dom.minidom} is included in Python 2. It is a minimal implementation, which means it does not provide all interfaces and operations required by the DOM standard. \code{4DOM}, part of the 4Suite set of XML tools (\url{http://www.4suite.org}), is a complete implementation of DOM Level 2 Core, so we will use that in the examples. The \module{xml.dom.ext.reader} package contains a number of classes that build a DOM tree from various input sources. One of the modules in the \module{xml.dom} package is named \module{Sax2}, and contains a \class{Reader} class that builds a DOM tree from a series of SAX2 events. \class{Reader} instances provide a \method{fromStream()} method that constructs a DOM tree from an input stream; the input can be a file-like object or a string. In the second case, it will be assumed to be a URL and will be opened with the \module{urllib2} module. The advantage of using \module{urllib2} over \module{urllib} is that HTTP errors will be reported as exceptions. \begin{verbatim} import sys from xml.dom.ext.reader import Sax2 # create Reader object reader = Sax2.Reader() # parse the document doc = reader.fromStream(sys.stdin) \end{verbatim} \method{fromStream()} returns the root of a DOM tree constructed from the input XML document. \subsection{Printing The Tree} We'll use a single example document throughout this section. Here's the sample: \begin{verbatim} No description XML bookmarks SIG for XML Processing in Python \end{verbatim} Converted to a DOM tree, this document could produce the following tree. % XXX what did this output come from? \begin{verbatim} Element xbel None Text #text ' \012 ' ProcessingInstruction processing 'instruction' Text #text '\012 ' Element desc None Text #text 'No description' Text #text '\012 ' Element folder None Text #text '\012 ' Element title None Text #text 'XML bookmarks' Text #text '\012 ' Element bookmark None Text #text '\012 ' Element title None Text #text 'SIG for XML Processing in Python' Text #text '\012 ' Text #text '\012 ' Text #text '\012' \end{verbatim} This isn't the only possible tree, because different parsers may differ in how they generate \class{Text} nodes; any of the \class{Text} nodes in the above tree might be split into multiple nodes. A DOM tree can be converted back to XML by using the \function{Print(\var{doc}, \var{stream})} or \function{PrettyPrint(\var{doc}, \var{stream})} functions in the \module{xml.dom.ext} module. If \var{stream} isn't provided, the resulting XML will be printed to standard output. \function{Print()} will simply render the DOM tree without any changes, while \function{PrettyPrint()} will add or remove whitespace in order to nicely indent the resulting XML. \subsection{Manipulating the Tree} We'll start by considering the basic \class{Node} class. All the other DOM nodes---\class{Document}, \class{Element}, \class{Text}, and so forth---are subclasses of \class{Node}. It's possible to perform many tasks using just the interface provided by \class{Node}. First, there are the attributes provided by all \class{Node} instances: \begin{tableii}{l|l}{member}{Attribute}{Meaning} \lineii{nodeType}{Integer constant giving the type of this node: \constant{ELEMENT_NODE}, \constant{TEXT_NODE}, etc.} \lineii{nodeName}{Name of this node. For some types of node, such as \class{Element}s, the name is the element name; for others, such as \class{Text}, the name is a constant value such as \samp{\#text} which isn't very useful. } \lineii{nodeValue}{Value of this node. For some types of node, such as \class{Text} nodes, the value is a string containing a chunk of textual data; for others, such as \class{Element}, the value is just \code{None}.} \lineii{parentNode}{Parent of this node, or \class{None} if this node is the root of a tree (usually meaning that it's a \class{Document} node).} \lineii{childNodes}{A possibly empty list containing the children of this node.} \lineii{firstChild}{First child of this node, or \code{None} if it has no children.} \lineii{lastChild}{Last child of this node, or \code{None} if it has no children.} \lineii{previousSibling}{Preceding child of this node's parent, or \class{None} if this node has no parent or if the parent has no preceding children. } \lineii{nextSibling}{Following child of this's node's parent, or \class{None} if this node has no parent or if the parent has no following children. } \lineii{ownerDocument}{Owning document of this node.} \lineii{attributes}{A \class{NamedNodeMap} instance that behaves mostly like a dictionary, and maps attribute names to \class{Attribute} instances.} \end{tableii} Next, there are the methods. If a node is already a child of node 1 and is added as a child of node 2, it will automatically be removed from node 1; nodes always have exactly zero or one parents. \begin{tableii}{l|l}{method}{Method}{Effect} \lineii{appendChild(\var{newChild})}{Add \var{newChild} as a child of this node, adding it to the end of the list of children. } \lineii{removeChild(\var{oldChild})}{Remove \var{oldChild}; its \member{parentNode} attribute will now return \class{None}.} \lineii{replaceChild(\var{newChild}, \var{oldChild}}{Replace the child \var{oldChild} with \var{newChild}. \var{oldChild} must already be a child of the node.} \lineii{insertBefore(\var{newChild}, \var{refChild})}{ Add \var{newChild} as a child of this node, adding it before the node \var{refChild}. \var{refChild} must already be a child of the node. } \lineii{hasChildNodes()}{Returns true if this node has any children.} \lineii{cloneNode(\var{deep})}{Returns a copy of this node. If \var{deep} is false, the copy will have no children. If it's true, then all of the children will also be copied and added as children to the returned copy. } \end{tableii} \class{Element} nodes and the \class{Document} node also have a useful method, \method{getElementsByTagName(\var{tagName})}, that returns a list of all elements with the given name. For example, all the \samp{chapter} elements can be returned by \code{document.getElementsByTagName('chapter')}. \subsection{Creating New Nodes} The base of the entire tree is the \class{Document} node. Its \member{documentElement} attribute contains the \class{Element} node for the root element. The \class{Document} node may have additional children, such as \class{ProcessingInstruction} nodes, but the list of children can include at most one \class{Element} node. When building a DOM tree from scratch, you'll need to construct new nodes of various types such as \class{Element} and \class{Text}. The \class{Document} node has a bunch of \method{create*()} methods such as \method{createElement} and \method{createTextNode()}. For example, here's an example that adds a new child element named \samp{chapter} to the root element. \begin{verbatim} new = document.createElement('chapter') new.setAttribute('number', '5') document.documentElement.appendChild(new) \end{verbatim} \subsection{Walking Over The Entire Tree} Once you have a tree, another common task is to traverse it. \class{Document} instances have a method called \method{createTreeWalker(\var{root}, \var{whatToShow}, \var{filter}, \var{entityRefExpansion})} that returns an instance of the \class{TreeWalker} class. Once you have a \class{TreeWalker} instance, it allows traversing through the subtree rooted at the \var{root} node. The \member{currentNode} attribute contains the current node that's been reached in this traversal, and can be advanced forward or backward by calling the \method{nextNode()} and \method{previousNode()} methods. There are also methods titled \method{parentNode()}, \method{firstChild()}, \method{lastChild()}, and \method{nextSibling()}, \method{previousSibling()} that return the appropriate value for the current node. \var{whattoshow} is a bitmask with bits set for each type of node that you want to see in the traversal. Constants are available as attributes on the \class{NodeFilter} class. 0 filters out all nodes, \constant{NodeFilter.SHOW_ALL} traverses every node, and constants such as \constant{SHOW_ELEMENT} and \constant{SHOW_TEXT} select individual types of node. \var{filter} is a function that will be passed every traversed node, and can return \constant{NodeFilter.FILTER_ACCEPT} or \constant{NodeFilter.FILTER_REJECT} to accept or reject the node. \var{filter} can be passed as \code{None} in order to accept all nodes. % XXX is expandEntityReferences() actually used anywhere? Here's an example that traverses the entire tree and prints out every element. \begin{verbatim} from xml.dom.NodeFilter import NodeFilter walker = doc.createTreeWalker(doc.documentElement, NodeFilter.SHOW_ELEMENT, None, 0) while 1: print walker.currentNode.tagName next = walker.nextNode() if next is None: break \end{verbatim} % XXX get a patch in and mention iterators %\subsection{More DOM Extensions} %XXX ext.c14n %XXX StripHtml, StripXml, GetElementById, %XmlSpaceState, GetAllNs, SeekNSS, %========================================================================== \section{XPath and XPointer\label{section-XPath}} XPath is a relatively simple language for writing expressions that select a subset of the nodes in a DOM tree. Here are some example XPath expressions, and what nodes they match: \begin{tableii}{l|l}{code}{Expression}{Meaning} \lineii{child::para}{Selects all children of the context node that are \element{para} elements.} \lineii{child::para[5]}{Selects the fifth child of the context node that are \element{para} elements.} \lineii{descendant::para}{Selects all descendants of the context node that are \element{para} elements.} \lineii{ancestor::*}{Selects all ancestors of the context node} \end{tableii} Consult the XPath Recommendation for the full syntax and grammar. The \module{xml.xpath} package contains a parser and evaluator for XPath expressions. The \function{Evaluate(\var{expr}, \var{contextNode})} function parses an expression and evalates it with respect to the given \class{Element} context node. For example: \begin{verbatim} from xml import xpath nodes = xpath.Evaluate('quotation/note', doc.documentElement) \end{verbatim} If \code{doc} is an appropriate DOM tree, then this will return a list containing the subset of nodes denoted by the XPath expression. \begin{seealso} \seetitle[http://www.w3.org/TR/xpath] {XML Path Language (XPath), Version 1.0} {The full specification for XPath.} \end{seealso} \begin{comment} %========================================================================== \section{XSLT\label{section-XSLT}} XML documents are often transformed from one format to another. These transformations can be minor, such as changing all \element{OL} elements into \element{UL} elements, or major, such as translating a DocBook document into HTML so it can be displayed in a Web browser. You can write a separate Python program to do each transformation as you need it, and at times that will be the most appropriate option, but an alternative approach is to use XSL, the Extensible Stylesheet Language. XSL is really two standards: XSLT, XSL Transformations; and XSL-FO, XSL Formatting Objects. XSLT is used much more often than XSL-FO, because XSL-FO is intended primarily for rendering XML for printing onto paper while XSLT is a general tool for transforming one XML document into another document, and therefore can be used for more diverse tasks. The PyXML package only has an implementation of XSLT; XSL-FO is not supported. To use XSLT, you have to write a \dfn{stylesheet}, which is itself an XML document written in the XSLT DTD. The source document is turned into a tree structure, and the stylesheet specifies the transformation you want to perform by selecting some elements from the tree and rearranging them. \subsection{Performing an XSL Transformation} The heart of 4XSLT is the \class{Processor} class. \class{Processor} instances automatically handle the parsing and processing of XSLT stylesheets and of input documents. The usual usage pattern will be to call some methods (\method{appendStylesheetString}, \method{appendStylesheetStream}, \method{appendStylesheetUri}, \method{appendStylesheetNode}) to parse at least one stylesheet, and then run input documents through these stylesheets using another set of methods (\method{runString}, \method{runStream}, \method{runUri}, \method{runNode}). The method names tell you what sort of input is expected, so \method{*String()} takes an XML string and parses it, \method{*Stream()} reads from a file-like object, \method{*Uri()} opens the requested URI, and finally \method{*Node()} expects a node from a DOM tree. % XXX finish this section when XSLT is supported again \begin{seealso} \seetitle[http://www.w3.org/Style/XSL/] {The Extensible Stylesheet Language (XSL)} {The W3C's overview page on XSL has links to the XSLT specifications and to friendlier tutorials.} \end{seealso} \end{comment} %========================================================================== \section{Marshalling Into XML} The \module{xml.marshal} package contains code for marshalling Python data types and objects into XML. The \module{xml.marshal.generic} module uses a simple DTD of its own, and provides \class{Marshaller} and \class{Unmarshaller} classes that can be subclassed to marshal objects using a different DTD. As an example, \module{xml.marshal.wddx} marshals Python objects into the WDDX DTD. The interface is the same as the standard Python \module{marshal} module: \function{dump(\var{value}, \var{file})} and \function{dumps(\var{value})} convert \var{value} into XML and either write it to the given file or return it as a string, while \function{load(\var{file})} and \function{loads(\var{string})} perform the reverse conversion. For example: \begin{verbatim} >>> generic.dumps( (1, 2.0, 'name', [2,3,5,7]) ) """ 1 2.0 name 2 3 5 7 """ >>> \end{verbatim} (The output has been pretty-printed for clarity.) Note that, at least in the \module{generic} module, strings are simply incorporated in the XML output and therefore can't contain control characters that are illegal in XML. If you need to marshal such strings, you'll have to encode them using the \module{binascii} module before calling the \function{dump()} function. %========================================================================== \section{Acknowledgements \label{section-acks}} The author would like to thank the following people for offering suggestions, corrections and assistance with various drafts of this article: Fred~L. Drake, Jr., Martin von L\"owis, Uche Ogbuji, Rich Salz. \end{document} PyXML-0.8.2/doc/xml-howto.txt0100644000076400001440000015625707540155636015207 0ustar martinusers Python/XML HOWTO _________________________________________________________________ A.M. Kuchling akuchlin@mems-exchange.org Abstract: XML is the eXtensible Markup Language, a subset of SGML intended to allow the creation and processing of application-specific markup languages. Python makes an excellent language for processing XML data. This document is a tutorial for the Python/XML package. It assumes you're already somewhat familiar with the structure and terminology of XML, though a brief introduction is supplied. Contents * 1 Introduction to XML + 1.1 Elements, Attributes and Entities + 1.2 Well-Formed XML + 1.3 DTDs * 2 XML-Related Standards * 3 Installing the XML Toolkit * 4 Package Overview * 5 SAX: The Simple API for XML + 5.1 Starting Out + 5.2 Error Handling + 5.3 Searching Element Content + 5.4 Enabling Namespace Processing * 6 DOM: The Document Object Model + 6.1 Getting A DOM Tree + 6.2 Printing The Tree + 6.3 Manipulating the Tree + 6.4 Creating New Nodes + 6.5 Walking Over The Entire Tree * 7 XPath and XPointer * 8 Marshalling Into XML * 9 Acknowledgements * About this document ... 1 Introduction to XML XML, the eXtensible Markup Language, is a simplified dialect of SGML, the Standardized General Markup Language. XML is intended to be reasonably simple to implement and use, and is already being used for specifying markup languages for various new standards: MathML for expressing mathematical equations, Synchronized Multimedia Integration Language for multimedia presentations, and so forth. SGML and XML represent a document by tagging the document's various components with their function or meaning. For example, a book contains several parts: it has a title, one or more authors, the text of the book, perhaps a preface or an index, and so forth. A markup languge for writing books would therefore have elements indicating what the contents of the preface are, what the title is, and so forth. This logical structure should not be confused with the physical details of how the document is actually printed on paper. The index might be printed with narrow margins in a smaller font than the rest of the book, but markup usually isn't (or shouldn't be, anyway) concerned with details such as this. Instead, other software will translate from the markup language to a typeset format, handling the presentation details. This section will provide a brief overview of XML and a few related standards, but it's far from being complete because making it complete would require a full-length book and not a short HOWTO. There's no better way to get a completely accurate (if rather dry) description than to read the original W3C Recommendations; you can find links to them below. If you already know what XML is, you can skip the rest of this section. Later sections of this HOWTO assume that you're familiar with XML terminology. Most sections will use XML terms such as element and attribute. Section does not require that you have experience with any of the various Java SAX implentations. See Also: Extensible Markup Language (XML) 1.0 (Second Edition) For the full details of XML's syntax, the definitive source is the XML 1.0 specification. However, like all specifications it's quite formal and isn't intended to be a friendly introduction or a tutorial. An annotated version of the standard, is also available, and there are many more informal tutorials and books available to introduce you to XML at greater (or lesser) length. The Annotated XML Specification This annotated version of the XML specification, produced by Tim Bray, is quite helpful in clarifying the specification's intent. It is presented as a richly-hyperlinked document that makes navigation easy, and evokes a sense of what hypertext was meant to be. The XML Cover Pages An extensive collection of links to XML and SGML resources, including a news page that's updated every few days. If you can only remember one XML-related URL, remember this one. Cafe con Leche is another good resource. xml-dev mailing list This is a high-traffic list for implementation and development of XML standards. Be warned: Some people might find the discussion too focused on vague theorizing about information representation, and not on inventing new standards and tools or applying existing standards. 1.1 Elements, Attributes and Entities A markup language specified using XML looks a lot like HTML; a document consists of a single element, which contains sub-elements, which can have further sub-elements inside them. Elements are indicated by tags in the text. Tags are always inside angle brackets < >. Elements can either contain content, or they can be empty. An element can contain content between opening and closing tags, as in Euryale, which is a name element containing the data "Euryale". This content may be text data, other XML elements, or a mixture of both. Elements can also be empty, containing nothing, and are represented as a single tag ended with a slash. For example, is an empty stop element. Unlike HTML, XML element names are case-sensitive; stop and Stop are two different elements. Opening and empty tags can also contain attributes, which specify values associated with an element. For example, in the XML text Herakles, the name element has a lang attribute which has a value of "greek". In Hercules, the attribute's value is "latin". XML also includes entities as a shorthand for including a particular character or a longer string. Entity references always begin with a "&" and end with a ";". For example, a particular Unicode character can be written as ሴ using its character code in decimal, or as ሴ using hexadecimal. It's also possible to define your own entities, making &title; expand to ``The Odyssey'', for example. If you want to include the "&" character in XML content, it must be written as &. 1.2 Well-Formed XML A legal XML document must, as a minimum, be well-formed: each opening tag must have a corresponding closing tag, and tags must nest properly. For example, text is not well-formed because the i element should be enclosed inside the b element, but instead the closing tag is encountered first. This example can be made well-formed by swapping the order of the closing tags, resulting in text. If you've ever written HTML by hand, you may have acquired the habit of being a bit sloppy about this. Strictly speaking HTML has exactly the same rules about nesting tags as XML, but most Web browsers are very forgiving of errors in HTML. This is convenient for HTML authors, but it makes it difficult to write programs to parse HTML input because the programs have to cope with all sorts of malformed input. The authors of the XML specification didn't want XML to fall into the same trap, because it would make XML processing software much harder to write. Therefore, all XML parsers have to be strict and must report an error if their input isn't well-formed. The Expat parser includes an executable program named xmlwf that parses the contents of files and reports any well-formedness violations; it's very handy for checking XML data that's been output from a program or written by hand. 1.3 DTDs Well-formedness just says that all tags nest properly and that every opening tag is matched by a closing tag. It says nothing about the order of elements or about which elements can be contained inside other elements. The following XML, apparently representing a book, is well-formed but it doesn't match the structure expected for a book: ... ... ... ... ... ... Prefaces don't come at the end of books, the index doesn't belong at the front, and the abstract doesn't belong in the middle. Well-formedness alone doesn't provide any way of enforcing that order. You could write a Python program that took an XML file like this and checked whether all the parts are in order, but then someone wanting to understand what documents are legal would have to read your program. Document Type Definitions, or DTDs for short, are a more concise way of enforcing ordering and nesting rules. A DTD declares the element names that are allowed, and how elements can be nested inside each other. To take an example from HTML, the LI element, representing an entry in a list, can only occur inside certain elements which represent lists, such as OL or UL. The DTD also specifies the attributes that can be provided for each element, the default value for each attribute, and whether the attribute can be omitted. A validating parser can take a document and a DTD, and check whether the document is legal according to the DTD's rules. (The PyXML package includes a validating parser called xmlproc.) DTDs are therefore an example of a schema language, a language for specifying a set of legal XML documents. Other applications want even stricter control over which documents are legal, and there are therefore stricter schema languages. XML Schema provides a type system and a number of basic types, so you can say that the value of an attribute must be a number or a date. RELAX NG is another schema language that provides more power and flexibility than XML Schema, but is simpler to read and implement. Note that it's quite possible to get useful work done without using any schema language at all. You might decide that just writing well-formed XML and checking it with a Python program is all you need. There's no reason to drag in a schema language if it won't be useful. Let's return to DTDs. A DTD lists the supported elements, the order in which elements must occur, and the possible attributes for each element. Here's a fragment from an imaginary DTD for writing books: The first line declares the book element, and specifies the elements that can occur inside it and the order in which the subelements must be provided. DTDs borrow from regular expression notation in order to express how elements can be repeated; "?"means an element must occur 0 or 1 times, "*" is 0 or more times, and "+" means the element must occur 1 or more times. For example, the above declarations imply that the abstract and appendix elements are optional inside a book element. Exactly one preface element has to be present, and it can be followed by any number of chapter elements; having no chapters at all would be legal. The ATTLIST declaration specifies attributes for the chapter element. Chapters can have two attributes, id and title. title contains character data (CDATA) and is optional (that's what "#IMPLIED"means, for obscure historical reasons). id must contain an ID value, and it's required and not optional. A validating parser could take this DTD and a sample document, and report whether the document is valid according to the rules of the DTD. A document is valid if all the elements occur in the right order, and in the right number of repetitions. 2 XML-Related Standards XML 1.0 is the basic standard, but people have built many, many additional standards and tools on top of XML or to be used with XML. This section will quickly introduce some of these related technologies, paying particular attention to those that are supported by the Python/XML package. SAX The Simple API for XML isn't a standard in the formal sense that XML or ANSI C are. Rather, SAX is an informal specification originally designed by David Megginson with input from many people on the xml-dev mailing list. SAX defines an event-driven interface for parsing XML. To use SAX, you must create Python class instances which implement a specified interface, and the parser will then call various methods on those objects. See section 5. DOM The Document Object Model specifies a tree-based representation for an XML document, as opposed to the event-driven processing provided by SAX. See section 6. Namespaces One XML document can refer to elements from more than one DTD. (Such documents can no longer be validated using DTDs, though other schema languages such as RELAX NG can handle namespaces.) For example, a document might contain both some text and a diagram. The text might be represented using some elements from the HTML DTD, and the diagram might use elements from the Scalable Vector Graphics DTD. All the relevant modules in the PyXML module can be used for namespace-aware processing. XPath and XPointer XPath is a language for referring to parts of an XML document. With XPath you can refer to paragraph number N, or ``all paragraphs of class "warning"'', or all chapters that have one or more subsections. XPointer defines a way to use XPath declarations as the fragment identifier in a URL to point at a part of an XML document. See section 7. XSLT XSLT is a general tool for transforming one XML document into another document, specifying the transformation using another XML document called a stylesheet. RDF The Resource Description Format is for describing metadata about other resources. The PyXML package doesn't contain any support for RDF, but a Python library called Redfoot (http://redfoot.sf.net) is available. 3 Installing the XML Toolkit Releases are available from http://sourceforge.net/projects/pyxml/. Windows users should download the appropriate precompiled version. Linux users can either download an RPM, or install from source. Users on other platfoms have no choice but to install from source. To compile from source on a Unix platform, simply perform the following steps. 1. Download the latest version of the source distribution from http://sourceforge.net/projects/pyxml. Unpack it with the following command. gzip -dc xml-package.tgz | tar -xvf - 2. Run python setup.py install. In order to run this, you'll need to have a C compiler installed, and it should be the same one that was used to build your Python installation. On a Unix system, this operation may require superuser permissions. setup.py supports a number of different commands and options; invoke setup.py without any arguments to see a help message. If you have difficulty installing this software, send a problem report to the XML-SIG mailing list describing the problem, or submit a bug report at http://sourceforget.net/projects/pyxml. One possible problem that some people encounter is a general issue of managing a Python installation with 3rd-party compiled extensions: If, when importing any of the C extensions provided with PyXML, you get an error message saying "undefined symbol: PyUnicodeUCS2_"..., then you are using a version of Python built using a 4-byte representation for Unicode characters, and PyXML was built with a Python that used a 2-byte Unicode character. Conversely, if the error message give a symbol name starting with PyUnicodeUCS4_ (note the different digit near the end), the extension was built using a 4-byte Unicode character, and Python was built using a 2-byte Unicode character. The Python interpreter and all extension code need to be built using the same size Unicode character representation. There are various demonstration programs in the demo/ directory of the Python/XML source distribution. You may wish to look at them to get an idea of what's possible with the XML tools, and as a source of example code. See Also: Python/XML Topic Guide This Guide is the starting point for Python-related XML topics, and includes links to software, mailing lists, documentation, and other useful resources. 4 Package Overview The PyXML package contains over 200 individual modules, some intended for public use and some not. Many of these modules often perform similar tasks, making it difficult to figure out which is the right one to use in any given situation, and this can make it confusing. Here's a list of the 30-odd packages and modules that are considered public, along with brief descriptions to help you choose the right one. xml.dom The Python DOM interface. The full interface support DOM Levels 1 and 2. xml.dom contains the implementation for DOM trees built from XML documents. (This implementation is called 4DOM, and was written by Fourthought Inc.) xml.dom.html DOM trees built from HTML documents are also supported. xml.dom.javadom An adaptor for using Java DOM implementations with Jython. xml.dom.minidom A lightweight DOM implementation that's also included in the Python standard library. xml.dom.minitraversal Offers traversal and ranges on top of xml.dom.minidom, using the 4DOM traversal implementation. xml.dom.pulldom Provides a stream of DOM elements. This module can make it easy to write certain types of DTD-specific processing code. xml.dom.xmlbuilder General support for the experimental Document Object Model (DOM) Level 3 Load and Save Specification. This currently only supports the xml.dom.minidom DOM implementation. xml.dom.ext Various DOM-related extensions for pretty-printing DOM trees as XML or XHTML. xml.dom.ext.Dom2Sax A parser to generate SAX events from a DOM tree. xml.dom.ext.c14n Takes a DOM tree and outputs a text stream containing the Canonical XML representation of the document. xml.dom.ext.reader Classes for building DOM trees from various input sources: SAX1 and SAX2 parsers, htmllib, and directly using Expat. xml.marshal.generic Marshals simple Python data types into an XML format. The Marshaller and Unmarshaller classes can be subclassed in order to implement marshalling into a different XML DTD. xml.marshal.wddx Marshals Python objects into WDDX. (This module is built on top of the preceding generic module.) xml.ns Contains constants for the namespace URIs for various XML-related standards. xml.parsers.sgmllib A version of the sgmllib module that's part of the standard Python library, rewritten to run on top of the sgmlop accelerator module. xml.parsers.xmlproc A validating XML parser. Usually you'll want to use xmlproc via SAX or some other higher-level interface. xml.sax SAX1 and SAX2 support for Python. xml.sax.drivers SAX1 drivers for various parsers: htmllib, LT, Expat, sgmllib, xmllib, xmlproc, and XML-Toolkit. xml.sax.drivers2 SAX2 drivers for various parsers: htmllib, Java SAX parsers (for Jython), Expat, sgmllib, xmlproc. xml.sax.handler Contains the core SAX2 handler classes ContentHandler, DTDHandler, EntityResolver, and ErrorHandler. Also contains symbolic names for the various SAX2 features and properties. xml.sax.sax2exts SAX2 extensions. This contains various factory classes that create parser objects, and is how SAX2 parsers are used. xml.sax.saxlib Contains two SAX2 handler classes, DeclHandler and LexicalHandler, and the XMLFilter interface. Also contains the deprecated SAX1 handler classes. xml.sax.saxutils Various utility classes, such as DefaultHandler, a default base class for SAX2 handlers, ErrorPrinter and ErrorRaiser, two default error handlers, and XMLGenerator, which generates XML output from a SAX2 event stream. xml.sax.xmlreader Contains the XMLReader, the base interface for implementing SAX2 parsers. xml.schema.trex A Python implementation of TREX, a schema language. xml.utils.characters Contains the legal XML character ranges as specified in the XML 1.0 Recommendation, and regular expressions that match various XML tokens. xml.utils.iso8601 Parses ISO-8601 date/time specifiers, which look like "2002-05-09T20:40Z". xml.utils.qp_xml A simple tree-based XML parsing interface. xml.xpath An XPath parser and evaluator. (This implementation is called 4XPath, and was written by Fourthought Inc.) 5 SAX: The Simple API for XML This HOWTO describes version 2 of SAX (also referred to as SAX2). Support is still present for SAX version 1, which is now only of historical interest; SAX1 will not be documented here. SAX is most suitable for purposes where you want to read through an entire XML document from beginning to end, and perform some computation such as building a data structure or summarizing the contained information (computing an average value of a certain element, for example). SAX is not very convenient if you want to modify the document structure by changing how elements are nested, though it would be straightforward to write a SAX program that simply changed element contents or attributes. For example, you wouldn't want to re-order chapters in a book using SAX, but you might want to extract the contents of all name elements with the attribute lang set to 'greek'. One advantage of SAX is speed and simplicity. Let's say you've defined a complicated DTD for listing comic books, and you wish to scan through your collection and list everything written by Neil Gaiman. For this specialized task, there's no need to expend effort examining elements for artists and editors and colourists, because they're irrelevant to the search. You can therefore write a class instance which ignores all elements that aren't writer. Another advantage of SAX is that you don't have the whole document resident in memory at any one time, which matters if you are processing really huge documents. SAX defines 4 basic interfaces. A SAX-compliant XML parser can be passed any objects that support these interfaces, and will call various methods as data is processed. Your task, therefore, is to implement those interfaces that are relevant to your application. The SAX interfaces are: Interface Purpose ContentHandler Called for general document events. This interface is the heart of SAX; its methods are called for the start of the document, the start and end of elements, and for the characters of data contained inside elements. DTDHandler Called to handle DTD events required for basic parsing. This means notation declarations (XML spec section 4.7) and unparsed entity declarations (XML spec section 4). EntityResolver Called to resolve references to external entities. If your documents will have no external entity references, you don't need to implement this interface. ErrorHandler Called for error handling. The parser will call methods from this interface to report all warnings and errors. Python doesn't support the concept of interfaces, so the interfaces listed above are implemented as Python classes. The default method implementations are defined to do nothing--the method body is just a Python pass statement--so usually you can simply ignore methods that aren't relevant to your application. Pseudo-code for using SAX looks something like this: # Define your specialized handler classes from xml.sax import ContentHandler, ... class docHandler(ContentHandler): ... # Create an instance of the handler classes dh = docHandler() # Create an XML parser parser = ... # Tell the parser to use your handler instance parser.setContentHandler(dh) # Parse the file; your handler's methods will get called parser.parse(sys.stdin) See Also: The SAX Home Page This website has the most recent copy of the specification, and lists SAX implementations for various languages and platforms. Much of the information is somewhat Java-centric, though. 5.1 Starting Out Let's follow the earlier example of a comic book collection, using a simple DTD-less format. Here's a sample document for a collection consisting of a single issue: Neil Gaiman Glyn Dillon Charles Vess An XML document must have a single root element; this is the "collection" element. It has one child comic element for each issue; the book's title and number are given as attributes of the comic element. The comic element can in turn contain several other elements such as writer and penciller listing the writer and artists responsible for the issue. There may be several artists or writers for a single issue. Let's start off with something simple: a document handler named FindIssue that reports whether a given issue is in the collection. from xml.sax import saxutils class FindIssue(saxutils.DefaultHandler): def __init__(self, title, number): self.search_title, self.search_number = title, number The DefaultHandler class inherits from all four interfaces: ContentHandler, DTDHandler, EntityResolver, and ErrorHandler. This is what you should use if you want to just write a single class that wraps up all the logic for your parsing. You could also subclass each interface individually and implement separate classes for each purpose. Neither of the two approaches is always ``better'' than the other; mostly it's a matter of taste. Since this class is doing a search, an instance needs to know what it's searching for. The desired title and issue number are passed to the FindIssue constructor, and stored as part of the instance. Now let's override some of the parsing methods. This simple search only requires looking at the attributes of a given element, so only the startElement method is relevant. def startElement(self, name, attrs): # If it's not a comic element, ignore it if name != 'comic': return # Look for the title and number attributes (see text) title = attrs.get('title', None) number = attrs.get('number', None) if (title == self.search_title and number == self.search_number): print title, '#' + str(number), 'found' The startElement() method is passed a string giving the name of the element, and an instance containing the element's attributes. Attributes are accessed using methods from the AttributeList interface, which includes most of the semantics of Python dictionaries. To summarize, the startElement() method looks for comic elements and compares the specified title and number attributes to the search values. If they match, a message is printed out. startElement() is called for every single element in the document. If you added print 'Starting element:', name to the top of startElement(), you would get the following output. Starting element: collection Starting element: comic Starting element: writer Starting element: penciller Starting element: penciller To actually use the class, we need top-level code that creates instances of a parser and of FindIssue, associates the parser and the handler, and then calls a parser method to process the input. from xml.sax import make_parser from xml.sax.handler import feature_namespaces if __name__ == '__main__': # Create a parser parser = make_parser() # Tell the parser we are not interested in XML namespaces parser.setFeature(feature_namespaces, 0) # Create the handler dh = FindIssue('Sandman', '62') # Tell the parser to use our handler parser.setContentHandler(dh) # Parse the input parser.parse(file) The make_parser class can automate the job of creating parsers. There are already several XML parsers available to Python, and more might be added in future. xmllib.py is included as part of the Python standard library, so it's always available, but it's also not particularly fast. A faster version of xmllib.py is included in xml.parsers. The xml.parsers.expat module is faster still, so it's obviously a preferred choice if it's available. make_parser determines which parsers are available and chooses the fastest one, so you don't have to know what the different parsers are, or how they differ. (You can also tell make_parser to try a list of parsers, if you want to use a specific one). Once you've created a parser instance, calling the setContentHandler() method tells the parser what to use as the content handler. There are similar methods for setting the other handlers: setDTDHandler(), setEntityResolver(), and setErrorHandler(). If you run the above code with the sample XML document, it'll print Sandman #62 found. 5.2 Error Handling Now, try running the above code with this file as input: &foo; The &foo; entity is unknown, and the comic element isn't closed (if it was empty, there would be a "/" before the closing ">". As a result, you get a SAXParseException, e.g. xml.sax._exceptions<.SAXParseException: undefined entity at None:2:2 The default code for the ErrorHandler interface automatically raises an exception for any error; if that is what you want, you don't need to implement an error handler class at all. Otherwise, you can provide your own version of the ErrorHandler interface, at minimum overriding the error() and fatalError() methods. The minimal implementation for each method can be a single line. The methods in the ErrorHandler interface--warning(), error(), and fatalError()--are all passed a single argument, an exception instance. The exception will always be a subclass of SAXException, and calling str() on it will produce a readable error message explaining the problem. For example, if you just want to continue running if a recoverable error occurs, simply define the error() method to print the exception it's passed: def error(self, exception): import sys sys.stderr.write("\%s\n" \% exception) With this definition, non-fatal errors will result in an error message, whereas fatal errors will continue to produce a traceback. 5.3 Searching Element Content Let's tackle a slightly more complicated task: printing out all issues written by a certain author. This now requires looking at element content, because the writer's name is inside a writer element: Peter Milligan. The search will be performed using the following algorithm: 1. The startElement method will be more complicated. For comic elements, the handler has to save the title and number, in case this comic is later found to match the search criterion. For writer elements, it sets a inWriterContent flag to true, and sets a writerName attribute to the empty string. 2. Characters outside of XML tags must be processed. When inWriterContent is true, these characters must be added to the writerName string. 3. When the writer element is finished, we've now collected all of the element's content in the writerName attribute, so we can check if the name matches the one we're searching for, and if so, print the information about this comic. We must also set inWriterContent back to false. Here's the first part of the code; this implements step 1. from xml.sax import ContentHandler import string def normalize_whitespace(text): "Remove redundant whitespace from a string" return ' '.join(text.split()) class FindWriter(ContentHandler): def __init__(self, search_name): # Save the name we're looking for self.search_name = normalize_whitespace(search_name) # Initialize the flag to false self.inWriterContent = 0 def startElement(self, name, attrs): # If it's a comic element, save the title and issue if name == 'comic': title = normalize_whitespace(attrs.get('title', "")) number = normalize_whitespace(attrs.get('number', "")) self.this_title = title self.this_number = number # If it's the start of a writer element, set flag elif name == 'writer': self.inWriterContent = 1 self.writerName = "" The startElement() method has been discussed previously. Now we have to look at how the content of elements is processed. The normalize_whitespace() function is important, and you'll probably use it in your own code. XML treats whitespace very flexibly; you can include extra spaces or newlines wherever you like. This means that you must normalize the whitespace before comparing attribute values or element content; otherwise the comparison might produce an incorrect result due to the content of two elements having different amounts of whitespace. def characters(self, ch): if self.inWriterContent: self.writerName = self.writerName + ch The characters() method is called for characters that aren't inside XML tags. ch is a string of characters. It is not necessarily a byte string; parsers may also provide a buffer object that is a slice of the full document, or they may pass Unicode objects. You also shouldn't assume that all the characters are passed in a single function call. In the example above, there might be only one call to characters() for the string "Peter Milligan", or it might call characters() once for each character. Another, more realistic example: if the content contains an entity reference, as in "Wagner & Seagle", the parser might call the method three times; once for "Wagner ", once for "&", represented by the entity reference, and again for " Seagle". For step 2 of the algorithm, characters() only has to check inWriterContent, and if it's true, add the characters to the string being built up. Finally, when the writer element ends, the entire name has been collected, so we can compare it to the name we're searching for. def endElement(self, name): if name == 'writer': self.inWriterContent = 0 self.writerName = normalize_whitespace(self.writerName) if self.search_name == self.writerName: print 'Found:', self.this_title, self.this_number To avoid being confused by differing whitespace, the normalize_whitespace() function is called. This can be done because we know that leading and trailing whitespace are insignificant for this application. End tags can't have attributes on them, so there's no attrs parameter to the endElement() method. Empty elements with attributes, such as "", will result in a call to startElement(), followed immediately by a call to endElement(). 5.4 Enabling Namespace Processing SAX2 supports XML namespaces. If namespace processing is active, parsers won't call startElement(), but instead will call a method named startElementNS(). The default of this setting varies from parser to parser, so you should always set it to a safe value (unless your handler supports both namespace-aware and -unaware processing). For example, our FindIssue content handler described in previous section doesn't implement the namespace-aware methods, so we should request that namespace processing is deactivated before beginning to parse XML: from xml.sax import make_parser from xml.sax.handler import feature_namespaces # Create a parser parser = make_parser() # Disable namespace processing parser.setFeature(feature_namespaces, 0) The second argument to setFeature() is the desired state of the feature, mostly commonly a Boolean. You would call parser.setFeature(feature_namespaces, 1) to enable namespace processing. Namespaces in XML work by first defining a namespace prefix that maps to a given URI specified by the relevant DTD, and then using that prefix to mark elements and attributes that come from that DTD. For example, the XLink specification says that the namaspace URI is "http://www.w3.org/1999/xlink". The following XML snippet includes some XLink attributes: The xmlns:xlink attribute on the root element declares that the prefix "xlink" maps to the given URL. The elem element therefore has one attribute named href that comes from the XLink namespace. Namespace-aware methods expect (URI, name) tuples instead of just element and attribute names; instead of "xlink:href", they would receive ('http://www.w3.org/1999/xlink', 'href'). Note that the actual value of the prefix is immaterial, and software shouldn't make assumptions about it. The XML document would have exactly the same meaning if the root element said "xmlns:pref1="http://..."" and the attribute name was given as "pref1:href". If namespace processing is turned on, you would have to write startElementNS() and endElementNS() methods that looked like this: def startElementNS(self, (uri, localname), qname, attrs): ... def endElementNS(self, (uri, localname, qname): ... The first argument is a 2-tuple containing the URI and the name of the element within that namespace. qname is a string containing the original qualified name of the element, such as "xlink:a", and attrs is a dictionary of attributes. The keys of this dictionary will be (URI, attribute_name) pairs. If no namespace is specified for an element or attribute, the URI will given given as None. 6 DOM: The Document Object Model With SAX you write a class which then gets the entire document poured through it as a sequence of method calls. An alternative approach is that taken by the Document Object Model, or DOM, which turns an XML document into a tree that's fully resident in memory. A top-level Document instance is the root of the tree, and has a single child which is the top-level Element instance; this Element has child nodes representing the content and any sub-elements, which may in turn have further children and so forth. There are different classes for everything that can be found in an XML document, so in addition to the Element class, there are also classes such as Text, Comment, CDATASection, EntityReference, and so on. Nodes have methods for accessing the parent and child nodes, accessing element and attribute values, insert and delete nodes, and converting the tree back into XML. The DOM is often useful for modifying XML documents, because you can create a DOM tree, modify it by adding new nodes and moving subtrees around, and then produce a new XML document as output. On the other hand, while the DOM doesn't require that the entire tree be resident in memory at one time, the Python DOM implementation currently keeps the whole tree in RAM. This means you may not have enough memory to process very large documents as a DOM tree. A SAX handler, on the other hand, can potentially churn through amounts of data far larger than the available RAM. This HOWTO can't be a complete introduction to the Document Object Model, because there are lots of interfaces and lots of methods. Luckily, the DOM Recommendation is quite readable, so I'd recommend that you read it to get a complete picture of the available interfaces. This section will only be a partial overview. See Also: Document Object Model (DOM) Level 1 The first version of the DOM endorsed by the W3C. Unlike most standards, this one is actually pretty readable, particularly if you're only interested in the Core XML interfaces. Document Object Model (DOM) Technical Reports Level 2 of the DOM has been defined, adding more specialized features such as support for XML namespaces, events, and ranges. DOM Level 3 is still being worked on, and will add yet more features. This overview provides a concise summary of the current status of each specification, and links to the latest version of each. 6.1 Getting A DOM Tree The easiest way to get a DOM tree is to have it built for you. PyXML offers two alternative implementations of the DOM, xml.dom.minidom and 4DOM. xml.dom.minidom is included in Python 2. It is a minimal implementation, which means it does not provide all interfaces and operations required by the DOM standard. 4DOM, part of the 4Suite set of XML tools (http://www.4suite.org), is a complete implementation of DOM Level 2 Core, so we will use that in the examples. The xml.dom.ext.reader package contains a number of classes that build a DOM tree from various input sources. One of the modules in the xml.dom package is named Sax2, and contains a Reader class that builds a DOM tree from a series of SAX2 events. Reader instances provide a fromStream() method that constructs a DOM tree from an input stream; the input can be a file-like object or a string. In the second case, it will be assumed to be a URL and will be opened with the urllib2 module. The advantage of using urllib2 over urllib is that HTTP errors will be reported as exceptions. import sys from xml.dom.ext.reader import Sax2 # create Reader object reader = Sax2.Reader() # parse the document doc = reader.fromStream(sys.stdin) fromStream() returns the root of a DOM tree constructed from the input XML document. 6.2 Printing The Tree We'll use a single example document throughout this section. Here's the sample: No description XML bookmarks SIG for XML Processing in Python Converted to a DOM tree, this document could produce the following tree. Element xbel None Text #text ' \012 ' ProcessingInstruction processing 'instruction' Text #text '\012 ' Element desc None Text #text 'No description' Text #text '\012 ' Element folder None Text #text '\012 ' Element title None Text #text 'XML bookmarks' Text #text '\012 ' Element bookmark None Text #text '\012 ' Element title None Text #text 'SIG for XML Processing in Python' Text #text '\012 ' Text #text '\012 ' Text #text '\012' This isn't the only possible tree, because different parsers may differ in how they generate Text nodes; any of the Text nodes in the above tree might be split into multiple nodes. A DOM tree can be converted back to XML by using the Print(doc, stream) or PrettyPrint(doc, stream) functions in the xml.dom.ext module. If stream isn't provided, the resulting XML will be printed to standard output. Print() will simply render the DOM tree without any changes, while PrettyPrint() will add or remove whitespace in order to nicely indent the resulting XML. 6.3 Manipulating the Tree We'll start by considering the basic Node class. All the other DOM nodes--Document, Element, Text, and so forth--are subclasses of Node. It's possible to perform many tasks using just the interface provided by Node. First, there are the attributes provided by all Node instances: Attribute Meaning nodeType Integer constant giving the type of this node: ELEMENT_NODE, TEXT_NODE, etc. nodeName Name of this node. For some types of node, such as Elements, the name is the element name; for others, such as Text, the name is a constant value such as "#text" which isn't very useful. nodeValue Value of this node. For some types of node, such as Text nodes, the value is a string containing a chunk of textual data; for others, such as Text, the value is just None. parentNode Parent of this node, or None if this node is the root of a tree (usually meaning that it's a Document node). childNodes A possibly empty list containing the children of this node. firstChild First child of this node, or None if it has no children. lastChild Last child of this node, or None if it has no children. previousSibling Preceding child of this node's parent, or None if this node has no parent or if the parent has no preceding children. nextSibling Following child of this's node's parent, or None if this node has no parent or if the parent has no following children. ownerDocument Owning document of this node. attributes A NamedNodeMap instance that behaves mostly like a dictionary, and maps attribute names to Attribute instances. Next, there are the methods. If a node is already a child of node 1 and is added as a child of node 2, it will automatically be removed from node 1; nodes always have exactly zero or one parents. Method Effect appendChild(newChild) Add newChild as a child of this node, adding it to the end of the list of children. removeChild(oldChild) Remove oldChild; its parentNode attribute will now return None. replaceChild(newChild, oldChild Replace the child oldChild with newChild. oldChild must already be a child of the node. insertBefore(newChild, refChild) Add newChild as a child of this node, adding it before the node refChild. refChild must already be a child of the node. hasChildNodes() Returns true if this node has any children. cloneNode(deep) Returns a copy of this node. If deep is false, the copy will have no children. If it's true, then all of the children will also be copied and added as children to the returned copy. Element nodes and the Document node also have a useful method, getElementsByTagName(tagName), that returns a list of all elements with the given name. For example, all the "chapter" elements can be returned by document.getElementsByTagName('chapter'). 6.4 Creating New Nodes The base of the entire tree is the Document node. Its documentElement attribute contains the Element node for the root element. The Document node may have additional children, such as ProcessingInstruction nodes, but the list of children can include at most one Element node. When building a DOM tree from scratch, you'll need to construct new nodes of various types such as Element and Text. The Document node has a bunch of create*() methods such as createElement and createTextNode(). For example, here's an example that adds a new child element named "chapter" to the root element. new = document.createElement('chapter') new.setAttribute('number', '5') document.documentElement.appendChild(new) 6.5 Walking Over The Entire Tree Once you have a tree, another common task is to traverse it. Document instances have a method called createTreeWalker(root, whatToShow, filter, entityRefExpansion) that returns an instance of the TreeWalker class. Once you have a TreeWalker instance, it allows traversing through the subtree rooted at the root node. The currentNode attribute contains the current node that's been reached in this traversal, and can be advanced forward or backward by calling the nextNode() and previousNode() methods. There are also methods titled parentNode(), firstChild(), lastChild(), and nextSibling(), previousSibling() that return the appropriate value for the current node. whattoshow is a bitmask with bits set for each type of node that you want to see in the traversal. Constants are available as attributes on the NodeFilter class. 0 filters out all nodes, NodeFilter.SHOW_ALL traverses every node, and constants such as SHOW_ELEMENT and SHOW_TEXT select individual types of node. filter is a function that will be passed every traversed node, and can return NodeFilter.FILTER_ACCEPT or NodeFilter.FILTER_REJECT to accept or reject the node. filter can be passed as None in order to accept all nodes. Here's an example that traverses the entire tree and prints out every element. from xml.dom.NodeFilter import NodeFilter walker = doc.createTreeWalker(doc.documentElement, NodeFilter.SHOW_ELEMENT, None, 0) while 1: print walker.currentNode.tagName next = walker.nextNode() if next is None: break 7 XPath and XPointer XPath is a relatively simple language for writing expressions that select a subset of the nodes in a DOM tree. Here are some example XPath expressions, and what nodes they match: Expression Meaning child::para Selects all children of the context node that are para elements. child::para[5] Selects the fifth child of the context node that are para elements. descendant::para Selects all descendants of the context node that are para elements. ancestor::* Selects all ancestors of the context node Consult the XPath Recommendation for the full syntax and grammar. The xml.xpath package contains a parser and evaluator for XPath expressions. The Evaluate(expr, contextNode) function parses an expression and evalates it with respect to the given Element context node. For example: from xml import xpath nodes = xpath.Evaluate('quotation/note', doc.documentElement) If doc is an appropriate DOM tree, then this will return a list containing the subset of nodes denoted by the XPath expression. See Also: XML Path Language (XPath), Version 1.0 The full specification for XPath. 8 Marshalling Into XML The xml.marshal package contains code for marshalling Python data types and objects into XML. The xml.marshal.generic module uses a simple DTD of its own, and provides Marshaller and Unmarshaller classes that can be subclassed to marshal objects using a different DTD. As an example, xml.marshal.wddx marshals Python objects into the WDDX DTD. The interface is the same as the standard Python marshal module: dump(value, file) and dumps(value) convert value into XML and either write it to the given file or return it as a string, while load(file) and loads(string) perform the reverse conversion. For example: >>> generic.dumps( (1, 2.0, 'name', [2,3,5,7]) ) """ 1 2.0 name 2 3 5 7 """ >>> (The output has been pretty-printed for clarity.) Note that, at least in the generic module, strings are simply incorporated in the XML output and therefore can't contain control characters that are illegal in XML. If you need to marshal such strings, you'll have to encode them using the binascii module before calling the dump() function. 9 Acknowledgements The author would like to thank the following people for offering suggestions, corrections and assistance with various drafts of this article: Fred L. Drake, Jr., Martin von Lwis, Uche Ogbuji, Rich Salz. About this document ... Python/XML HOWTO This document was generated using the LaTeX2HTML translator. LaTeX2HTML is Copyright 1993, 1994, 1995, 1996, 1997, Nikos Drakos, Computer Based Learning Unit, University of Leeds, and Copyright 1997, 1998, Ross Moore, Mathematics Department, Macquarie University, Sydney. The application of LaTeX2HTML to the Python documentation has been heavily tailored by Fred L. Drake, Jr. Original navigation icons were contributed by Christopher Petrilli. _________________________________________________________________ Python/XML HOWTO _________________________________________________________________ Release 0.7.1. PyXML-0.8.2/doc/xml-ref.tex0100644000076400001440000016241107611541420014556 0ustar martinusers% Questions: % Should xmllib.py be moved into xml.parsers? % Should ErrorPrinter go to standard error, not stdout? \documentclass{howto} \newcommand{\element}[1]{\code{#1}} \newcommand{\attribute}[1]{\code{#1}} \title{Python/XML Reference Guide} \release{0.8} \author{The Python/XML Special Interest Group} \authoraddress{\email{xml-sig@python.org}\break (edited by \email{amk@amk.ca})} \begin{document} \maketitle \begin{abstract} \noindent XML is the Extensible Markup Language, a subset of SGML, intended to allow the creation and processing of application-specific markup languages. Python makes an excellent language for processing XML data. This document is the reference manual for the Python/XML package, containing several XML modules. \end{abstract} \tableofcontents \section{\module{xml.dom} Extensions} \declaremodule{}{xml.dom} \modulesynopsis{Common aspects of the DOM interface.} \sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org} \begin{notice} The material in this section describes features of the \module{xml.dom} module that does not appear in the version of the module included with Python. This is written as a supplement to the \ulink{corresponding section}{http://www.python.org/doc/2.2.1/lib/module-xml.dom.html} in the Python 2.2.1 documentation. We intend that all or most of these additions be added to the Python standard library in a future release. \end{notice} Starting with PyXML 0.8, some features of the DOM Level~3 working drafts are being added. These features are based on working drafts and will be changed as the drafts are updated. Use at your own risk. \begin{excdesc}{ValidationErr} New exception. The validation features of the Level~3 DOM can raise this exception when validation constraints are not met. The rest of the validation features have not been implemented, but any Python DOM implementation would use the same exception, so it is offered at this point. \end{excdesc} % Written this way so I can copy the table line into the docs when % this gets integrated. The additional exception code defined in the Level~3 DOM specification map to the exception described above: \begin{tableii}{l|l}{constant}{Constant}{Exception} \lineii{VALIDATION_ERR}{\exception{ValidationErr}} \end{tableii} The \class{Node} class has grown a number of additional constants useful for some of the new methods added in DOM Level~3. These constants are: \constant{TREE_POSITION_PRECEDING}, \constant{TREE_POSITION_FOLLOWING}, \constant{TREE_POSITION_ANCESTOR}, \constant{TREE_POSITION_DESCENDENT}, \constant{TREE_POSITION_EQUIVALENT}, \constant{TREE_POSITION_SAME_NODE}, \constant{TREE_POSITION_DISCONNECTED}. Additional classes have been added to provide access to constants and serve as base classes for implementations: \begin{classdesc*}{UserDataHandler} The DOM Level~3 Core adds a method \method{setUserData()} which accepts an instance conforming to the \class{UserDataHandler} interface. This class provides the constants used as arguments to the \method{handle()} of that interface. The constants provided are \constant{NODE_CLONED}, \constant{NODE_IMPORTED}, \constant{NODE_DELETED}, and \constant{NODE_RENAMED}. Implementation classes may choose to subclass from this class, but there is no reason for them to do so. \end{classdesc*} \begin{classdesc*}{DOMError} The DOM Level~3 Core feature adds support for a user-settable error handler. This class provides the constants used to indicate the severity of an error, and may be used as a base class by DOM implementations. These constants should be used to test the value of the \member{severity} member of instances of this interface. The constants provided are \constant{SEVERITY_WARNING}, \constant{SEVERITY_ERROR}, and \constant{SEVERITY_FATA_ERROR}. \end{classdesc*} The \function{getDOMImplementation()} function has been extended to support DOM Level~3: \begin{funcdesc}{getDOMImplementation}{\optional{name\optional{, features}}} The \var{features} argument now accepts a string as well as a list of feature-version pairs. The string should contain a list of feature names, separated by whitespace, each followed by an optional version number. Version numbers begin with a digit; feature names must not begin with a digit (the draft specification does not adequately address this detail). If a feature name is not followed by a version number, any version of that feature is considered acceptable. \begin{notice} There is an API issue hiding in this addition: The function is still not really compatible with the DOM Level~3 version. The draft specification states that if no implementation is available that provides the desired features, \code{None} should be returned, but this function raises \exception{ImportError}. \end{notice} \end{funcdesc} \subsection{UserDataHandler Objects \label{userdatahandler}} The \class{UserDataHandler} interface, introduced in the DOM Level~3 Core (draft) specification, is used to allow DOM clients to manage node-specific application data stored using the \method{setUserData()} method on nodes. \class{UserDataHandler} implementations need only define one method: \begin{methoddesc}[UserDataHandler]{handle}{operation, key, data, src, dest} This method is called for a few particular events in the lifespan the node on which it was registered. For each type of event, \var{operation} indicates the specific operation being performed on the node, \var{key} gives the key for which \var{data} and the handler object were registered, \var{data} is the actual data object, and \var{src} is the node on which the handler was registered. The \var{dest} argument will always be either \code{None} or a different node, depending on the specific operation. If \var{operation} is \constant{NODE_CLONED}, then \var{dest} is the clone of \var{src}; \var{src} and \var{dest} will always belong to the same document unless \var{src} is a \constant{DOCUMENT_TYPE_NODE}. It \var{operation} is \constant{NODE_IMPORTED}, then \var{dest} is the imported version of \var{src}, and belongs to a different document. If \var{operation} is \constant{NODE_RENAMED}, then \var{src} and \var{dest} are intended to represent the same node, but different node objects are used. This is \emph{not} called when \method{Document.renameNode()} does not create a new node instance. If \var{operation} is \constant{NODE_DELETED}, then \var{src} is about to be deleted (not just removed from the document tree), and \var{dest} is \code{None}. It is not expected that Python implementations of the DOM will implement this, since doing so properly may interfere with the reclamation of unused nodes. The constants passed as the values for the \var{operation} argument of this method are available from the \class{xml.dom.UserDataHandler} class. \end{methoddesc} \section{\module{xml.dom.ext.c14n} --- Canonical XML generation} This module takes a DOM element node (and all its children) and generates canonical XML as defined by the W3C candidate recommendation \url{http://www.w3.org/TR/xml-c14n}. (Unlike the specification, however, general document subsets are not supported.) The module name, \code{c14n}, comes from the standard way of abbreviating the word "canonicalization." This module is typically imported by doing \code{from xml.dom.ext import Canonicalize}. \begin{funcdesc}{Canonicalize}{node\optional{output\optional{**keywords}}} This function generates the canonical format. If \var{output} is specified, the data is sent by invoking its \method{write} method, the the function will return \var{None}. If \var{output} is omitted or has the value \var{None}, then the \method{Canonicalize} will return the data as a string. The keyword argument \var{comments}, if non-zero, directs the function to leave any comment nodes in the output. By default, they are removed. The keyword argument \var{stripspace}, if non-zero, directs the function to strip all extra whitespace from text elements. By default, whitespace is preserved. This argument should be used with caution, as the canonicalization specification directs that whitespace be preserved. The keyword argument \var{nsdict} may be used to provide a namespace dictionary that is assumed to be in the \var{node}'s containing context. The keys are namespace prefixes, and the values are the namespace URI's. If \var{nsdict} is \code{None} or an empty dictionary, then an initial dictionary containing just the URI's for the \code{xml} and \code{xmlns} prefixes will be used. \end{funcdesc} \section{\module{xml.dom.minidom} Extensions} The implementation of \module{xml.dom.minidom} in PyXML contains support for more of the DOM Level~2 Core specification than the version packaged in Python, and incorporates partial support for the draft DOM Level~3 Core and Load/Save specifications. This additional support includes the interfaces documented for the \refmodule{xml.dom.xmlbuilder} module. This section describes the major extensions beyond what's documented for this module in the \citetitle [http://www.python.org/doc/2.2.1/lib/module-xml.dom.minidom.html] {Python Library Reference} for Python 2.2.1. The \class{Entity} and \class{Notation} node types are now supported, and the \class{TypeInfo} interface is also supported. These additional \class{Node} attributes have been implemented or changed: \begin{methoddesc}[Node]{toxml}{\optional{encoding}} The optional \var{encoding} argument has been added to the \method{toxml()} method. When specified and not \code{None}, the output document uses the given encoding. \versionchanged[the \var{encoding} argument was added]{0.8} \end{methoddesc} \begin{methoddesc}[Node]{isSupported}{feature, version} This is equivalent to calling \code{hasFeature(\var{feature}, \var{version})} on the corresponding \class{DOMImplementation} object. Added in DOM Level~2 Core. \end{methoddesc} \begin{methoddesc}[Node]{getInterface}{feature} Return the interface object for the current node that supports the \var{feature} feature if \code{isSupported(\var{feature}, None)} returns true, otherwise returns \code{None}. It is not expected that Python DOM implementations will normally need this, but a DOM implementation that adds substantial new functionality may want to require the use of this method to provide access to a helper object that implements extension-specific methods. Added in DOM Level~3. \end{methoddesc} \begin{methoddesc}[Node]{getUserData}{key} Retrieve the data registered with the node for the key \var{key} using \method{setUserData()}. Returns \code{None} if no data was registered for \var{key}. Added in DOM Level~3. \end{methoddesc} \begin{methoddesc}[Node]{setUserData}{key, data, handler} Set the object \var{data} to be associated with a key \var{key} on the current node. \var{key} can be any hashable object, and will be used as a dictionary key. Any previous value registered for the same value of \var{key} will be discarded. The \var{handler} argument should be \code{None} or an implementation of the \class{UserDataHandler} interface. Added in DOM Level~3. \end{methoddesc} These additional \class{Text} attributes have been added based on the Level~3 drafts. These are also available on \class{CDATASection} nodes. \begin{memberdesc}[Text]{isWhitespaceInElementContent} \code{True} if the text node represents only whitespace and the immediately containing element has a content model that permits only elements as child nodes. If the content model for the containing element is not known, or if there is no containing element, this attribute will be \code{False}. \end{memberdesc} \begin{memberdesc}[Text]{wholeText} Returns the textual content for a contiguous range of nodes of type \constant{TEXT_NODE} and \constant{CDATA_SECTION_NODE} nodes containing the current node. \end{memberdesc} \begin{methoddesc}[Text]{replaceWholeText}{content} Replace a contiguous range of nodes of type \constant{TEXT_NODE} and \constant{CDATA_SECTION_NODE} nodes containing the current node, with a single node containing the text \var{content}. Returns the node containing \var{content}. If \var{content} is an empty string, removes the entire range of affected nodes and returns \code{None}. \end{methoddesc} These methods and attributes have been added to the \class{Document} interface: \begin{memberdesc}[Document]{actualEncoding} The encoding used by the parser, if it was overridden by source context (such as HTTP headers) rather than determined based on the bytes of the source document. If only the source document was used to determine the encoding, this is \code{None} Added in DOM Level~3. \end{memberdesc} \begin{memberdesc}[Document]{encoding} The encoding specified in the XML declaration, or \code{None} if the declaration or \attribute{encoding} pseudo-attribute were omitted. Added in DOM Level~3. \end{memberdesc} \begin{memberdesc}[Document]{standalone} If the \attribute{standalone} pseudo-attribute was given in the document's XML declaration, this will be \code{True} if the value was \samp{yes} or \code{False} if the value was \samp{no}. If the XML declaration or \attribute{standalone} pseudo-attribute were omitted, this will be \code{None}. Added in DOM Level~3. \end{memberdesc} \begin{memberdesc}[Document]{version} The value of the \attribute{version} pseudo-attribute from the XML declaration, if present, or \code{None}. Added in DOM Level~3. \end{memberdesc} \begin{methoddesc}[Document]{importNode}{node, deep} Imports a node \var{node} from another document. If \var{deep} is true, child nodes are recursively imported. Nodes of type \constant{DOCUMENT_NODE} and \constant{DOCUMENT_TYPE_NODE} cannot be imported; if \var{node} has one of these values for its \member{nodeType} attribute, \exception{xml.dom.NotSupportedErr} will be raised. Added in DOM Level~2. \end{methoddesc} \begin{methoddesc}[Document]{renameNode}{node, namespaceURI, name} Added in DOM Level~3. \end{methoddesc} The following have been added to the \class{Attr} class: \begin{memberdesc}[Attr]{isId} \code{True} if the attribute represents an ID while attached to it's current \member{ownerElement}, otherwise \code{False}. Added in DOM Level~3. \end{memberdesc} \begin{memberdesc}[Attr]{schemaType} The \class{TypeInfo} object representing the type of this attribute, taking into account the type of the element to which is it attached. Added in DOM Level~3. \end{memberdesc} The following attributes have been added to the \class{Element} class: \begin{memberdesc}[Element]{schemaType} The \class{TypeInfo} object representing the type of this element, taking into account the type of the element to which is it attached. Added in DOM Level~3. \end{memberdesc} \begin{methoddesc}[Element]{setIdAttribute}{name} \methodline{setIdAttributeNS}{namespaceURI, localName} \methodline{setIdAttributeNode}{idAttr} Set the specified attribute of the element to be an ID, even if the schema information does not cause it to be an ID. Existing IDs remain valid. The \member{schemaType} value is not changed. Added in DOM Level~3. \end{methoddesc} \class{TypeInfo} objects have the following attributes: \begin{memberdesc}[TypeInfo]{name} Name of the type. Type names are only meaningful within the context of a namespace defining type names. DTD-based types have no name, so this will be \code{None} for types from DTDs. \end{memberdesc} \begin{memberdesc}[TypeInfo]{namespace} Namespace URI for a type system. This will be \code{None} for DTD-based types. \end{memberdesc} \strong{Implementation specific behavior:} The DOM Level~2 Core specification leaves some room for differing behaviors for how some node types are handled by the \method{Node.cloneNode()} method. Before PyXML 0.8.1, the specific behavior exhibited by PyXML varied as an accident of implementation. Starting with PyXML 0.8.1, the following behavior is considered intentional and will be maintained. When called on a \class{Document} node, \method{cloneNode()} with the \var{deep} argument set to true will create a new document with the children recursively imported into the new document. When \var{deep} is false, \method{cloneNode()} will return \code{None}, as the operation is no reasonable meaning for the operation. When called on a \class{DocumentType} node, \method{cloneNode()} will return \code{None} if it is owned by a document. If it is not owned, a new document type node is created with all of the attributes copied over, except for the \member{entities} and \member{notations} fields. If \var{deep} is true, these will be new \class{NamedNodeMap} objects which hold clones of the \class{Entity} and \class{Notation} nodes, as appropriate. If \var{deep} is false, these will be initialized to new, empty \class{NamedNodeMap} objects. \section{\module{xml.dom.xmlbuilder} --- DOM Level~3 Load/Save Interface} \declaremodule{}{xml.dom.xmlbuilder} \modulesynopsis{DOM Level~3 Load/Save interface.} \sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org} \versionadded{0.8} \begin{notice}[warning] The \module{xml.dom.xmlbuilder} represents the DOM Level~3 Load/Save interface, which is only defined in a W3C working draft at this time. The Python API presented here is modelled on the 25 July 2025 version of the working draft, and is expected to change as new drafts are released. Backward compatibility to support older versions of this interface will not be preserved. \end{notice} This module provides API support for the DOM Level~3 Load/Save specification. It includes an implementation of the loading components of that specification only at this time. Tow groups of classes are provided. The first group implements the objects specific to the Load/Save specification, and the second provides a group of mixin classes that can be used by a DOM implementation to make use of the first group of classes. Implementation classes: \class{DOMInputSource} \class{DOMEntityResolver} \class{DOMBuilder} \class{DOMBuilderFilter} Mixin classes: \begin{classdesc*}{DOMImplementationLS} Class that can be mixed into an implementation of the \class{DOMImplementation} interface. This implementation provides the \constant{MODE_SYNCHRONOUS} and \constant{MODE_ASYNCHRONOUS} constants and the \method{createDOMBuilder()}, \method{createDOMWriter()}, and \method{createDOMInputSource()} methods. Most DOM implementations should be able to re-use the \method{createDOMInputSource()} method, and will need to override the \method{createDOMBuilder()} method if it will actually be using a different DOM builder. The \method{createDOMWriter()} method should be usable for all implementations once the \class{DOMWriter} has been implemented, but that has not yet been done in PyXML. \end{classdesc*} \begin{classdesc*}{DocumentLS} Class that can be mixed in to a \class{Document} implementation to provide access to features of the Load/Save interface. There isn't much that can be provided by this implementation, so most methods raise \exception{NotSupportedErr}. \end{classdesc*} \subsection{DOMImplementationLS Extensions} The \class{DOMImplementationLS} mixin class is designed to be used in an implementation of the \class{DOMImplementation} interface. This class provides the constants \constant{MODE_SYNCHRONOUS} and \constant{MODE_ASYNCHRONOUS}, and the following methods: \begin{methoddesc}[DOMImplementationLS]{createDOMBuilder}{mode, schemaType} Returns a \class{DOMBuilder} instance. Specific DOM implementations will usually need to override this to return a specialized subclass of the \class{DOMBuilder} class; see the documentation on the \class{DOMBuilder} for information on how and when to write a subclass of that. \end{methoddesc} \begin{methoddesc}[DOMImplementationLS]{createDOMWriter}{} For now, raises \exception{NotImplementedError} since the writer interface has not been implemented yet. \end{methoddesc} \begin{methoddesc}[DOMImplementationLS]{createDOMInputSource}{} Returns a \class{DOMInputSource} instance with all attributes set to \code{None}. \end{methoddesc} \subsection{DocumentLS Extensions} The \class{DocumentLS} mixin class for a \class{Document} adds the following methods: \begin{methoddesc}[DocumentLS]{load}{uri} Load a new document from a URI into this DOM \class{Document} instance. This is not yet implemented in PyXML. \end{methoddesc} \begin{methoddesc}[DocumentLS]{loadXML}{source} Load a new document from a \class{DOMInputSource} into this DOM \class{Document} instance. This is not yet implemented in PyXML. \end{methoddesc} \begin{methoddesc}[DocumentLS]{saveXML}{snode} Return an XML serialization of the DOM node \var{snode} as a string. \var{snode} must belong to this document; if not, \exception{xml.dom.WrongDocumentErr} will be raised. \end{methoddesc} The following attribute is also added: \begin{memberdesc}[DocumentLS]{async} If set to a true value, the \method{load()} and \method{loadXML()} methods should load documents asynchronously. If false, these methods will operate in a synchronous mode. PyXML does not support setting this to true. \end{memberdesc} \subsection{DOMBuilder Objects} The \class{DOMBuilder} class provides support for configuring the DOM construction process, and allows alternate DOM construction methods to be provided by subclasses. The general public API has two aspects, configuration and \class{Document} creation. The configuration aspect provides the following attributes and methods: \begin{methoddesc}[DOMBuilder]{canSetFeature}{name, state} Return true if the feature \var{name} can be set to \var{state}, otherwise returns false. If feature \var{name} is not supported, returns false. \end{methoddesc} \begin{methoddesc}[DOMBuilder]{getFeature}{name} Returns the state for the feature \var{name}. If \var{name} is unrecognized or not supported, \exception{xml.dom.NotFoundErr} is raised. \end{methoddesc} \begin{methoddesc}[DOMBuilder]{setFeature}{name, state} Set the feature \var{name} to \var{state}. If feature \var{name} is not recognized, \exception{xml.dom.NotFoundErr} is raised; if the specific state requested is not supported, \exception{xml.dom.NotSupportedErr} is raised. \end{methoddesc} \begin{methoddesc}[DOMBuilder]{supportsFeature}{name} Returns true if the feature \var{name} is supported at all, otherwise returns false. A true return does not imply that any particular value for the feature is supported. \end{methoddesc} The \class{Document}-creation aspect of the public API is provided by these methods: \begin{methoddesc}[DOMBuilder]{parse}{input} Returns a document based on the \class{DOMInputSource} given as \var{input}. \end{methoddesc} \begin{methoddesc}[DOMBuilder]{parseURI}{uri} Returns a document from the URI given by \var{uri}. \end{methoddesc} \begin{methoddesc}[DOMBuilder]{parseWithContext}{input, cnode, action} \note{Not implemented in the current version.} Legal values for \var{action} are given by the constants \constant{ACTION_REPLACE}, \constant{ACTION_APPEND_AS_CHILDREN}, \constant{ACTION_INSERT_AFTER}, and \constant{ACTION_INSERT_BEFORE}, all defined on the \class{DOMBuilder} class. \end{methoddesc} Subclasses are expected to define the following method to determine how the \class{Document} instances returned by the \method{parse()} method will be created. \begin{notice}[warning] The interface for subclasses is \emph{very} preliminary, and should be considered likely to change in future releases. \end{notice} \begin{methoddesc}[DOMBuilder]{_parse_bytestream}{stream, options} Returns a \class{Document} instance parsed from the file object given as \var{stream} using the configuration options in the \var{options} object. The default implementation uses \module{xml.parsers.expat} to construct documents using the \module{xml.dom.minidom} DOM implementation. \end{methoddesc} \subsection{Subclassing \class{DOMBuilder}} There are two important aspects to subclassing the \class{DOMBuilder}: implementing a useful subclass and getting a \class{DOMImplementation} that uses it. The first aspect is faily easy; to create a \class{DOMBuilder} that uses a different parser, use a subclass that overrides the \method{_parse_bytestream()} method, documented above. The implementation of a specialized DOM builder may not be trivial, but the integration with the provided \class{DOMBuilder} class will be reasonably direct. The second aspect, creating a DOM implementation that uses the new \class{DOMBuilder} implementation, is a little more tedious, but not excessively so. The \class{DOMImplementationLS} mixin class can be used, and the \method{createDOMBuilder()} method overridden to use the new \class{DOMBuilder} implementation. This makes less sense if you want to re-use most of an existing DOM implementation, however. To use a new \class{DOMBuilder} with existing DOM implementation code, such as \module{xml.dom.minidom}, the easiest approach is to subclass an existing \class{DOMImplementation} class. For \module{xml.dom.minidom}, this could be done this way: \begin{verbatim} import xml.dom from xml.dom.minidom import DOMImplementation from xml.dom.xmlbuilder import DOMBuilder class MyDOMBuilder(DOMBuilder): def __init__(self, implementation): self._implementation = implementation def _parse_bytestream(self, stream, options): raise xml.dom.NotSupportedErr( "I'm just an example; don't expect much.") class MyDOMImplementation(DOMImplementation): def createDOMBuilder(self, mode, schemaType): # check for the supported mode and schemaType if schemaType is not None: raise xml.dom.NotSupportedErr( "unsupported schema type: %s" % schemaType) if mode != DOMImplementation.MODE_SYNCHRONOUS: raise xml.dom.NotSupportedErr( "asynchronous loading not supported") return MyDOMBuilder(self) # minidom just stores the implementation on the class instance, # so we need to do the same to override that attribute on instances. # MyDOMImplementation.implementation = MyDOMImplementation() \end{verbatim} %\section{builder} %\section{core} %\section{esis_builder} %\section{html_builder} %\section{sax_builder} %\section{transform} %\section{transformer} %\section{walker} %\section{writer} %\section{\module{xml.marshal}} \section{\module{xml.ns} --- XML Namespace constants} \declaremodule{}{xml.ns} \modulesynopsis{Constants giving the URIs for common namespaces.} \moduleauthor{Rich Salz}{rsalz@zolera.com} \sectionauthor{Rich Salz}{rsalz@zolera.com} \sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org} This module contains the definitions of namespaces (and sometimes other URI's) used by a variety of XML standards. Each class has a short all-uppercase name, which should follow any (emerging) convention for how that standard is commonly used. For example, \samp{ds} is almost always used as the namespace prefixes for items in XML Signature, so \samp{DS} is the class name. Attributes within that class define symbolic names (hopefully evocative) for ``constants'' used in that standard. \begin{classdesc*}{XMLNS} The \citetitle[http://www.w3.org/TR/REC-xml-names]{Namespaces in XML} recommendation defines the concept and syntactic constructs relating to XML namespaces. \begin{memberdesc}{BASE} The namespace URI assigned to namespace declarations. This is assigned to attributes named \code{xmlns} and attributes which have a namespace prefix of \code{xmlns}. \end{memberdesc} \begin{memberdesc}{XML} The namespace bound to this URI is used for all elements and attributes which start with the letters \samp{xml}, regardless of case. No other elements or attributes are allowed to use this namespace. \end{memberdesc} \begin{memberdesc}{HTML} This namespace is recommended for use with HTML 4.0. \end{memberdesc} \end{classdesc*} \begin{classdesc*}{XLINK} The \citetitle[http://www.w3.org/TR/xlink/]{XML Linking Language} defines document linking semantics and an attribute language that allows these semantics to be expressed in XML documents. \begin{memberdesc}{BASE} The URI of the global attributes defined in the XLink specification. All attributes that define the presence and behavior of links are in this namespace. \end{memberdesc} \end{classdesc*} \begin{classdesc*}{SOAP} \citetitle[http://www.w3.org/TR/SOAP]{Simple Object Access Protocol} defines a means of communicating with objects on servers. It can be used as a remote procedure call (RPC) mechanism, or as a basis for message passing systems. \begin{memberdesc}{ENV} This URI is used for the namespace of the ``envelope'' which contains the message. Elements in this namespace provide for destination identification and other information needed to route and decode the message. \end{memberdesc} \begin{memberdesc}{ENC} The namespace URI used for the optional payload encoding defined in section 5 of the SOAP specification. \end{memberdesc} \begin{memberdesc}{ACTOR_NEXT} The URI specified in section 4.2.2 of the SOAP specification which is used to indicate the destination of a SOAP message. \end{memberdesc} \end{classdesc*} \begin{classdesc*}{DSIG} The namespace URIs given here are defined by the XML digital signature specification. \begin{memberdesc}{BASE} The basic namespace defined by the specification. \end{memberdesc} \begin{memberdesc}{C14N} The URI by which \citetitle[http://www.w3.org/TR/xml-c14n]{Canonical XML} (Version 1.0) is identified when used as a transformation or canonicalization method. \end{memberdesc} \begin{memberdesc}{C14N_COMM} This URI identifies ``canonical XML with comments,'' as described in \citetitle[http://www.w3.org/TR/xml-c14n]{Canonical XML} (Version 1.0), section 2.1. \end{memberdesc} \begin{memberdesc}{C14N_EXCL} The URI by which the canonicalization variant defined in \citetitle[http://www.w3.org/TR/xml-exc-c14n]{Exclusive XML Canonicalization} (Version 1.0) is identified when used as a transformation or canonicalization method. \end{memberdesc} The specification also assigns URIs to specific methods of computing message digests and signatures, and other encoding techniques used in the specification. \begin{memberdesc}{DIGEST_SHA1} The URI for the SHA-1 digest method. \end{memberdesc} \begin{memberdesc}{DIGEST_MD2} The URI for the MD2 digest method. \end{memberdesc} \begin{memberdesc}{DIGEST_MD5} The URI for the MD5 digest method. \end{memberdesc} \begin{memberdesc}{SIG_DSA_SHA1} The URI used to specify the Digital Signature Algorithm (DSA) with the SHA-1 hash algorithm. DSA is specified in FIPS PUB 186-2, \citetitle [http://csrc.nist.gov/publications/fips/fips186-2/fips186-2.pdf] {Digital Signature Standard (DSS)}. \end{memberdesc} \begin{memberdesc}{SIG_RSA_SHA1} The URI indicating the RSA signature algorithm using SHA-1 for the secure hash. \end{memberdesc} \begin{memberdesc}{HMAC_SHA1} URI for the SHA-1 HMAC algorithm. \end{memberdesc} \begin{memberdesc}{ENC_BASE64} URI used to denote the base64 encoding and transform. \end{memberdesc} \begin{memberdesc}{ENVELOPED} URI used to specify the enveloped signature transform method (\ulink{section 6.6.4}{http://www.w3.org/TR/xmldsig-core/#sec-EnvelopedSignature} of the specification). \end{memberdesc} \begin{memberdesc}{XPATH} URI used to specify the XPath filtering transform method (\ulink{section 6.6.3}{http://www.w3.org/TR/xmldsig-core/#sec-XPath} of the specification). \end{memberdesc} \begin{memberdesc}{XSLT} URI used to specify the XSLT transform method (\ulink{section 6.6.5}{http://www.w3.org/TR/xmldsig-core/#sec-XSLT} of the specification). \end{memberdesc} \end{classdesc*} \begin{classdesc*}{RNG} The URIs provided here are used with the Relax NG schema language. \begin{memberdesc}{BASE} The namespace URI of the elements defined by the \citetitle[http://www.oasis-open.org/committees/relax-ng/spec-20011203.html] {Relax NG Specification}. \end{memberdesc} \end{classdesc*} \begin{classdesc*}{SCHEMA} \begin{memberdesc}{BASE} \end{memberdesc} \begin{memberdesc}{XSD1} \end{memberdesc} \begin{memberdesc}{XSD2} \end{memberdesc} \begin{memberdesc}{XSD3} \end{memberdesc} \begin{memberdesc}{XSI1} \end{memberdesc} \begin{memberdesc}{XSI2} \end{memberdesc} \begin{memberdesc}{XSI3} \end{memberdesc} Two additional convenience attributes are defined: \begin{memberdesc}{XSD_LIST} A sequence of all ... namespaces. \end{memberdesc} \begin{memberdesc}{XSI_LIST} A sequence of all ... namespaces. \end{memberdesc} \end{classdesc*} \begin{classdesc*}{XSLT} XSLT, defined in \citetitle[http://www.w3.org/TR/]{XML Stylesheet Language --- Transformations}, defines a single namespace: \begin{memberdesc}{BASE} This URI is used as the namespace for all XSLT elements and for XSLT attributes attached to non-XSLT elements. \end{memberdesc} \end{classdesc*} %\begin{classdesc*}{XPATH} % Why does this class even exist if there are no namespaces? %\end{classdesc*} \begin{classdesc*}{WSDL} The Web Services Description Language (WSDL) defines a language to specify the logical interactions with applications that use Web technologies as their access mechanism; this can be thought of as an IDL for servers that speak HTTP instead of XDR or IIOP. \begin{memberdesc}{BASE} The basic namespace defined in this specification. \end{memberdesc} \begin{memberdesc}{BIND_SOAP} The URI of the SOAP binding for WSDL. \end{memberdesc} \begin{memberdesc}{BIND_HTTP} HTTP bindings for WSDL using the \code{GET} and \code{POST} methods. \end{memberdesc} \begin{memberdesc}{BIND_MIME} The URI of the namespace for MIME-type bindings for WSDL. \end{memberdesc} \end{classdesc*} \section{\module{xml.parsers.expat} Extensions} The version of the \module{xml.parsers.expat} module currently shipped with PyXML extends that provided by the standard Python library by exposing features of recent versions of the C implementation of the underlying Expat parser. These extensions are described here; the base documentation for this module is that published as part of the \citetitle [http://www.python.org/doc/2.2.1/lib/module-xml.parsers.expat.html] {Python Library Reference}. The module provides a new data attribute: \begin{datadesc}{features} A list of \var{name}-\var{value} pairs giving some information about the compilation of Expat being used. This is generated directly from the feature information provided by Expat's \cfunction{XML_GetFeatureList()} function. It is unlikely to be of interest to most applications. This was added in PyXML 0.8.1 to support Expat 1.95.5 and newer. \end{datadesc} The parser provides a new method: \begin{methoddesc}[xmlparser]{UseForeignDTD}{\optional{flag}} Tells Expat whether is should attempt to load an application-provided external subset if one is not specified by the document type declaration. If \var{flag} is true or omitted, Expat will attempt to load an external subset by calling the \member{ExternalEntityRefHandler} callback with \var{systemId} and \var{publicId} both set to \code{None}; this is done \emph{only} if the document does not specify a external subset. If \var{flag} is false (or this method is never called), Expat will not attempt such a load. This method should only be called before parsing has actually started; \exception{ExpatError} will be raised if this is called after parsing has begun. This was added in PyXML 0.8.1 to support Expat 1.95.5 and newer. \end{methoddesc} and one new attribute: \begin{memberdesc}[xmlparser]{namespace_prefixes} Set to true on a parser with namespaces enabled to request that the actual prefix is reported as well as the namespace URI for each namespace-qualified name. This modifies the element or attribute names passed to the \member{StartElementHandler} and \member{EndElementHandler} callbacks, if true. If set to a true value, the names passed to these callbacks will have the prefix added to the end, separated from the local name by the value of the \var{namespace_separator} passed to the parser constructor. No additional information will be added if the name uses the default namespace. This should only be called before parsing has begun. This was added in PyXML 0.8 to support Expat 1.95.4 and newer. \end{memberdesc} One new callback method has been added as well: \begin{methoddesc}[xmlparser]{SkippedEntityHandler}{name, is_param_entity} This is called when an external entity is not read, and gives information about the entity. The entity name will have been previously reported by the \member{EntityDeclHandler}, if set. This was added in PyXML 0.8 to support Expat 1.95.4 and newer. \end{methoddesc} \begin{seealso} \seetitle[http://www.libexpat.org/]{Expat Home Page}{ The home page for the Expat project provides information about new versions of the library and user resources such as 3rd-party language bindings and mailing lists.} \end{seealso} \section{\module{xml.parsers.sgmllib} --- Accelerated SGML Parser} \declaremodule{}{xml.parsers.sgmllib} \moduleauthor{Fredrik Lundh}{effbot@effbot.org} This module is an alternate implementation of the \ulink{\module{sgmllib} module}{http://www.python.org/doc/current/lib/module-sgmllib.html} from the Python standard library. This implementation uses the \refmodule{xml.parsers.sgmlop} accelerator to improve performance. This module does create a cyclic reference. In order to break the cycle, be sure to call the \method{close()} method of the parser instances when done with them. \section{\module{xml.parsers.sgmlop} --- XML/SGML Parser Accelerator} \declaremodule{}{xml.parsers.sgmlop} \moduleauthor{Fredrik Lundh}{effbot@effbot.org} The \module{xml.parsers.sgmlop} module is a C implementation of a parser similar in interface to the \class{xmllib.XMLParser} and \class{sgmllib.SGMLParser} classes from the \ulink{Python standard library}{http://www.python.org/doc/current/lib/lib.html}. Additional support is provided for a basic tree-constructor which is intended to be used in conjunction with the parsers implemented by this module. %\section{\module{xml.sax.drivers}} %XXX Should all the driver modules be documented, or should they be %treated as internal modules, whose details will be handled by a parser %Factory function? %\section{\module{xml.sax.drivers.drv_xmllib}} %\section{\module{xml.sax.drivers.drv_xmlproc}} %\section{\module{xml.sax.drivers.drv_xmlproc_val}} %\section{\module{xml.sax.drivers.drv_xmltok}} %\section{\module{xml.sax.drivers.drv_xmltoolkit}} \section{\module{xml.sax.saxexts}} \begin{funcdesc}{make_parser}{\optional{parser}} A utility function that returns a \class{Parser} object for a non-validating XML parser. If \var{parser} is specified, it must be a parser name; otherwise, a list of available parsers is checked and the fastest one chosen. \end{funcdesc} \begin{datadesc}{HTMLParserFactory} An instance of the \class{ParserFactory} class that's already been prepared with a list of HTML parsers. Simply call its \method{make_parser()} method to get a \class{Parser} object. \end{datadesc} \begin{classdesc}{ParserFactory}{} A general class to be used by applications for creating parsers on foreign systems where the list of installed parsers is unknown. \end{classdesc} \begin{datadesc}{SGMLParserFactory} An instance of the \class{ParserFactory} class that's already been prepared with a list of SGML parsers. Simply call its \method{make_parser()} method to get a parser object. \end{datadesc} \begin{datadesc}{XMLParserFactory} An instance of the \class{ParserFactory} class that's already been prepared with a list of nonvalidating XML parsers. Simply call its \method{make_parser()} method to get a parser object. \end{datadesc} \begin{datadesc}{XMLValParserFactory} An instance of the \class{ParserFactory} class that's already been prepared with a list of validating XML parsers. Simply call its \method{make_parser()} method to get a parser object. \end{datadesc} \begin{classdesc}{ExtendedParser}{} This class is an experimental extended parser interface, that offers additional functionality that may be useful. However, it's not specified by the SAX specification. \end{classdesc} \subsection{\class{ExtendedParser} methods} \begin{methoddesc}{close}{} Called after the last call to feed, when there are no more data. \end{methoddesc} \begin{methoddesc}{feed}{data} Feeds \var{data} to the parser. \end{methoddesc} \begin{methoddesc}{get_parser_name}{} Returns a single-word parser name. \end{methoddesc} \begin{methoddesc}{get_parser_version}{} Returns the version of the imported parser, which may not be the one the driver was implemented for. \end{methoddesc} \begin{methoddesc}{is_dtd_reading}{} True if the parser is non-validating, but conforms to the XML specification by reading the DTD. \end{methoddesc} \begin{methoddesc}{is_validating}{} Returns true if the parser is validating, false otherwise. \end{methoddesc} \begin{methoddesc}{reset}{} Makes the parser start parsing afresh. \end{methoddesc} \subsection{\class{ParserFactory} methods} \begin{methoddesc}{get_parser_list}{} Returns the list of possible drivers. Currently this starts out as \code{["xml.sax.drivers.drv_xmltok", "xml.sax.drivers.drv_xmlproc", "xml.sax.drivers.drv_xmltoolkit", "xml.sax.drivers.drv_xmllib"]}. \end{methoddesc} \begin{methoddesc}{make_parser}{\optional{driver_name}} Returns a SAX driver for the first available parser of the parsers in the list. Note that the list contains drivers, so it first tries the driver and if that exists imports it to see if the parser also exists. If no parsers are available a \class{SAXException} is thrown. Optionally, \var{driver_name} can be a string containing the name of the driver to be used; the stored parser list will then not be used at all. \end{methoddesc} \begin{methoddesc}{set_parser_list}{list} Sets the driver list to \var{list}. \end{methoddesc} \section{\module{xml.sax.saxlib}} \begin{classdesc}{AttributeList}{} Interface for an attribute list. This interface provides information about a list of attributes for an element (only specified or defaulted attributes will be reported). Note that the information returned by this object will be valid only during the scope of the \method{DocumentHandler.startElement} callback, and the attributes will not necessarily be provided in the order declared or specified. \end{classdesc} \begin{classdesc}{DocumentHandler}{} Handle general document events. This is the main client interface for SAX: it contains callbacks for the most important document events, such as the start and end of elements. You need to create an object that implements this interface, and then register it with the \class{Parser}. If you do not want to implement the entire interface, you can derive a class from \class{HandlerBase}, which implements the default functionality. You can find the location of any document event using the \class{Locator} interface supplied by \method{setDocumentLocator()}. \end{classdesc} \begin{classdesc}{DTDHandler}{} Handle DTD events. This interface specifies only those DTD events required for basic parsing (unparsed entities and attributes). If you do not want to implement the entire interface, you can extend \class{HandlerBase}, which implements the default behaviour. \end{classdesc} \begin{classdesc}{EntityResolver}{} This is the basic interface for resolving entities. If you create an object implementing this interface, then register the object with your \class{Parser} instance, the parser will call the method in your object to resolve all external entities. Note that \class{HandlerBase} implements this interface with the default behaviour. \end{classdesc} \begin{classdesc}{ErrorHandler}{} This is the basic interface for SAX error handlers. If you create an object that implements this interface, then register the object with your Parser, the parser will call the methods in your object to report all warnings and errors. There are three levels of errors available: warnings, (possibly) recoverable errors, and unrecoverable errors. All methods take a SAXParseException as the only parameter. \end{classdesc} \begin{classdesc}{HandlerBase}{} Default base class for handlers. This class implements the default behaviour for four SAX interfaces, inheriting from them all: \class{EntityResolver}, \class{DTDHandler}, \class{DocumentHandler}, and \class{ErrorHandler}. Rather than implementing those full interfaces, you may simply extend this class and override the methods that you need. Note that the use of this class is optional, since you are free to implement the interfaces directly if you wish. \end{classdesc} \begin{classdesc}{Locator}{} Interface for associating a SAX event with a document location. A locator object will return valid results only during calls to methods of the \class{SAXDocumentHandler} class; at any other time, the results are unpredictable. \end{classdesc} \begin{classdesc}{Parser}{} Basic interface for SAX parsers. All SAX parsers must implement this basic interface: it allows users to register handlers for different types of events and to initiate a parse from a URI, a character stream, or a byte stream. SAX parsers should also implement a zero-argument constructor. \end{classdesc} \begin{classdesc}{SAXException}{msg, exception, locator} Encapsulate an XML error or warning. This class can contain basic error or warning information from either the XML parser or the application: you can subclass it to provide additional functionality, or to add localization. Note that although you will receive a \exception{SAXException} as the argument to the handlers in the \class{ErrorHandler} interface, you are not actually required to throw the exception; instead, you can simply read the information in it. \end{classdesc} \begin{classdesc}{SAXParseException}{msg, exception, locator} Encapsulate an XML parse error or warning. This exception will include information for locating the error in the original XML document. Note that although the application will receive a \exception{SAXParseException} as the argument to the handlers in the \class{ErrorHandler} interface, the application is not actually required to throw the exception; instead, it can simply read the information in it and take a different action. Since this exception is a subclass of \exception{SAXException}, it inherits the ability to wrap another exception. \end{classdesc} \subsection{\class{AttributeList} methods} The \class{AttributeList} class supports some of the behaviour of Python dictionaries; the \function{len()} function and \method{has_key()}, \method{keys()} methods are available, and \code{attr['href']} will retrieve the value of the \attribute{href} attribute. There are also additional methods specific to \class{AttributeList}: \begin{methoddesc}{getLength}{} Return the number of attributes in the list. \end{methoddesc} \begin{methoddesc}{getName}{i} Return the name of attribute \var{i} in the list. \end{methoddesc} \begin{methoddesc}{getType}{i} Return the type of an attribute in the list. \var{i} can be either the integer index or the attribute name. \end{methoddesc} \begin{methoddesc}{getValue}{i} Return the value of an attribute in the list. \var{i} can be either the integer index or the attribute name. \end{methoddesc} \subsection{\class{DocumentHandler} methods} \begin{methoddesc}{characters}{ch, start, length} Handle a character data event. \end{methoddesc} \begin{methoddesc}{endDocument}{} Handle an event for the end of a document. \end{methoddesc} \begin{methoddesc}{endElement}{name} Handle an event for the end of an element. \end{methoddesc} \begin{methoddesc}{ignorableWhitespace}{ch, start, length} Handle an event for ignorable whitespace in element content. \end{methoddesc} \begin{methoddesc}{processingInstruction}{target, data} Handle a processing instruction event. \end{methoddesc} \begin{methoddesc}{setDocumentLocator}{locator} Receive an object for locating the origin of SAX document events. You'll probably want to store the value of \var{locator} as an attribute of the handler instance. \end{methoddesc} \begin{methoddesc}{startDocument}{} Handle an event for the beginning of a document. \end{methoddesc} \begin{methoddesc}{startElement}{name, attrs} Handle an event for the beginning of an element. \end{methoddesc} \subsection{\class{DTDHandler} methods} \begin{methoddesc}{notationDecl}{name, publicId, systemId} Handle a notation declaration event. \end{methoddesc} \begin{methoddesc}{unparsedEntityDecl}{publicId, systemId, notationName} Handle an unparsed entity declaration event. \end{methoddesc} \subsection{\class{EntityResolver} methods} \begin{methoddesc}{resolveEntity}{name, publicId, systemId} Resolve the system identifier of an entity. \end{methoddesc} \subsection{\class{ErrorHandler} methods} \begin{methoddesc}{error}{exception} Handle a recoverable error. \end{methoddesc} \begin{methoddesc}{fatalError}{exception} Handle a non-recoverable error. \end{methoddesc} \begin{methoddesc}{warning}{exception} Handle a warning. \end{methoddesc} \subsection{\class{Locator} methods} \begin{methoddesc}{getColumnNumber}{} Return the column number where the current event ends. \end{methoddesc} \begin{methoddesc}{getLineNumber}{} Return the line number where the current event ends. \end{methoddesc} \begin{methoddesc}{getPublicId}{} Return the public identifier for the current event. \end{methoddesc} \begin{methoddesc}{getSystemId}{} Return the system identifier for the current event. \end{methoddesc} \subsection{\class{Parser} methods} \begin{methoddesc}{parse}{systemId} Parse an XML document from a system identifier. \end{methoddesc} \begin{methoddesc}{parseFile}{fileobj} Parse an XML document from a file-like object. \end{methoddesc} \begin{methoddesc}{setDocumentHandler}{handler} Register an object to receive basic document-related events. \end{methoddesc} \begin{methoddesc}{setDTDHandler}{handler} Register an object to receive basic DTD-related events. \end{methoddesc} \begin{methoddesc}{setEntityResolver}{resolver} Register an object to resolve external entities. \end{methoddesc} \begin{methoddesc}{setErrorHandler}{handler} Register an object to receive error-message events. \end{methoddesc} \begin{methoddesc}{setLocale}{locale} Allow an application to set the locale for errors and warnings. SAX parsers are not required to provide localisation for errors and warnings; if they cannot support the requested locale, however, they must throw a SAX exception. Applications may request a locale change in the middle of a parse. \end{methoddesc} \subsection{\class{SAXException} methods} \begin{methoddesc}{getException}{} Return the embedded exception, if any. \end{methoddesc} \begin{methoddesc}{getMessage}{} Return a message for this exception. \end{methoddesc} \subsection{\class{SAXParseException} methods} The \class{SAXParseException} class has a \member{locator} attribute, containing an instance of the \class{Locator} class, which represents the location in the document where the parse error occurred. The following methods are delegated to this instance. \begin{methoddesc}{getColumnNumber}{} Return the column number of the end of the text where the exception occurred. \end{methoddesc} \begin{methoddesc}{getLineNumber}{} Return the line number of the end of the text where the exception occurred. \end{methoddesc} \begin{methoddesc}{getPublicId}{} Return the public identifier of the entity where the exception occurred. \end{methoddesc} \begin{methoddesc}{getSystemId}{} Return the system identifier of the entity where the exception occurred. \end{methoddesc} \section{\module{xml.sax.saxutils}} \begin{funcdesc}{escape}{data\optional{, entities}} Escape \character{\&}, \character{<}, and \character{>} in a string of data. You can escape other strings of data by passing a dictionary as the optional \var{entities} parameter. The keys and values must all be strings; each key will be replaced with its corresponding value. \end{funcdesc} \begin{funcdesc}{quoteattr}{data\optional{, entities}} Similar to \function{escape()}, but also prepares \var{data} to be used as an attribute value. The return value is a quoted version of \var{data} with any additional required replacements. \function{quoteattr()} will select a quote character based on the content of \var{data}, attempting to avoid encoding any quote characters in the string. If both single- and double-quote characters are already in \var{data}, the double-quote characters will be encoded and \var{data} will be wrapped in doule-quotes. The resulting string can be used directly as an attribute value: \begin{verbatim} >>> print "" % quoteattr("ab ' cd \" ef") \end{verbatim} This function is useful when generating attribute values for HTML or any SGML using the reference concrete syntax. \end{funcdesc} \begin{classdesc}{Canonizer}{writer} A SAX document handler that produces canonicalized XML output. \var{writer} must support a \method{write()} method which accepts a single string. \end{classdesc} \begin{classdesc}{ErrorPrinter}{} A simple class that just prints error messages to standard error (\code{sys.stderr}). \end{classdesc} \begin{classdesc}{ESISDocHandler}{writer} A SAX document handler that produces naive ESIS output. \var{writer} must support a \method{write()} method which accepts a single string. \end{classdesc} \begin{classdesc}{EventBroadcaster}{list} Takes a list of objects and forwards any method calls received to all objects in the list. The attribute \member{list} holds the list and can freely be modified by clients. \end{classdesc} \begin{classdesc}{Location}{locator} Represents a location in an XML entity. Initialized by being passed a locator, from which it reads off the current location, which is then stored internally. \end{classdesc} \subsection{\class{Location} methods} \begin{methoddesc}{getColumnNumber}{} Return the column number of the location. \end{methoddesc} \begin{methoddesc}{getLineNumber}{} Return the line number of the location. \end{methoddesc} \begin{methoddesc}{getPublicId}{} Return the public identifier for the location. \end{methoddesc} \begin{methoddesc}{getSystemId}{} Return the system identifier for the location. \end{methoddesc} \section{\module{xml.utils.iso8601} %--- Utilities for handling ISO~8601 dates } \declaremodule{}{xml.utils.iso8601} \moduleauthor{Fred L. Drake, Jr.}{fdrake@acm.org} \sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org} The \module{xml.utils.iso8601} module provides conversion routines between the ISO~8601 representations of date/time values and the floating point values used elsewhere in Python. The floating point represtentation is particularly useful in conjunction with the standard \module{time} module. Currently, this module supports a small superset of the ISO~8601 profile described by the World Wide Web Consortium (W3C). This is a subset of ISO~8601, but covers the cases expected to be used most often in the context of XML processing and Web applications. Future versions of this module may support a larger subset of ISO~8601-defined formats. \begin{funcdesc}{parse}{s} Parse an ISO~8601 date representation (with an optional time-of-day component) and return the date in seconds since the epoch. \end{funcdesc} \begin{funcdesc}{parse_timezone}{timezone} Parse an ISO~8601 time zone designator and return the offset relative to Universal Coordinated Time (UTC) in seconds. If \var{timezone} is not valid, \exception{ValueError} is raised. \end{funcdesc} \begin{funcdesc}{tostring}{t\optional{, timezone}} Return formatted date/time value according to the profile described by the W3C. If \var{timezone} is provided, it must be the offset from UTC in seconds specified as a number, or time zone designator which can be parsed by \function{parse_timezone()}. If \var{timezone} is specified as a string and cannot be parsed by \function{parse_timezone()}, \exception{ValueError} will be raised. \end{funcdesc} \begin{funcdesc}{ctime}{t} Return formatter date/time value using the local timezone. This is equivalent to \samp{tostring(\var{t}, time.timezone)}. \end{funcdesc} \begin{seealso} \seetitle{Data elements and interchange formats --- Information interchange --- Representation of dates and times.}{The actual ISO~8601 standard published by the International Organization for Standardization, 1988.} \seetitle[ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/ISO8601.ps.Z] {ISO~8601 date/time representations}{Gary Houston's description of the ISO~8601 formats for humans, written in January 1993.} \seetitle[http://www.cl.cam.ac.uk/~mgk25/iso-time.html]{A Summary of the International Standard Date and Time Notation}{Markus Kuhn's excellent discussion of international date/time representations.} \seetitle[http://www.w3.org/TR/NOTE-datetime]{Date and Time Formats} {World Wide Web Consortium Technical Note from September 1998, written by Misha Wolf and Charles Wicksteed.} \end{seealso} \end{document} PyXML-0.8.2/doc/xml-ref.txt0100644000076400001440000014730207540155636014612 0ustar martinusers Python/XML Reference Guide _________________________________________________________________ The Python/XML Special Interest Group xml-sig@python.org (edited by akuchling@acm.org) Abstract: XML is the Extensible Markup Language, a subset of SGML, intended to allow the creation and processing of application-specific markup languages. Python makes an excellent language for processing XML data. This document is the reference manual for the Python/XML package, containing several XML modules. This is a draft document; 'XXX' in the text indicates that something has to be filled in later, or rewritten, or verified, or something. Contents * 1 xml.dom Extensions + 1.1 UserDataHandler Objects * 2 xml.dom.ext.c14n -- Canonical XML generation * 3 xml.dom.minidom Extensions * 4 xml.dom.xmlbuilder -- DOM Level 3 Load/Save Interface + 4.1 DOMImplementationLS Extensions + 4.2 DocumentLS Extensions + 4.3 DOMBuilder Objects + 4.4 Subclassing DOMBuilder * 5 xml.ns -- XML Namespace constants * 6 xml.parsers.expat Extensions * 7 xml.parsers.sgmllib -- Accelerated SGML Parser * 8 xml.parsers.sgmlop -- XML/SGML Parser Accelerator * 9 xml.sax.saxexts + 9.1 ExtendedParser methods + 9.2 ParserFactory methods * 10 xml.sax.saxlib + 10.1 AttributeList methods + 10.2 DocumentHandler methods + 10.3 DTDHandler methods + 10.4 EntityResolver methods + 10.5 ErrorHandler methods + 10.6 Locator methods + 10.7 Parser methods + 10.8 SAXException methods + 10.9 SAXParseException methods * 11 xml.sax.saxutils + 11.1 Location methods * 12 xml.utils.iso8601 * About this document ... 1 xml.dom Extensions Note: The material in this section describes features of the xml.dom module that does not appear in the version of the module included with Python. This is written as a supplement to the corresponding section in the Python 2.2.1 documentation. We intend that all or most of these additions be added to the Python standard library in a future release. Starting with PyXML 0.8, some features of the DOM Level 3 working drafts are being added. These features are based on working drafts and will be changed as the drafts are updated. Use at your own risk. exception ValidationErr New exception. The validation features of the Level 3 DOM can raise this exception when validation constraints are not met. The rest of the validation features have not been implemented, but any Python DOM implementation would use the same exception, so it is offered at this point. The additional exception code defined in the Level 3 DOM specification map to the exception described above: Constant Exception VALIDATION_ERR ValidationErr The Node class has grown a number of additional constants useful for some of the new methods added in DOM Level 3. These constants are: TREE_POSITION_PRECEDING, TREE_POSITION_FOLLOWING, TREE_POSITION_ANCESTOR, TREE_POSITION_DESCENDENT, TREE_POSITION_EQUIVALENT, TREE_POSITION_SAME_NODE, TREE_POSITION_DISCONNECTED. Additional classes have been added to provide access to constants and serve as base classes for implementations: class UserDataHandler The DOM Level 3 Core adds a method setUserData() which accepts an instance conforming to the UserDataHandler interface. This class provides the constants used as arguments to the handle() of that interface. The constants provided are NODE_CLONED, NODE_IMPORTED, NODE_DELETED, and NODE_RENAMED. Implementation classes may choose to subclass from this class, but there is no reason for them to do so. class DOMError The DOM Level 3 Core feature adds support for a user-settable error handler. This class provides the constants used to indicate the severity of an error, and may be used as a base class by DOM implementations. These constants should be used to test the value of the severity member of instances of this interface. The constants provided are SEVERITY_WARNING, SEVERITY_ERROR, and SEVERITY_FATA_ERROR. 1.1 UserDataHandler Objects The UserDataHandler interface, introduced in the DOM Level 3 Core (draft) specification, is used to allow DOM clients to manage node-specific application data stored using the setUserData() method on nodes. UserDataHandler implementations need only define one method: handle( operation, key, data, src, dest) This method is called for a few particular events in the lifespan the node on which it was registered. For each type of event, operation indicates the specific operation being performed on the node, key gives the key for which data and the handler object were registered, data is the actual data object, and src is the node on which the handler was registered. The dest argument will always be either None or a different node, depending on the specific operation. If operation is NODE_CLONED, then dest is the clone of src; src and dest will always belong to the same document unless src is a DOCUMENT_TYPE_NODE. It operation is NODE_IMPORTED, then dest is the imported version of src, and belongs to a different document. If operation is NODE_RENAMED, then src and dest are intended to represent the same node, but different node objects are used. This is not called when Document.renameNode() does not create a new node instance. If operation is NODE_DELETED, then src is about to be deleted (not just removed from the document tree), and dest is None. It is not expected that Python implementations of the DOM will implement this, since doing so properly may interfere with the reclamation of unused nodes. The constants passed as the values for the operation argument of this method are available from the xml.dom.UserDataHandler class. 2 xml.dom.ext.c14n -- Canonical XML generation This module takes a DOM element node (and all its children) and generates canonical XML as defined by the W3C candidate recommendation http://www.w3.org/TR/xml-c14n. (Unlike the specification, however, general document subsets are not supported.) The module name, c14n, comes from the standard way of abbreviating the word "canonicalization." This module is typically imported by doing from xml.dom.ext import Canonicalize. Canonicalize( node[output[**keywords]]) This function generates the canonical format. If output is specified, the data is sent by invoking its write method, the the function will return None. If output is omitted or has the value None, then the Canonicalize will return the data as a string. The keyword argument comments, if non-zero, directs the function to leave any comment nodes in the output. By default, they are removed. The keyword argument stripspace, if non-zero, directs the function to strip all extra whitespace from text elements. By default, whitespace is preserved. This argument should be used with caution, as the canonicalization specification directs that whitespace be preserved. The keyword argument nsdict may be used to provide a namespace dictionary that is assumed to be in the node's containing context. The keys are namespace prefixes, and the values are the namespace URI's. If nsdict is None or an empty dictionary, then an initial dictionary containing just the URI's for the xml and xmlns prefixes will be used. 3 xml.dom.minidom Extensions The implementation of xml.dom.minidom in PyXML contains support for more of the DOM Level 2 Core specification than the version packaged in Python, and incorporates partial support for the draft DOM Level 3 Core and Load/Save specifications. This additional support includes the interfaces documented for the xml.dom.xmlbuilder module. This section describes the major extensions beyond what's documented for this module in the Python Library Reference for Python 2.2.1. The Entity and Notation node types are now supported. These additional Node attributes have been implemented or changed: toxml( [encoding]) The optional encoding argument has been added to the toxml() method. When specified and not None, the output document uses the given encoding. Changed in version 0.8: the encoding argument was added. isSupported( feature, version) This is equivalent to calling hasFeature(feature, version) on the corresponding DOMImplementation object. Added in DOM Level 2 Core. getInterface( feature) Return the interface object for the current node that supports the feature feature if isSupported(feature, None) returns true, otherwise returns None. It is not expected that Python DOM implementations will normally need this, but a DOM implementation that adds substantial new functionality may want to require the use of this method to provide access to a helper object that implements extension-specific methods. Added in DOM Level 3. getUserData( key) Retrieve the data registered with the node for the key key using setUserData(). Returns None if no data was registered for key. Added in DOM Level 3. setUserData( key, data, handler) Set the object data to be associated with a key key on the current node. key can be any hashable object, and will be used as a dictionary key. Any previous value registered for the same value of key will be discarded. The handler argument should be None or an implementation of the UserDataHandler interface. Added in DOM Level 3. These additional Text attributes have been added based on the Level 3 drafts. These are also available on CDATASection nodes. wholeText Returns the textual content for a contiguous range of nodes of type TEXT_NODE and CDATA_SECTION_NODE nodes containing the current node. replaceWholeText( content) Replace a contiguous range of nodes of type TEXT_NODE and CDATA_SECTION_NODE nodes containing the current node, with a single node containing the text content. Returns the node containing content. If content is an empty string, removes the entire range of affected nodes and returns None. These methods and attributes have been added to the Document interface: actualEncoding The encoding used by the parser, if it was overridden by source context (such as HTTP headers) rather than determined based on the bytes of the source document. If only the source document was used to determine the encoding, this is None Added in DOM Level 3. encoding The encoding specified in the XML declaration, or None if the declaration or encoding pseudo-attribute were omitted. Added in DOM Level 3. standalone If the standalone pseudo-attribute was given in the document's XML declaration, this will be True if the value was "yes" or False if the value was "no". If the XML declaration or standalone pseudo-attribute were omitted, this will be None. Added in DOM Level 3. version The value of the version pseudo-attribute from the XML declaration, if present, or None. Added in DOM Level 3. importNode( node, deep) Imports a node node from another document. If deep is true, child nodes are recursively imported. Nodes of type DOCUMENT_NODE and DOCUMENT_TYPE_NODE cannot be imported; if node has one of these values for its nodeType attribute, xml.dom.NotSupportedErr will be raised. Added in DOM Level 2. renameNode( node, namespaceURI, name) Added in DOM Level 3. Implementation specific behavior: The DOM Level 2 Core specification leaves some room for differing behaviors for how some node types are handled by the Node.cloneNode() method. Before PyXML 0.8.1, the specific behavior exhibited by PyXML varied as an accident of implementation. Starting with PyXML 0.8.1, the following behavior is considered intentional and will be maintained. When called on a Document node, cloneNode() with the deep argument set to true will create a new document with the children recursively imported into the new document. When deep is false, cloneNode() will return None, as the operation is no reasonable meaning for the operation. When called on a DocumentType node, cloneNode() will return None if it is owned by a document. If it is not owned, a new document type node is created with all of the attributes copied over, except for the entities and notations fields. If deep is true, these will be new NamedNodeMap objects which hold clones of the Entity and Notation nodes, as appropriate. If deep is false, these will be initialized to new, empty NamedNodeMap objects. 4 xml.dom.xmlbuilder -- DOM Level 3 Load/Save Interface New in version 0.8. Warning: The xml.dom.xmlbuilder represents the DOM Level 3 Load/Save interface, which is only defined in a W3C working draft at this time. The Python API presented here is modelled on the 25 July 2025 version of the working draft, and is expected to change as new drafts are released. Backward compatibility to support older versions of this interface will not be preserved. This module provides API support for the DOM Level 3 Load/Save specification. It includes an implementation of the loading components of that specification only at this time. Tow groups of classes are provided. The first group implements the objects specific to the Load/Save specification, and the second provides a group of mixin classes that can be used by a DOM implementation to make use of the first group of classes. Implementation classes: DOMInputSource DOMEntityResolver DOMBuilder DOMBuilderFilter Mixin classes: class DOMImplementationLS Class that can be mixed into an implementation of the DOMImplementation interface. This implementation provides the MODE_SYNCHRONOUS and MODE_ASYNCHRONOUS constants and the createDOMBuilder(), createDOMWriter(), and createDOMInputSource() methods. Most DOM implementations should be able to re-use the createDOMInputSource() method, and will need to override the createDOMBuilder() method if it will actually be using a different DOM builder. The createDOMWriter() method should be usable for all implementations once the DOMWriter has been implemented, but that has not yet been done in PyXML. class DocumentLS Class that can be mixed in to a Document implementation to provide access to features of the Load/Save interface. There isn't much that can be provided by this implementation, so most methods raise NotSupportedErr. 4.1 DOMImplementationLS Extensions The DOMImplementationLS mixin class is designed to be used in an implementation of the DOMImplementation interface. This class provides the constants MODE_SYNCHRONOUS and MODE_ASYNCHRONOUS, and the following methods: createDOMBuilder( mode, schemaType) Returns a DOMBuilder instance. Specific DOM implementations will usually need to override this to return a specialized subclass of the DOMBuilder class; see the documentation on the DOMBuilder for information on how and when to write a subclass of that. createDOMWriter( ) For now, raises NotImplementedError since the writer interface has not been implemented yet. createDOMInputSource( ) Returns a DOMInputSource instance with all attributes set to None. 4.2 DocumentLS Extensions The DocumentLS mixin class for a Document adds the following methods: load( uri) Load a new document from a URI into this DOM Document instance. This is not yet implemented in PyXML. loadXML( source) Load a new document from a DOMInputSource into this DOM Document instance. This is not yet implemented in PyXML. saveXML( snode) Return an XML serialization of the DOM node snode as a string. snode must belong to this document; if not, xml.dom.WrongDocumentErr will be raised. The following attribute is also added: async If set to a true value, the load() and loadXML() methods should load documents asynchronously. If false, these methods will operate in a synchronous mode. PyXML does not support setting this to true. 4.3 DOMBuilder Objects The DOMBuilder class provides support for configuring the DOM construction process, and allows alternate DOM construction methods to be provided by subclasses. The general public API has two aspects, configuration and Document creation. The configuration aspect provides the following attributes and methods: canSetFeature( name, state) Return true if the feature name can be set to state, otherwise returns false. If feature name is not supported, returns false. getFeature( name) Returns the state for the feature name. If name is unrecognized or not supported, xml.dom.NotFoundErr is raised. setFeature( name, state) Set the feature name to state. If feature name is not recognized, xml.dom.NotFoundErr is raised; if the specific state requested is not supported, xml.dom.NotSupportedErr is raised. supportsFeature( name) Returns true if the feature name is supported at all, otherwise returns false. A true return does not imply that any particular value for the feature is supported. The Document-creation aspect of the public API is provided by these methods: parse( input) Returns a document based on the DOMInputSource given as input. parseURI( uri) Returns a document from the URI given by uri. parseWithContext( input, cnode, action) Note: Not implemented in the current version. Legal values for action are given by the constants ACTION_REPLACE, ACTION_APPEND_AS_CHILDREN, ACTION_INSERT_AFTER, and ACTION_INSERT_BEFORE, all defined on the DOMBuilder class. Subclasses are expected to define the following method to determine how the Document instances returned by the parse() method will be created. Warning: The interface for subclasses is very preliminary, and should be considered likely to change in future releases. _parse_bytestream( stream, options) Returns a Document instance parsed from the file object given as stream using the configuration options in the options object. The default implementation uses xml.parsers.expat to construct documents using the xml.dom.minidom DOM implementation. 4.4 Subclassing DOMBuilder There are two important aspects to subclassing the DOMBuilder: implementing a useful subclass and getting a DOMImplementation that uses it. The first aspect is faily easy; to create a DOMBuilder that uses a different parser, use a subclass that overrides the _parse_bytestream() method, documented above. The implementation of a specialized DOM builder may not be trivial, but the integration with the provided DOMBuilder class will be reasonably direct. The second aspect, creating a DOM implementation that uses the new DOMBuilder implementation, is a little more tedious, but not excessively so. The DOMImplementationLS mixin class can be used, and the createDOMBuilder() method overridden to use the new DOMBuilder implementation. This makes less sense if you want to re-use most of an existing DOM implementation, however. To use a new DOMBuilder with existing DOM implementation code, such as xml.dom.minidom, the easiest approach is to subclass an existing DOMImplementation class. For xml.dom.minidom, this could be done this way: import xml.dom from xml.dom.minidom import DOMImplementation from xml.dom.xmlbuilder import DOMBuilder class MyDOMBuilder(DOMBuilder): def __init__(self, implementation): self._implementation = implementation def _parse_bytestream(self, stream, options): raise xml.dom.NotSupportedErr( "I'm just an example; don't expect much.") class MyDOMImplementation(DOMImplementation): def createDOMBuilder(self, mode, schemaType): # check for the supported mode and schemaType if schemaType is not None: raise xml.dom.NotSupportedErr( "unsupported schema type: %s" % schemaType) if mode != DOMImplementation.MODE_SYNCHRONOUS: raise xml.dom.NotSupportedErr( "asynchronous loading not supported") return MyDOMBuilder(self) # minidom just stores the implementation on the class instance, # so we need to do the same to override that attribute on instances. # MyDOMImplementation.implementation = MyDOMImplementation() 5 xml.ns -- XML Namespace constants This module contains the definitions of namespaces (and sometimes other URI's) used by a variety of XML standards. Each class has a short all-uppercase name, which should follow any (emerging) convention for how that standard is commonly used. For example, "ds" is almost always used as the namespace prefixes for items in XML Signature, so "DS" is the class name. Attributes within that class define symbolic names (hopefully evocative) for ``constants'' used in that standard. class XMLNS The Namespaces in XML recommendation defines the concept and syntactic constructs relating to XML namespaces. BASE The namespace URI assigned to namespace declarations. This is assigned to attributes named xmlns and attributes which have a namespace prefix of xmlns. XML The namespace bound to this URI is used for all elements and attributes which start with the letters "xml", regardless of case. No other elements or attributes are allowed to use this namespace. HTML This namespace is recommended for use with HTML 4.0. class XLINK The XML Linking Language defines document linking semantics and an attribute language that allows these semantics to be expressed in XML documents. BASE The URI of the global attributes defined in the XLink specification. All attributes that define the presence and behavior of links are in this namespace. class SOAP Simple Object Access Protocol defines a means of communicating with objects on servers. It can be used as a remote procedure call (RPC) mechanism, or as a basis for message passing systems. ENV This URI is used for the namespace of the ``envelope'' which contains the message. Elements in this namespace provide for destination identification and other information needed to route and decode the message. ENC The namespace URI used for the optional payload encoding defined in section 5 of the SOAP specification. ACTOR_NEXT The URI specified in section 4.2.2 of the SOAP specification which is used to indicate the destination of a SOAP message. class DSIG The namespace URIs given here are defined by the XML digital signature specification. BASE The basic namespace defined by the specification. C14N The URI by which Canonical XML (Version 1.0) is identified when used as a transformation or canonicalization method. C14N_COMM This URI identifies ``canonical XML with comments,'' as described in Canonical XML (Version 1.0), section 2.1. C14N_EXCL The URI by which the canonicalization variant defined in Exclusive XML Canonicalization (Version 1.0) is identified when used as a transformation or canonicalization method. The specification also assigns URIs to specific methods of computing message digests and signatures, and other encoding techniques used in the specification. DIGEST_SHA1 The URI for the SHA-1 digest method. DIGEST_MD2 The URI for the MD2 digest method. DIGEST_MD5 The URI for the MD5 digest method. SIG_DSA_SHA1 The URI used to specify the Digital Signature Algorithm (DSA) with the SHA-1 hash algorithm. DSA is specified in FIPS PUB 186-2, Digital Signature Standard (DSS). SIG_RSA_SHA1 The URI indicating the RSA signature algorithm using SHA-1 for the secure hash. HMAC_SHA1 URI for the SHA-1 HMAC algorithm. ENC_BASE64 URI used to denote the base64 encoding and transform. ENVELOPED URI used to specify the enveloped signature transform method (section 6.6.4 of the specification). XPATH URI used to specify the XPath filtering transform method (section 6.6.3 of the specification). XSLT URI used to specify the XSLT transform method (section 6.6.5 of the specification). class RNG The URIs provided here are used with the Relax NG schema language. BASE The namespace URI of the elements defined by the Relax NG Specification. class SCHEMA BASE XSD1 XSD2 XSD3 XSI1 XSI2 XSI3 Two additional convenience attributes are defined: XSD_LIST A sequence of all ... namespaces. XSI_LIST A sequence of all ... namespaces. class XSLT XSLT, defined in XML Stylesheet Language -- Transformations, defines a single namespace: BASE This URI is used as the namespace for all XSLT elements and for XSLT attributes attached to non-XSLT elements. class WSDL The Web Services Description Language (WSDL) defines a language to specify the logical interactions with applications that use Web technologies as their access mechanism; this can be thought of as an IDL for servers that speak HTTP instead of XDR or IIOP. BASE The basic namespace defined in this specification. BIND_SOAP The URI of the SOAP binding for WSDL. BIND_HTTP HTTP bindings for WSDL using the GET and POST methods. BIND_MIME The URI of the namespace for MIME-type bindings for WSDL. 6 xml.parsers.expat Extensions The version of the xml.parsers.expat module currently shipped with PyXML extends that provided by the standard Python library by exposing features of recent versions of the C implementation of the underlying Expat parser. These extensions are described here; the base documentation for this module is that published as part of the Python Library Reference. The module provides a new data attribute: features A list of name-value pairs giving some information about the compilation of Expat being used. This is generated directly from the feature information provided by Expat's XML_GetFeatureList() function. It is unlikely to be of interest to most applications. This was added in PyXML 0.8.1 to support Expat 1.95.5 and newer. The parser provides a new method: UseForeignDTD( [flag]) Tells Expat whether is should attempt to load an application-provided external subset if one is not specified by the document type declaration. If flag is true or omitted, Expat will attempt to load an external subset by calling the ExternalEntityRefHandler callback with systemId and publicId both set to None; this is done only if the document does not specify a external subset. If flag is false (or this method is never called), Expat will not attempt such a load. This method should only be called before parsing has actually started; ExpatError will be raised if this is called after parsing has begun. This was added in PyXML 0.8.1 to support Expat 1.95.5 and newer. and one new attribute: namespace_prefixes Set to true on a parser with namespaces enabled to request that the actual prefix is reported as well as the namespace URI for each namespace-qualified name. This modifies the element or attribute names passed to the StartElementHandler and EndElementHandler callbacks, if true. If set to a true value, the names passed to these callbacks will have the prefix added to the end, separated from the local name by the value of the namespace_separator passed to the parser constructor. No additional information will be added if the name uses the default namespace. This should only be called before parsing has begun. This was added in PyXML 0.8 to support Expat 1.95.4 and newer. One new callback method has been added as well: SkippedEntityHandler( name, is_param_entity) This is called when an external entity is not read, and gives information about the entity. The entity name will have been previously reported by the EntityDeclHandler, if set. This was added in PyXML 0.8 to support Expat 1.95.4 and newer. See Also: Expat Home Page The home page for the Expat project provides information about new versions of the library and user resources such as 3rd-party language bindings and mailing lists. 7 xml.parsers.sgmllib -- Accelerated SGML Parser This module is an alternate implementation of the sgmllib module from the Python standard library. This implementation uses the xml.parsers.sgmlop accelerator to improve performance. This module does create a cyclic reference. In order to break the cycle, be sure to call the close() method of the parser instances when done with them. 8 xml.parsers.sgmlop -- XML/SGML Parser Accelerator The xml.parsers.sgmlop module is a C implementation of a parser similar in interface to the xmllib.XMLParser and sgmllib.SGMLParser classes from the Python standard library. Additional support is provided for a basic tree-constructor which is intended to be used in conjunction with the parsers implemented by this module. 9 xml.sax.saxexts make_parser( [parser]) A utility function that returns a Parser object for a non-validating XML parser. If parser is specified, it must be a parser name; otherwise, a list of available parsers is checked and the fastest one chosen. HTMLParserFactory An instance of the ParserFactory class that's already been prepared with a list of HTML parsers. Simply call its make_parser() method to get a Parser object. class ParserFactory( ) A general class to be used by applications for creating parsers on foreign systems where the list of installed parsers is unknown. SGMLParserFactory An instance of the ParserFactory class that's already been prepared with a list of SGML parsers. Simply call its make_parser() method to get a parser object. XMLParserFactory An instance of the ParserFactory class that's already been prepared with a list of nonvalidating XML parsers. Simply call its make_parser() method to get a parser object. XMLValParserFactory An instance of the ParserFactory class that's already been prepared with a list of validating XML parsers. Simply call its make_parser() method to get a parser object. class ExtendedParser( ) This class is an experimental extended parser interface, that offers additional functionality that may be useful. However, it's not specified by the SAX specification. 9.1 ExtendedParser methods close( ) Called after the last call to feed, when there are no more data. feed( data) Feeds data to the parser. get_parser_name( ) Returns a single-word parser name. get_parser_version( ) Returns the version of the imported parser, which may not be the one the driver was implemented for. is_dtd_reading( ) True if the parser is non-validating, but conforms to the XML specification by reading the DTD. is_validating( ) Returns true if the parser is validating, false otherwise. reset( ) Makes the parser start parsing afresh. 9.2 ParserFactory methods get_parser_list( ) Returns the list of possible drivers. Currently this starts out as ["xml.sax.drivers.drv_xmltok", "xml.sax.drivers.drv_xmlproc", "xml.sax.drivers.drv_xmltoolkit", "xml.sax.drivers.drv_xmllib"]. make_parser( [driver_name]) Returns a SAX driver for the first available parser of the parsers in the list. Note that the list contains drivers, so it first tries the driver and if that exists imports it to see if the parser also exists. If no parsers are available a SAXException is thrown. Optionally, driver_name can be a string containing the name of the driver to be used; the stored parser list will then not be used at all. set_parser_list( list) Sets the driver list to list. 10 xml.sax.saxlib class AttributeList( ) Interface for an attribute list. This interface provides information about a list of attributes for an element (only specified or defaulted attributes will be reported). Note that the information returned by this object will be valid only during the scope of the DocumentHandler.startElement callback, and the attributes will not necessarily be provided in the order declared or specified. class DocumentHandler( ) Handle general document events. This is the main client interface for SAX: it contains callbacks for the most important document events, such as the start and end of elements. You need to create an object that implements this interface, and then register it with the Parser. If you do not want to implement the entire interface, you can derive a class from HandlerBase, which implements the default functionality. You can find the location of any document event using the Locator interface supplied by setDocumentLocator(). class DTDHandler( ) Handle DTD events. This interface specifies only those DTD events required for basic parsing (unparsed entities and attributes). If you do not want to implement the entire interface, you can extend HandlerBase, which implements the default behaviour. class EntityResolver( ) This is the basic interface for resolving entities. If you create an object implementing this interface, then register the object with your Parser instance, the parser will call the method in your object to resolve all external entities. Note that HandlerBase implements this interface with the default behaviour. class ErrorHandler( ) This is the basic interface for SAX error handlers. If you create an object that implements this interface, then register the object with your Parser, the parser will call the methods in your object to report all warnings and errors. There are three levels of errors available: warnings, (possibly) recoverable errors, and unrecoverable errors. All methods take a SAXParseException as the only parameter. class HandlerBase( ) Default base class for handlers. This class implements the default behaviour for four SAX interfaces, inheriting from them all: EntityResolver, DTDHandler, DocumentHandler, and ErrorHandler. Rather than implementing those full interfaces, you may simply extend this class and override the methods that you need. Note that the use of this class is optional, since you are free to implement the interfaces directly if you wish. class Locator( ) Interface for associating a SAX event with a document location. A locator object will return valid results only during calls to methods of the SAXDocumentHandler class; at any other time, the results are unpredictable. class Parser( ) Basic interface for SAX parsers. All SAX parsers must implement this basic interface: it allows users to register handlers for different types of events and to initiate a parse from a URI, a character stream, or a byte stream. SAX parsers should also implement a zero-argument constructor. class SAXException( msg, exception, locator) Encapsulate an XML error or warning. This class can contain basic error or warning information from either the XML parser or the application: you can subclass it to provide additional functionality, or to add localization. Note that although you will receive a SAXException as the argument to the handlers in the ErrorHandler interface, you are not actually required to throw the exception; instead, you can simply read the information in it. class SAXParseException( msg, exception, locator) Encapsulate an XML parse error or warning. This exception will include information for locating the error in the original XML document. Note that although the application will receive a SAXParseException as the argument to the handlers in the ErrorHandler interface, the application is not actually required to throw the exception; instead, it can simply read the information in it and take a different action. Since this exception is a subclass of SAXException, it inherits the ability to wrap another exception. 10.1 AttributeList methods The AttributeList class supports some of the behaviour of Python dictionaries; the len() function and has_key(), keys() methods are available, and attr['href'] will retrieve the value of the href attribute. There are also additional methods specific to AttributeList: getLength( ) Return the number of attributes in the list. getName( i) Return the name of attribute i in the list. getType( i) Return the type of an attribute in the list. i can be either the integer index or the attribute name. getValue( i) Return the value of an attribute in the list. i can be either the integer index or the attribute name. 10.2 DocumentHandler methods characters( ch, start, length) Handle a character data event. endDocument( ) Handle an event for the end of a document. endElement( name) Handle an event for the end of an element. ignorableWhitespace( ch, start, length) Handle an event for ignorable whitespace in element content. processingInstruction( target, data) Handle a processing instruction event. setDocumentLocator( locator) Receive an object for locating the origin of SAX document events. You'll probably want to store the value of locator as an attribute of the handler instance. startDocument( ) Handle an event for the beginning of a document. startElement( name, attrs) Handle an event for the beginning of an element. 10.3 DTDHandler methods notationDecl( name, publicId, systemId) Handle a notation declaration event. unparsedEntityDecl( publicId, systemId, notationName) Handle an unparsed entity declaration event. 10.4 EntityResolver methods resolveEntity( name, publicId, systemId) Resolve the system identifier of an entity. 10.5 ErrorHandler methods error( exception) Handle a recoverable error. fatalError( exception) Handle a non-recoverable error. warning( exception) Handle a warning. 10.6 Locator methods getColumnNumber( ) Return the column number where the current event ends. getLineNumber( ) Return the line number where the current event ends. getPublicId( ) Return the public identifier for the current event. getSystemId( ) Return the system identifier for the current event. 10.7 Parser methods parse( systemId) Parse an XML document from a system identifier. parseFile( fileobj) Parse an XML document from a file-like object. setDocumentHandler( handler) Register an object to receive basic document-related events. setDTDHandler( handler) Register an object to receive basic DTD-related events. setEntityResolver( resolver) Register an object to resolve external entities. setErrorHandler( handler) Register an object to receive error-message events. setLocale( locale) Allow an application to set the locale for errors and warnings. SAX parsers are not required to provide localisation for errors and warnings; if they cannot support the requested locale, however, they must throw a SAX exception. Applications may request a locale change in the middle of a parse. 10.8 SAXException methods getException( ) Return the embedded exception, if any. getMessage( ) Return a message for this exception. 10.9 SAXParseException methods The SAXParseException class has a locator attribute, containing an instance of the Locator class, which represents the location in the document where the parse error occurred. The following methods are delegated to this instance. getColumnNumber( ) Return the column number of the end of the text where the exception occurred. getLineNumber( ) Return the line number of the end of the text where the exception occurred. getPublicId( ) Return the public identifier of the entity where the exception occurred. getSystemId( ) Return the system identifier of the entity where the exception occurred. 11 xml.sax.saxutils escape( data[, entities]) Escape "&", "<", and ">" in a string of data. You can escape other strings of data by passing a dictionary as the optional entities parameter. The keys and values must all be strings; each key will be replaced with its corresponding value. quoteattr( data[, entities]) Similar to escape(), but also prepares data to be used as an attribute value. The return value is a quoted version of data with any additional required replacements. quoteattr() will select a quote character based on the content of data, attempting to avoid encoding any quote characters in the string. If both single- and double-quote characters are already in data, the double-quote characters will be encoded and data will be wrapped in doule-quotes. The resulting string can be used directly as an attribute value: >>> print "" % quoteattr("ab ' cd \" ef") This function is useful when generating attribute values for HTML or any SGML using the reference concrete syntax. class Canonizer( writer) A SAX document handler that produces canonicalized XML output. writer must support a write() method which accepts a single string. class ErrorPrinter( ) A simple class that just prints error messages to standard error (sys.stderr). class ESISDocHandler( writer) A SAX document handler that produces naive ESIS output. writer must support a write() method which accepts a single string. class EventBroadcaster( list) Takes a list of objects and forwards any method calls received to all objects in the list. The attribute list holds the list and can freely be modified by clients. class Location( locator) Represents a location in an XML entity. Initialized by being passed a locator, from which it reads off the current location, which is then stored internally. 11.1 Location methods getColumnNumber( ) Return the column number of the location. getLineNumber( ) Return the line number of the location. getPublicId( ) Return the public identifier for the location. getSystemId( ) Return the system identifier for the location. 12 xml.utils.iso8601 The xml.utils.iso8601 module provides conversion routines between the ISO 8601 representations of date/time values and the floating point values used elsewhere in Python. The floating point represtentation is particularly useful in conjunction with the standard time module. Currently, this module supports a small superset of the ISO 8601 profile described by the World Wide Web Consortium (W3C). This is a subset of ISO 8601, but covers the cases expected to be used most often in the context of XML processing and Web applications. Future versions of this module may support a larger subset of ISO 8601-defined formats. parse( s) Parse an ISO 8601 date representation (with an optional time-of-day component) and return the date in seconds since the epoch. parse_timezone( timezone) Parse an ISO 8601 time zone designator and return the offset relative to Universal Coordinated Time (UTC) in seconds. If timezone is not valid, ValueError is raised. tostring( t[, timezone]) Return formatted date/time value according to the profile described by the W3C. If timezone is provided, it must be the offset from UTC in seconds specified as a number, or time zone designator which can be parsed by parse_timezone(). If timezone is specified as a string and cannot be parsed by parse_timezone(), ValueError will be raised. ctime( t) Return formatter date/time value using the local timezone. This is equivalent to "tostring(t, time.timezone)". See Also: Data elements and interchange formats -- Information interchange -- Representation of dates and times. The actual ISO 8601 standard published by the International Organization for Standardization, 1988. ISO 8601 date/time representations Gary Houston's description of the ISO 8601 formats for humans, written in January 1993. A Summary of the International Standard Date and Time Notation Markus Kuhn's excellent discussion of international date/time representations. Date and Time Formats World Wide Web Consortium Technical Note from September 1998, written by Misha Wolf and Charles Wicksteed. About this document ... Python/XML Reference Guide This document was generated using the LaTeX2HTML translator. LaTeX2HTML is Copyright 1993, 1994, 1995, 1996, 1997, Nikos Drakos, Computer Based Learning Unit, University of Leeds, and Copyright 1997, 1998, Ross Moore, Mathematics Department, Macquarie University, Sydney. The application of LaTeX2HTML to the Python documentation has been heavily tailored by Fred L. Drake, Jr. Original navigation icons were contributed by Christopher Petrilli. _________________________________________________________________ Python/XML Reference Guide _________________________________________________________________ Release 0.8. PyXML-0.8.2/extensions/0040755000076400001440000000000007614726123014122 5ustar martinusersPyXML-0.8.2/extensions/expat/0040755000076400001440000000000007614726123015243 5ustar martinusersPyXML-0.8.2/extensions/expat/lib/0040755000076400001440000000000007614726123016011 5ustar martinusersPyXML-0.8.2/extensions/expat/lib/ascii.h0100644000076400001440000000342507614471161017252 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #define ASCII_A 0x41 #define ASCII_B 0x42 #define ASCII_C 0x43 #define ASCII_D 0x44 #define ASCII_E 0x45 #define ASCII_F 0x46 #define ASCII_G 0x47 #define ASCII_H 0x48 #define ASCII_I 0x49 #define ASCII_J 0x4A #define ASCII_K 0x4B #define ASCII_L 0x4C #define ASCII_M 0x4D #define ASCII_N 0x4E #define ASCII_O 0x4F #define ASCII_P 0x50 #define ASCII_Q 0x51 #define ASCII_R 0x52 #define ASCII_S 0x53 #define ASCII_T 0x54 #define ASCII_U 0x55 #define ASCII_V 0x56 #define ASCII_W 0x57 #define ASCII_X 0x58 #define ASCII_Y 0x59 #define ASCII_Z 0x5A #define ASCII_a 0x61 #define ASCII_b 0x62 #define ASCII_c 0x63 #define ASCII_d 0x64 #define ASCII_e 0x65 #define ASCII_f 0x66 #define ASCII_g 0x67 #define ASCII_h 0x68 #define ASCII_i 0x69 #define ASCII_j 0x6A #define ASCII_k 0x6B #define ASCII_l 0x6C #define ASCII_m 0x6D #define ASCII_n 0x6E #define ASCII_o 0x6F #define ASCII_p 0x70 #define ASCII_q 0x71 #define ASCII_r 0x72 #define ASCII_s 0x73 #define ASCII_t 0x74 #define ASCII_u 0x75 #define ASCII_v 0x76 #define ASCII_w 0x77 #define ASCII_x 0x78 #define ASCII_y 0x79 #define ASCII_z 0x7A #define ASCII_0 0x30 #define ASCII_1 0x31 #define ASCII_2 0x32 #define ASCII_3 0x33 #define ASCII_4 0x34 #define ASCII_5 0x35 #define ASCII_6 0x36 #define ASCII_7 0x37 #define ASCII_8 0x38 #define ASCII_9 0x39 #define ASCII_TAB 0x09 #define ASCII_SPACE 0x20 #define ASCII_EXCL 0x21 #define ASCII_QUOT 0x22 #define ASCII_AMP 0x26 #define ASCII_APOS 0x27 #define ASCII_MINUS 0x2D #define ASCII_PERIOD 0x2E #define ASCII_COLON 0x3A #define ASCII_SEMI 0x3B #define ASCII_LT 0x3C #define ASCII_EQUALS 0x3D #define ASCII_GT 0x3E #define ASCII_LSQB 0x5B #define ASCII_RSQB 0x5D #define ASCII_UNDERSCORE 0x5F PyXML-0.8.2/extensions/expat/lib/asciitab.h0100644000076400001440000000334007517567466017755 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, /* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, PyXML-0.8.2/extensions/expat/lib/expat.h0100644000076400001440000010674507614471161017314 0ustar martinusers/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #ifndef XmlParse_INCLUDED #define XmlParse_INCLUDED 1 #ifdef __VMS /* 0 1 2 3 0 1 2 3 1234567890123456789012345678901 1234567890123456789012345678901 */ #define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler #define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler #define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler #define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg #endif #include #ifndef XMLPARSEAPI #if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) #ifdef XML_STATIC #define XMLPARSEAPI(type) type __cdecl #else #define XMLPARSEAPI(type) __declspec(dllimport) type __cdecl #endif #else #define XMLPARSEAPI(type) type #endif #endif /* not defined XMLPARSEAPI */ #ifdef __cplusplus extern "C" { #endif #ifdef XML_UNICODE_WCHAR_T #define XML_UNICODE #endif struct XML_ParserStruct; typedef struct XML_ParserStruct *XML_Parser; #ifdef XML_UNICODE /* Information is UTF-16 encoded. */ #ifdef XML_UNICODE_WCHAR_T typedef wchar_t XML_Char; typedef wchar_t XML_LChar; #else typedef unsigned short XML_Char; typedef char XML_LChar; #endif /* XML_UNICODE_WCHAR_T */ #else /* Information is UTF-8 encoded. */ typedef char XML_Char; typedef char XML_LChar; #endif /* XML_UNICODE */ /* Should this be defined using stdbool.h when C99 is available? */ typedef unsigned char XML_Bool; #define XML_TRUE ((XML_Bool) 1) #define XML_FALSE ((XML_Bool) 0) enum XML_Error { XML_ERROR_NONE, XML_ERROR_NO_MEMORY, XML_ERROR_SYNTAX, XML_ERROR_NO_ELEMENTS, XML_ERROR_INVALID_TOKEN, XML_ERROR_UNCLOSED_TOKEN, XML_ERROR_PARTIAL_CHAR, XML_ERROR_TAG_MISMATCH, XML_ERROR_DUPLICATE_ATTRIBUTE, XML_ERROR_JUNK_AFTER_DOC_ELEMENT, XML_ERROR_PARAM_ENTITY_REF, XML_ERROR_UNDEFINED_ENTITY, XML_ERROR_RECURSIVE_ENTITY_REF, XML_ERROR_ASYNC_ENTITY, XML_ERROR_BAD_CHAR_REF, XML_ERROR_BINARY_ENTITY_REF, XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, XML_ERROR_MISPLACED_XML_PI, XML_ERROR_UNKNOWN_ENCODING, XML_ERROR_INCORRECT_ENCODING, XML_ERROR_UNCLOSED_CDATA_SECTION, XML_ERROR_EXTERNAL_ENTITY_HANDLING, XML_ERROR_NOT_STANDALONE, XML_ERROR_UNEXPECTED_STATE, XML_ERROR_ENTITY_DECLARED_IN_PE, XML_ERROR_FEATURE_REQUIRES_XML_DTD, XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING }; enum XML_Content_Type { XML_CTYPE_EMPTY = 1, XML_CTYPE_ANY, XML_CTYPE_MIXED, XML_CTYPE_NAME, XML_CTYPE_CHOICE, XML_CTYPE_SEQ }; enum XML_Content_Quant { XML_CQUANT_NONE, XML_CQUANT_OPT, XML_CQUANT_REP, XML_CQUANT_PLUS }; /* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be XML_CQUANT_NONE, and the other fields will be zero or NULL. If type == XML_CTYPE_MIXED, then quant will be NONE or REP and numchildren will contain number of elements that may be mixed in and children point to an array of XML_Content cells that will be all of XML_CTYPE_NAME type with no quantification. If type == XML_CTYPE_NAME, then the name points to the name, and the numchildren field will be zero and children will be NULL. The quant fields indicates any quantifiers placed on the name. CHOICE and SEQ will have name NULL, the number of children in numchildren and children will point, recursively, to an array of XML_Content cells. The EMPTY, ANY, and MIXED types will only occur at top level. */ typedef struct XML_cp XML_Content; struct XML_cp { enum XML_Content_Type type; enum XML_Content_Quant quant; XML_Char * name; unsigned int numchildren; XML_Content * children; }; /* This is called for an element declaration. See above for description of the model argument. It's the caller's responsibility to free model when finished with it. */ typedef void (*XML_ElementDeclHandler) (void *userData, const XML_Char *name, XML_Content *model); XMLPARSEAPI(void) XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl); /* The Attlist declaration handler is called for *each* attribute. So a single Attlist declaration with multiple attributes declared will generate multiple calls to this handler. The "default" parameter may be NULL in the case of the "#IMPLIED" or "#REQUIRED" keyword. The "isrequired" parameter will be true and the default value will be NULL in the case of "#REQUIRED". If "isrequired" is true and default is non-NULL, then this is a "#FIXED" default. */ typedef void (*XML_AttlistDeclHandler) (void *userData, const XML_Char *elname, const XML_Char *attname, const XML_Char *att_type, const XML_Char *dflt, int isrequired); XMLPARSEAPI(void) XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl); /* The XML declaration handler is called for *both* XML declarations and text declarations. The way to distinguish is that the version parameter will be NULL for text declarations. The encoding parameter may be NULL for XML declarations. The standalone parameter will be -1, 0, or 1 indicating respectively that there was no standalone parameter in the declaration, that it was given as no, or that it was given as yes. */ typedef void (*XML_XmlDeclHandler) (void *userData, const XML_Char *version, const XML_Char *encoding, int standalone); XMLPARSEAPI(void) XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler xmldecl); typedef struct { void *(*malloc_fcn)(size_t size); void *(*realloc_fcn)(void *ptr, size_t size); void (*free_fcn)(void *ptr); } XML_Memory_Handling_Suite; /* Constructs a new parser; encoding is the encoding specified by the external protocol or NULL if there is none specified. */ XMLPARSEAPI(XML_Parser) XML_ParserCreate(const XML_Char *encoding); /* Constructs a new parser and namespace processor. Element type names and attribute names that belong to a namespace will be expanded; unprefixed attribute names are never expanded; unprefixed element type names are expanded only if there is a default namespace. The expanded name is the concatenation of the namespace URI, the namespace separator character, and the local part of the name. If the namespace separator is '\0' then the namespace URI and the local part will be concatenated without any separator. When a namespace is not declared, the name and prefix will be passed through without expansion. */ XMLPARSEAPI(XML_Parser) XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); /* Constructs a new parser using the memory management suite referred to by memsuite. If memsuite is NULL, then use the standard library memory suite. If namespaceSeparator is non-NULL it creates a parser with namespace processing as described above. The character pointed at will serve as the namespace separator. All further memory operations used for the created parser will come from the given suite. */ XMLPARSEAPI(XML_Parser) XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *memsuite, const XML_Char *namespaceSeparator); /* Prepare a parser object to be re-used. This is particularly valuable when memory allocation overhead is disproportionatly high, such as when a large number of small documnents need to be parsed. All handlers are cleared from the parser, except for the unknownEncodingHandler. The parser's external state is re-initialized except for the values of ns and ns_triplets. Added in Expat 1.95.3. */ XMLPARSEAPI(XML_Bool) XML_ParserReset(XML_Parser parser, const XML_Char *encoding); /* atts is array of name/value pairs, terminated by 0; names and values are 0 terminated. */ typedef void (*XML_StartElementHandler)(void *userData, const XML_Char *name, const XML_Char **atts); typedef void (*XML_EndElementHandler)(void *userData, const XML_Char *name); /* s is not 0 terminated. */ typedef void (*XML_CharacterDataHandler)(void *userData, const XML_Char *s, int len); /* target and data are 0 terminated */ typedef void (*XML_ProcessingInstructionHandler)(void *userData, const XML_Char *target, const XML_Char *data); /* data is 0 terminated */ typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); typedef void (*XML_StartCdataSectionHandler)(void *userData); typedef void (*XML_EndCdataSectionHandler)(void *userData); /* This is called for any characters in the XML document for which there is no applicable handler. This includes both characters that are part of markup which is of a kind that is not reported (comments, markup declarations), or characters that are part of a construct which could be reported but for which no handler has been supplied. The characters are passed exactly as they were in the XML document except that they will be encoded in UTF-8 or UTF-16. Line boundaries are not normalized. Note that a byte order mark character is not passed to the default handler. There are no guarantees about how characters are divided between calls to the default handler: for example, a comment might be split between multiple calls. */ typedef void (*XML_DefaultHandler)(void *userData, const XML_Char *s, int len); /* This is called for the start of the DOCTYPE declaration, before any DTD or internal subset is parsed. */ typedef void (*XML_StartDoctypeDeclHandler)(void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset); /* This is called for the start of the DOCTYPE declaration when the closing > is encountered, but after processing any external subset. */ typedef void (*XML_EndDoctypeDeclHandler)(void *userData); /* This is called for entity declarations. The is_parameter_entity argument will be non-zero if the entity is a parameter entity, zero otherwise. For internal entities (), value will be non-NULL and systemId, publicID, and notationName will be NULL. The value string is NOT nul-terminated; the length is provided in the value_length argument. Since it is legal to have zero-length values, do not use this argument to test for internal entities. For external entities, value will be NULL and systemId will be non-NULL. The publicId argument will be NULL unless a public identifier was provided. The notationName argument will have a non-NULL value only for unparsed entity declarations. Note that is_parameter_entity can't be changed to XML_Bool, since that would break binary compatibility. */ typedef void (*XML_EntityDeclHandler) (void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); XMLPARSEAPI(void) XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler); /* OBSOLETE -- OBSOLETE -- OBSOLETE This handler has been superceded by the EntityDeclHandler above. It is provided here for backward compatibility. This is called for a declaration of an unparsed (NDATA) entity. The base argument is whatever was set by XML_SetBase. The entityName, systemId and notationName arguments will never be NULL. The other arguments may be. */ typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, const XML_Char *entityName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); /* This is called for a declaration of notation. The base argument is whatever was set by XML_SetBase. The notationName will never be NULL. The other arguments can be. */ typedef void (*XML_NotationDeclHandler)(void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); /* When namespace processing is enabled, these are called once for each namespace declaration. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers. For an xmlns attribute, prefix will be NULL. For an xmlns="" attribute, uri will be NULL. */ typedef void (*XML_StartNamespaceDeclHandler)(void *userData, const XML_Char *prefix, const XML_Char *uri); typedef void (*XML_EndNamespaceDeclHandler)(void *userData, const XML_Char *prefix); /* This is called if the document is not standalone, that is, it has an external subset or a reference to a parameter entity, but does not have standalone="yes". If this handler returns XML_STATUS_ERROR, then processing will not continue, and the parser will return a XML_ERROR_NOT_STANDALONE error. If parameter entity parsing is enabled, then in addition to the conditions above this handler will only be called if the referenced entity was actually read. */ typedef int (*XML_NotStandaloneHandler)(void *userData); /* This is called for a reference to an external parsed general entity. The referenced entity is not automatically parsed. The application can parse it immediately or later using XML_ExternalEntityParserCreate. The parser argument is the parser parsing the entity containing the reference; it can be passed as the parser argument to XML_ExternalEntityParserCreate. The systemId argument is the system identifier as specified in the entity declaration; it will not be NULL. The base argument is the system identifier that should be used as the base for resolving systemId if systemId was relative; this is set by XML_SetBase; it may be NULL. The publicId argument is the public identifier as specified in the entity declaration, or NULL if none was specified; the whitespace in the public identifier will have been normalized as required by the XML spec. The context argument specifies the parsing context in the format expected by the context argument to XML_ExternalEntityParserCreate; context is valid only until the handler returns, so if the referenced entity is to be parsed later, it must be copied. context is NULL only when the entity is a parameter entity. The handler should return XML_STATUS_ERROR if processing should not continue because of a fatal error in the handling of the external entity. In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING error. Note that unlike other handlers the first argument is the parser, not userData. */ typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); /* This is called in two situations: 1) An entity reference is encountered for which no declaration has been read *and* this is not an error. 2) An internal entity reference is read, but not expanded, because XML_SetDefaultHandler has been called. Note: skipped parameter entities in declarations and skipped general entities in attribute values cannot be reported, because the event would be out of sync with the reporting of the declarations or attribute values */ typedef void (*XML_SkippedEntityHandler)(void *userData, const XML_Char *entityName, int is_parameter_entity); /* This structure is filled in by the XML_UnknownEncodingHandler to provide information to the parser about encodings that are unknown to the parser. The map[b] member gives information about byte sequences whose first byte is b. If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. If map[b] is -1, then the byte sequence is malformed. If map[b] is -n, where n >= 2, then b is the first byte of an n-byte sequence that encodes a single Unicode scalar value. The data member will be passed as the first argument to the convert function. The convert function is used to convert multibyte sequences; s will point to a n-byte sequence where map[(unsigned char)*s] == -n. The convert function must return the Unicode scalar value represented by this byte sequence or -1 if the byte sequence is malformed. The convert function may be NULL if the encoding is a single-byte encoding, that is if map[b] >= -1 for all bytes b. When the parser is finished with the encoding, then if release is not NULL, it will call release passing it the data member; once release has been called, the convert function will not be called again. Expat places certain restrictions on the encodings that are supported using this mechanism. 1. Every ASCII character that can appear in a well-formed XML document, other than the characters $@\^`{}~ must be represented by a single byte, and that byte must be the same byte that represents that character in ASCII. 2. No character may require more than 4 bytes to encode. 3. All characters encoded must have Unicode scalar values <= 0xFFFF, (i.e., characters that would be encoded by surrogates in UTF-16 are not allowed). Note that this restriction doesn't apply to the built-in support for UTF-8 and UTF-16. 4. No Unicode character may be encoded by more than one distinct sequence of bytes. */ typedef struct { int map[256]; void *data; int (*convert)(void *data, const char *s); void (*release)(void *data); } XML_Encoding; /* This is called for an encoding that is unknown to the parser. The encodingHandlerData argument is that which was passed as the second argument to XML_SetUnknownEncodingHandler. The name argument gives the name of the encoding as specified in the encoding declaration. If the callback can provide information about the encoding, it must fill in the XML_Encoding structure, and return XML_STATUS_OK. Otherwise it must return XML_STATUS_ERROR. If info does not describe a suitable encoding, then the parser will return an XML_UNKNOWN_ENCODING error. */ typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); XMLPARSEAPI(void) XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end); XMLPARSEAPI(void) XML_SetStartElementHandler(XML_Parser, XML_StartElementHandler); XMLPARSEAPI(void) XML_SetEndElementHandler(XML_Parser, XML_EndElementHandler); XMLPARSEAPI(void) XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler); XMLPARSEAPI(void) XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler); XMLPARSEAPI(void) XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler); XMLPARSEAPI(void) XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end); XMLPARSEAPI(void) XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start); XMLPARSEAPI(void) XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end); /* This sets the default handler and also inhibits expansion of internal entities. These entity references will be passed to the default handler, or to the skipped entity handler, if one is set. */ XMLPARSEAPI(void) XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler); /* This sets the default handler but does not inhibit expansion of internal entities. The entity reference will not be passed to the default handler. */ XMLPARSEAPI(void) XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler); XMLPARSEAPI(void) XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end); XMLPARSEAPI(void) XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start); XMLPARSEAPI(void) XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end); XMLPARSEAPI(void) XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler); XMLPARSEAPI(void) XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler); XMLPARSEAPI(void) XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end); XMLPARSEAPI(void) XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start); XMLPARSEAPI(void) XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end); XMLPARSEAPI(void) XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler); XMLPARSEAPI(void) XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler); /* If a non-NULL value for arg is specified here, then it will be passed as the first argument to the external entity ref handler instead of the parser object. */ XMLPARSEAPI(void) XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); XMLPARSEAPI(void) XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler); XMLPARSEAPI(void) XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *encodingHandlerData); /* This can be called within a handler for a start element, end element, processing instruction or character data. It causes the corresponding markup to be passed to the default handler. */ XMLPARSEAPI(void) XML_DefaultCurrent(XML_Parser parser); /* If do_nst is non-zero, and namespace processing is in effect, and a name has a prefix (i.e. an explicit namespace qualifier) then that name is returned as a triplet in a single string separated by the separator character specified when the parser was created: URI + sep + local_name + sep + prefix. If do_nst is zero, then namespace information is returned in the default manner (URI + sep + local_name) whether or not the name has a prefix. Note: Calling XML_SetReturnNSTriplet after XML_Parse or XML_ParseBuffer has no effect. */ XMLPARSEAPI(void) XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); /* This value is passed as the userData argument to callbacks. */ XMLPARSEAPI(void) XML_SetUserData(XML_Parser parser, void *userData); /* Returns the last value set by XML_SetUserData or NULL. */ #define XML_GetUserData(parser) (*(void **)(parser)) /* This is equivalent to supplying an encoding argument to XML_ParserCreate. On success XML_SetEncoding returns non-zero, zero otherwise. Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer has no effect and returns XML_STATUS_ERROR. */ XMLPARSEAPI(enum XML_Status) XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); /* If this function is called, then the parser will be passed as the first argument to callbacks instead of userData. The userData will still be accessible using XML_GetUserData. */ XMLPARSEAPI(void) XML_UseParserAsHandlerArg(XML_Parser parser); /* If useDTD == XML_TRUE is passed to this function, then the parser will assume that there is an external subset, even if none is specified in the document. In such a case the parser will call the externalEntityRefHandler with a value of NULL for the systemId argument (the publicId and context arguments will be NULL as well). Note: If this function is called, then this must be done before the first call to XML_Parse or XML_ParseBuffer, since it will have no effect after that. Returns XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING. Note: If the document does not have a DOCTYPE declaration at all, then startDoctypeDeclHandler and endDoctypeDeclHandler will not be called, despite an external subset being parsed. Note: If XML_DTD is not defined when Expat is compiled, returns XML_ERROR_FEATURE_REQUIRES_XML_DTD. */ XMLPARSEAPI(enum XML_Error) XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); /* Sets the base to be used for resolving relative URIs in system identifiers in declarations. Resolving relative identifiers is left to the application: this value will be passed through as the base argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base argument will be copied. Returns XML_STATUS_ERROR if out of memory, XML_STATUS_OK otherwise. */ XMLPARSEAPI(enum XML_Status) XML_SetBase(XML_Parser parser, const XML_Char *base); XMLPARSEAPI(const XML_Char *) XML_GetBase(XML_Parser parser); /* Returns the number of the attribute/value pairs passed in last call to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ XMLPARSEAPI(int) XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to XML_StartElementHandler, or -1 if there is no ID attribute. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); /* Parses some input. Returns XML_STATUS_ERROR if a fatal error is detected. The last call to XML_Parse must have isFinal true; len may be zero for this call (or any other). The XML_Status enum gives the possible return values for the XML_Parse and XML_ParseBuffer functions. Though the return values for these functions has always been described as a Boolean value, the implementation, at least for the 1.95.x series, has always returned exactly one of these values. The preprocessor #defines are included so this stanza can be added to code that still needs to support older versions of Expat 1.95.x: #ifndef XML_STATUS_OK #define XML_STATUS_OK 1 #define XML_STATUS_ERROR 0 #endif Otherwise, the #define hackery is quite ugly and would have been dropped. */ enum XML_Status { XML_STATUS_ERROR = 0, #define XML_STATUS_ERROR XML_STATUS_ERROR XML_STATUS_OK = 1 #define XML_STATUS_OK XML_STATUS_OK }; XMLPARSEAPI(enum XML_Status) XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); XMLPARSEAPI(void *) XML_GetBuffer(XML_Parser parser, int len); XMLPARSEAPI(enum XML_Status) XML_ParseBuffer(XML_Parser parser, int len, int isFinal); /* Creates an XML_Parser object that can parse an external general entity; context is a '\0'-terminated string specifying the parse context; encoding is a '\0'-terminated string giving the name of the externally specified encoding, or NULL if there is no externally specified encoding. The context string consists of a sequence of tokens separated by formfeeds (\f); a token consisting of a name specifies that the general entity of the name is open; a token of the form prefix=uri specifies the namespace for a particular prefix; a token of the form =uri specifies the default namespace. This can be called at any point after the first call to an ExternalEntityRefHandler so longer as the parser has not yet been freed. The new parser is completely independent and may safely be used in a separate thread. The handlers and userData are initialized from the parser argument. Returns NULL if out of memory. Otherwise returns a new XML_Parser object. */ XMLPARSEAPI(XML_Parser) XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *context, const XML_Char *encoding); enum XML_ParamEntityParsing { XML_PARAM_ENTITY_PARSING_NEVER, XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, XML_PARAM_ENTITY_PARSING_ALWAYS }; /* Controls parsing of parameter entities (including the external DTD subset). If parsing of parameter entities is enabled, then references to external parameter entities (including the external DTD subset) will be passed to the handler set with XML_SetExternalEntityRefHandler. The context passed will be 0. Unlike external general entities, external parameter entities can only be parsed synchronously. If the external parameter entity is to be parsed, it must be parsed during the call to the external entity ref handler: the complete sequence of XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during this call. After XML_ExternalEntityParserCreate has been called to create the parser for the external parameter entity (context must be 0 for this call), it is illegal to make any calls on the old parser until XML_ParserFree has been called on the newly created parser. If the library has been compiled without support for parameter entity parsing (ie without XML_DTD being defined), then XML_SetParamEntityParsing will return 0 if parsing of parameter entities is requested; otherwise it will return non-zero. Note: If XML_SetParamEntityParsing is called after XML_Parse or XML_ParseBuffer, then it has no effect and will always return 0. */ XMLPARSEAPI(int) XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing parsing); /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then XML_GetErrorCode returns information about the error. */ XMLPARSEAPI(enum XML_Error) XML_GetErrorCode(XML_Parser parser); /* These functions return information about the current parse location. They may be called from any callback called to report some parse event; in this case the location is the location of the first of the sequence of characters that generated the event. They may also be called after returning from a call to XML_Parse or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then the location is the location of the character at which the error was detected; otherwise the location is the location of the last parse event, as described above. */ XMLPARSEAPI(int) XML_GetCurrentLineNumber(XML_Parser parser); XMLPARSEAPI(int) XML_GetCurrentColumnNumber(XML_Parser parser); XMLPARSEAPI(long) XML_GetCurrentByteIndex(XML_Parser parser); /* Return the number of bytes in the current event. Returns 0 if the event is in an internal entity. */ XMLPARSEAPI(int) XML_GetCurrentByteCount(XML_Parser parser); /* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets the integer pointed to by offset to the offset within this buffer of the current parse position, and sets the integer pointed to by size to the size of this buffer (the number of input bytes). Otherwise returns a NULL pointer. Also returns a NULL pointer if a parse isn't active. NOTE: The character pointer returned should not be used outside the handler that makes the call. */ XMLPARSEAPI(const char *) XML_GetInputContext(XML_Parser parser, int *offset, int *size); /* For backwards compatibility with previous versions. */ #define XML_GetErrorLineNumber XML_GetCurrentLineNumber #define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber #define XML_GetErrorByteIndex XML_GetCurrentByteIndex /* Frees the content model passed to the element declaration handler */ XMLPARSEAPI(void) XML_FreeContentModel(XML_Parser parser, XML_Content *model); /* Exposing the memory handling functions used in Expat */ XMLPARSEAPI(void *) XML_MemMalloc(XML_Parser parser, size_t size); XMLPARSEAPI(void *) XML_MemRealloc(XML_Parser parser, void *ptr, size_t size); XMLPARSEAPI(void) XML_MemFree(XML_Parser parser, void *ptr); /* Frees memory used by the parser. */ XMLPARSEAPI(void) XML_ParserFree(XML_Parser parser); /* Returns a string describing the error. */ XMLPARSEAPI(const XML_LChar *) XML_ErrorString(enum XML_Error code); /* Return a string containing the version number of this expat */ XMLPARSEAPI(const XML_LChar *) XML_ExpatVersion(void); typedef struct { int major; int minor; int micro; } XML_Expat_Version; /* Return an XML_Expat_Version structure containing numeric version number information for this version of expat. */ XMLPARSEAPI(XML_Expat_Version) XML_ExpatVersionInfo(void); /* Added in Expat 1.95.5. */ enum XML_FeatureEnum { XML_FEATURE_END = 0, XML_FEATURE_UNICODE, XML_FEATURE_UNICODE_WCHAR_T, XML_FEATURE_DTD, XML_FEATURE_CONTEXT_BYTES, XML_FEATURE_MIN_SIZE, XML_FEATURE_SIZEOF_XML_CHAR, XML_FEATURE_SIZEOF_XML_LCHAR /* Additional features must be added to the end of this enum. */ }; typedef struct { enum XML_FeatureEnum feature; const XML_LChar *name; long int value; } XML_Feature; XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); /* Expat follows the GNU/Linux convention of odd number minor version for beta/development releases and even number minor version for stable releases. Micro is bumped with each release, and set to 0 with each change to major or minor version. */ #define XML_MAJOR_VERSION 1 #define XML_MINOR_VERSION 95 #define XML_MICRO_VERSION 6 #ifdef __cplusplus } #endif #endif /* not XmlParse_INCLUDED */ PyXML-0.8.2/extensions/expat/lib/expat.h.in0100644000076400001440000006753707335151677017735 0ustar martinusers/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #ifndef XmlParse_INCLUDED #define XmlParse_INCLUDED 1 #include #ifndef XMLPARSEAPI # if defined(__declspec) && !defined(__BEOS__) # define XMLPARSEAPI(type) __declspec(dllimport) type __cdecl # else # define XMLPARSEAPI(type) type # endif #endif /* not defined XMLPARSEAPI */ #ifdef __cplusplus extern "C" { #endif typedef void *XML_Parser; /* Information is UTF-8 encoded. */ typedef char XML_Char; typedef char XML_LChar; enum XML_Content_Type { XML_CTYPE_EMPTY = 1, XML_CTYPE_ANY, XML_CTYPE_MIXED, XML_CTYPE_NAME, XML_CTYPE_CHOICE, XML_CTYPE_SEQ }; enum XML_Content_Quant { XML_CQUANT_NONE, XML_CQUANT_OPT, XML_CQUANT_REP, XML_CQUANT_PLUS }; /* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be XML_CQUANT_NONE, and the other fields will be zero or NULL. If type == XML_CTYPE_MIXED, then quant will be NONE or REP and numchildren will contain number of elements that may be mixed in and children point to an array of XML_Content cells that will be all of XML_CTYPE_NAME type with no quantification. If type == XML_CTYPE_NAME, then the name points to the name, and the numchildren field will be zero and children will be NULL. The quant fields indicates any quantifiers placed on the name. CHOICE and SEQ will have name NULL, the number of children in numchildren and children will point, recursively, to an array of XML_Content cells. The EMPTY, ANY, and MIXED types will only occur at top level. */ typedef struct XML_cp XML_Content; struct XML_cp { enum XML_Content_Type type; enum XML_Content_Quant quant; XML_Char * name; unsigned int numchildren; XML_Content * children; }; /* This is called for an element declaration. See above for description of the model argument. It's the caller's responsibility to free model when finished with it. */ typedef void (*XML_ElementDeclHandler) (void *userData, const XML_Char *name, XML_Content *model); XMLPARSEAPI(void) XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl); /* The Attlist declaration handler is called for *each* attribute. So a single Attlist declaration with multiple attributes declared will generate multiple calls to this handler. The "default" parameter may be NULL in the case of the "#IMPLIED" or "#REQUIRED" keyword. The "isrequired" parameter will be true and the default value will be NULL in the case of "#REQUIRED". If "isrequired" is true and default is non-NULL, then this is a "#FIXED" default. */ typedef void (*XML_AttlistDeclHandler) (void *userData, const XML_Char *elname, const XML_Char *attname, const XML_Char *att_type, const XML_Char *dflt, int isrequired); XMLPARSEAPI(void) XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl); /* The XML declaration handler is called for *both* XML declarations and text declarations. The way to distinguish is that the version parameter will be null for text declarations. The encoding parameter may be null for XML declarations. The standalone parameter will be -1, 0, or 1 indicating respectively that there was no standalone parameter in the declaration, that it was given as no, or that it was given as yes. */ typedef void (*XML_XmlDeclHandler) (void *userData, const XML_Char *version, const XML_Char *encoding, int standalone); XMLPARSEAPI(void) XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler xmldecl); typedef struct { void *(*malloc_fcn)(size_t size); void *(*realloc_fcn)(void *ptr, size_t size); void (*free_fcn)(void *ptr); } XML_Memory_Handling_Suite; /* Constructs a new parser; encoding is the encoding specified by the external protocol or null if there is none specified. */ XMLPARSEAPI(XML_Parser) XML_ParserCreate(const XML_Char *encoding); /* Constructs a new parser and namespace processor. Element type names and attribute names that belong to a namespace will be expanded; unprefixed attribute names are never expanded; unprefixed element type names are expanded only if there is a default namespace. The expanded name is the concatenation of the namespace URI, the namespace separator character, and the local part of the name. If the namespace separator is '\0' then the namespace URI and the local part will be concatenated without any separator. When a namespace is not declared, the name and prefix will be passed through without expansion. */ XMLPARSEAPI(XML_Parser) XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); /* Constructs a new parser using the memory management suit referred to by memsuite. If memsuite is NULL, then use the standard library memory suite. If namespaceSeparator is non-NULL it creates a parser with namespace processing as described above. The character pointed at will serve as the namespace separator. All further memory operations used for the created parser will come from the given suite. */ XMLPARSEAPI(XML_Parser) XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *memsuite, const XML_Char *namespaceSeparator); /* atts is array of name/value pairs, terminated by 0; names and values are 0 terminated. */ typedef void (*XML_StartElementHandler)(void *userData, const XML_Char *name, const XML_Char **atts); typedef void (*XML_EndElementHandler)(void *userData, const XML_Char *name); /* s is not 0 terminated. */ typedef void (*XML_CharacterDataHandler)(void *userData, const XML_Char *s, int len); /* target and data are 0 terminated */ typedef void (*XML_ProcessingInstructionHandler)(void *userData, const XML_Char *target, const XML_Char *data); /* data is 0 terminated */ typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); typedef void (*XML_StartCdataSectionHandler)(void *userData); typedef void (*XML_EndCdataSectionHandler)(void *userData); /* This is called for any characters in the XML document for which there is no applicable handler. This includes both characters that are part of markup which is of a kind that is not reported (comments, markup declarations), or characters that are part of a construct which could be reported but for which no handler has been supplied. The characters are passed exactly as they were in the XML document except that they will be encoded in UTF-8. Line boundaries are not normalized. Note that a byte order mark character is not passed to the default handler. There are no guarantees about how characters are divided between calls to the default handler: for example, a comment might be split between multiple calls. */ typedef void (*XML_DefaultHandler)(void *userData, const XML_Char *s, int len); /* This is called for the start of the DOCTYPE declaration, before any DTD or internal subset is parsed. */ typedef void (*XML_StartDoctypeDeclHandler)(void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset); /* This is called for the start of the DOCTYPE declaration when the closing > is encountered, but after processing any external subset. */ typedef void (*XML_EndDoctypeDeclHandler)(void *userData); /* This is called for entity declarations. The is_parameter_entity argument will be non-zero if the entity is a parameter entity, zero otherwise. For internal entities (), value will be non-null and systemId, publicID, and notationName will be null. The value string is NOT null terminated; the length is provided in the value_length argument. Since it is legal to have zero-length values, do not use this argument to test for internal entities. For external entities, value will be null and systemId will be non-null. The publicId argument will be null unless a public identifier was provided. The notationName argument will have a non-null value only for unparsed entity declarations. */ typedef void (*XML_EntityDeclHandler) (void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); XMLPARSEAPI(void) XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler); /* OBSOLETE -- OBSOLETE -- OBSOLETE This handler has been superceded by the EntityDeclHandler above. It is provided here for backward compatibility. This is called for a declaration of an unparsed (NDATA) entity. The base argument is whatever was set by XML_SetBase. The entityName, systemId and notationName arguments will never be null. The other arguments may be. */ typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, const XML_Char *entityName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); /* This is called for a declaration of notation. The base argument is whatever was set by XML_SetBase. The notationName will never be null. The other arguments can be. */ typedef void (*XML_NotationDeclHandler)(void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); /* When namespace processing is enabled, these are called once for each namespace declaration. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers. For an xmlns attribute, prefix will be null. For an xmlns="" attribute, uri will be null. */ typedef void (*XML_StartNamespaceDeclHandler)(void *userData, const XML_Char *prefix, const XML_Char *uri); typedef void (*XML_EndNamespaceDeclHandler)(void *userData, const XML_Char *prefix); /* This is called if the document is not standalone (it has an external subset or a reference to a parameter entity, but does not have standalone="yes"). If this handler returns 0, then processing will not continue, and the parser will return a XML_ERROR_NOT_STANDALONE error. */ typedef int (*XML_NotStandaloneHandler)(void *userData); /* This is called for a reference to an external parsed general entity. The referenced entity is not automatically parsed. The application can parse it immediately or later using XML_ExternalEntityParserCreate. The parser argument is the parser parsing the entity containing the reference; it can be passed as the parser argument to XML_ExternalEntityParserCreate. The systemId argument is the system identifier as specified in the entity declaration; it will not be null. The base argument is the system identifier that should be used as the base for resolving systemId if systemId was relative; this is set by XML_SetBase; it may be null. The publicId argument is the public identifier as specified in the entity declaration, or null if none was specified; the whitespace in the public identifier will have been normalized as required by the XML spec. The context argument specifies the parsing context in the format expected by the context argument to XML_ExternalEntityParserCreate; context is valid only until the handler returns, so if the referenced entity is to be parsed later, it must be copied. The handler should return 0 if processing should not continue because of a fatal error in the handling of the external entity. In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING error. Note that unlike other handlers the first argument is the parser, not userData. */ typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); /* This structure is filled in by the XML_UnknownEncodingHandler to provide information to the parser about encodings that are unknown to the parser. The map[b] member gives information about byte sequences whose first byte is b. If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. If map[b] is -1, then the byte sequence is malformed. If map[b] is -n, where n >= 2, then b is the first byte of an n-byte sequence that encodes a single Unicode scalar value. The data member will be passed as the first argument to the convert function. The convert function is used to convert multibyte sequences; s will point to a n-byte sequence where map[(unsigned char)*s] == -n. The convert function must return the Unicode scalar value represented by this byte sequence or -1 if the byte sequence is malformed. The convert function may be null if the encoding is a single-byte encoding, that is if map[b] >= -1 for all bytes b. When the parser is finished with the encoding, then if release is not null, it will call release passing it the data member; once release has been called, the convert function will not be called again. Expat places certain restrictions on the encodings that are supported using this mechanism. 1. Every ASCII character that can appear in a well-formed XML document, other than the characters $@\^`{}~ must be represented by a single byte, and that byte must be the same byte that represents that character in ASCII. 2. No character may require more than 4 bytes to encode. 3. All characters encoded must have Unicode scalar values <= 0xFFFF, (i.e., characters that would be encoded by surrogates in UTF-16 are not allowed). Note that this restriction doesn't apply to the built-in support for UTF-8 and UTF-16. 4. No Unicode character may be encoded by more than one distinct sequence of bytes. */ typedef struct { int map[256]; void *data; int (*convert)(void *data, const char *s); void (*release)(void *data); } XML_Encoding; /* This is called for an encoding that is unknown to the parser. The encodingHandlerData argument is that which was passed as the second argument to XML_SetUnknownEncodingHandler. The name argument gives the name of the encoding as specified in the encoding declaration. If the callback can provide information about the encoding, it must fill in the XML_Encoding structure, and return 1. Otherwise it must return 0. If info does not describe a suitable encoding, then the parser will return an XML_UNKNOWN_ENCODING error. */ typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); XMLPARSEAPI(void) XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end); XMLPARSEAPI(void) XML_SetStartElementHandler(XML_Parser, XML_StartElementHandler); XMLPARSEAPI(void) XML_SetEndElementHandler(XML_Parser, XML_EndElementHandler); XMLPARSEAPI(void) XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler); XMLPARSEAPI(void) XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler); XMLPARSEAPI(void) XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler); XMLPARSEAPI(void) XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end); XMLPARSEAPI(void) XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start); XMLPARSEAPI(void) XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end); /* This sets the default handler and also inhibits expansion of internal entities. The entity reference will be passed to the default handler. */ XMLPARSEAPI(void) XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler); /* This sets the default handler but does not inhibit expansion of internal entities. The entity reference will not be passed to the default handler. */ XMLPARSEAPI(void) XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler); XMLPARSEAPI(void) XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end); XMLPARSEAPI(void) XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start); XMLPARSEAPI(void) XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end); XMLPARSEAPI(void) XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler); XMLPARSEAPI(void) XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler); XMLPARSEAPI(void) XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end); XMLPARSEAPI(void) XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start); XMLPARSEAPI(void) XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end); XMLPARSEAPI(void) XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler); XMLPARSEAPI(void) XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler); /* If a non-null value for arg is specified here, then it will be passed as the first argument to the external entity ref handler instead of the parser object. */ XMLPARSEAPI(void) XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); XMLPARSEAPI(void) XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *encodingHandlerData); /* This can be called within a handler for a start element, end element, processing instruction or character data. It causes the corresponding markup to be passed to the default handler. */ XMLPARSEAPI(void) XML_DefaultCurrent(XML_Parser parser); /* If do_nst is non-zero, and namespace processing is in effect, and a name has a prefix (i.e. an explicit namespace qualifier) then that name is returned as a triplet in a single string separated by the separator character specified when the parser was created: URI + sep + local_name + sep + prefix. If do_nst is zero, then namespace information is returned in the default manner (URI + sep + local_name) whether or not the names has a prefix. */ XMLPARSEAPI(void) XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); /* This value is passed as the userData argument to callbacks. */ XMLPARSEAPI(void) XML_SetUserData(XML_Parser parser, void *userData); /* Returns the last value set by XML_SetUserData or null. */ #define XML_GetUserData(parser) (*(void **)(parser)) /* This is equivalent to supplying an encoding argument to XML_ParserCreate. It must not be called after XML_Parse or XML_ParseBuffer. */ XMLPARSEAPI(int) XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); /* If this function is called, then the parser will be passed as the first argument to callbacks instead of userData. The userData will still be accessible using XML_GetUserData. */ XMLPARSEAPI(void) XML_UseParserAsHandlerArg(XML_Parser parser); /* Sets the base to be used for resolving relative URIs in system identifiers in declarations. Resolving relative identifiers is left to the application: this value will be passed through as the base argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base argument will be copied. Returns zero if out of memory, non-zero otherwise. */ XMLPARSEAPI(int) XML_SetBase(XML_Parser parser, const XML_Char *base); XMLPARSEAPI(const XML_Char *) XML_GetBase(XML_Parser parser); /* Returns the number of the attribute/value pairs passed in last call to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ XMLPARSEAPI(int) XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to XML_StartElementHandler, or -1 if there is no ID attribute. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); /* Parses some input. Returns 0 if a fatal error is detected. The last call to XML_Parse must have isFinal true; len may be zero for this call (or any other). */ XMLPARSEAPI(int) XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); XMLPARSEAPI(void *) XML_GetBuffer(XML_Parser parser, int len); XMLPARSEAPI(int) XML_ParseBuffer(XML_Parser parser, int len, int isFinal); /* Creates an XML_Parser object that can parse an external general entity; context is a '\0'-terminated string specifying the parse context; encoding is a '\0'-terminated string giving the name of the externally specified encoding, or null if there is no externally specified encoding. The context string consists of a sequence of tokens separated by formfeeds (\f); a token consisting of a name specifies that the general entity of the name is open; a token of the form prefix=uri specifies the namespace for a particular prefix; a token of the form =uri specifies the default namespace. This can be called at any point after the first call to an ExternalEntityRefHandler so longer as the parser has not yet been freed. The new parser is completely independent and may safely be used in a separate thread. The handlers and userData are initialized from the parser argument. Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */ XMLPARSEAPI(XML_Parser) XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *context, const XML_Char *encoding); enum XML_ParamEntityParsing { XML_PARAM_ENTITY_PARSING_NEVER, XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, XML_PARAM_ENTITY_PARSING_ALWAYS }; /* Controls parsing of parameter entities (including the external DTD subset). If parsing of parameter entities is enabled, then references to external parameter entities (including the external DTD subset) will be passed to the handler set with XML_SetExternalEntityRefHandler. The context passed will be 0. Unlike external general entities, external parameter entities can only be parsed synchronously. If the external parameter entity is to be parsed, it must be parsed during the call to the external entity ref handler: the complete sequence of XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during this call. After XML_ExternalEntityParserCreate has been called to create the parser for the external parameter entity (context must be 0 for this call), it is illegal to make any calls on the old parser until XML_ParserFree has been called on the newly created parser. If the library has been compiled without support for parameter entity parsing (ie without XML_DTD being defined), then XML_SetParamEntityParsing will return 0 if parsing of parameter entities is requested; otherwise it will return non-zero. */ XMLPARSEAPI(int) XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing parsing); enum XML_Error { XML_ERROR_NONE, XML_ERROR_NO_MEMORY, XML_ERROR_SYNTAX, XML_ERROR_NO_ELEMENTS, XML_ERROR_INVALID_TOKEN, XML_ERROR_UNCLOSED_TOKEN, XML_ERROR_PARTIAL_CHAR, XML_ERROR_TAG_MISMATCH, XML_ERROR_DUPLICATE_ATTRIBUTE, XML_ERROR_JUNK_AFTER_DOC_ELEMENT, XML_ERROR_PARAM_ENTITY_REF, XML_ERROR_UNDEFINED_ENTITY, XML_ERROR_RECURSIVE_ENTITY_REF, XML_ERROR_ASYNC_ENTITY, XML_ERROR_BAD_CHAR_REF, XML_ERROR_BINARY_ENTITY_REF, XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, XML_ERROR_MISPLACED_XML_PI, XML_ERROR_UNKNOWN_ENCODING, XML_ERROR_INCORRECT_ENCODING, XML_ERROR_UNCLOSED_CDATA_SECTION, XML_ERROR_EXTERNAL_ENTITY_HANDLING, XML_ERROR_NOT_STANDALONE, XML_ERROR_UNEXPECTED_STATE }; /* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode returns information about the error. */ XMLPARSEAPI(enum XML_Error) XML_GetErrorCode(XML_Parser parser); /* These functions return information about the current parse location. They may be called when XML_Parse or XML_ParseBuffer return 0; in this case the location is the location of the character at which the error was detected. They may also be called from any other callback called to report some parse event; in this the location is the location of the first of the sequence of characters that generated the event. */ XMLPARSEAPI(int) XML_GetCurrentLineNumber(XML_Parser parser); XMLPARSEAPI(int) XML_GetCurrentColumnNumber(XML_Parser parser); XMLPARSEAPI(long) XML_GetCurrentByteIndex(XML_Parser parser); /* Return the number of bytes in the current event. Returns 0 if the event is in an internal entity. */ XMLPARSEAPI(int) XML_GetCurrentByteCount(XML_Parser parser); /* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets the integer pointed to by offset to the offset within this buffer of the current parse position, and sets the integer pointed to by size to the size of this buffer (the number of input bytes). Otherwise returns a null pointer. Also returns a null pointer if a parse isn't active. NOTE: The character pointer returned should not be used outside the handler that makes the call. */ XMLPARSEAPI(const char *) XML_GetInputContext(XML_Parser parser, int *offset, int *size); /* For backwards compatibility with previous versions. */ #define XML_GetErrorLineNumber XML_GetCurrentLineNumber #define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber #define XML_GetErrorByteIndex XML_GetCurrentByteIndex /* Frees memory used by the parser. */ XMLPARSEAPI(void) XML_ParserFree(XML_Parser parser); /* Returns a string describing the error. */ XMLPARSEAPI(const XML_LChar *) XML_ErrorString(int code); /* Return a string containing the version number of this expat */ XMLPARSEAPI(const XML_LChar *) XML_ExpatVersion(void); typedef struct { int major; int minor; int micro; } XML_Expat_Version; /* Return an XML_Expat_Version structure containing numeric version number information for this version of expat */ XMLPARSEAPI(XML_Expat_Version) XML_ExpatVersionInfo(void); #define XML_MAJOR_VERSION @EXPAT_MAJOR_VERSION@ #define XML_MINOR_VERSION @EXPAT_MINOR_VERSION@ #define XML_MICRO_VERSION @EXPAT_EDIT@ #ifdef __cplusplus } #endif #endif /* not XmlParse_INCLUDED */ PyXML-0.8.2/extensions/expat/lib/iasciitab.h0100644000076400001440000000344607517567466020135 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ /* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, /* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, PyXML-0.8.2/extensions/expat/lib/internal.h0100644000076400001440000000351607614471161017777 0ustar martinusers/* internal.h Internal definitions used by Expat. This is not needed to compile client code. The following calling convention macros are defined for frequently called functions: FASTCALL - Used for those internal functions that have a simple body and a low number of arguments and local variables. PTRCALL - Used for functions called though function pointers. PTRFASTCALL - Like PTRCALL, but for low number of arguments. inline - Used for selected internal functions for which inlining may improve performance on some platforms. Note: Use of these macros is based on judgement, not hard rules, and therefore subject to change. */ #if defined(__GNUC__) /* Instability reported with egcs on a RedHat Linux 7.3. Let's comment it out: #define FASTCALL __attribute__((stdcall, regparm(3))) and let's try this: */ #define FASTCALL __attribute__((regparm(3))) #define PTRCALL #define PTRFASTCALL __attribute__((regparm(3))) #elif defined(WIN32) /* Using __fastcall seems to have an unexpected negative effect under MS VC++, especially for function pointers, so we won't use it for now on that platform. It may be reconsidered for a future release if it can be made more effective. Likely reason: __fastcall on Windows is like stdcall, therefore the compiler cannot perform stack optimizations for call clusters. */ #define FASTCALL #define PTRCALL #define PTRFASTCALL #endif #ifndef FASTCALL #define FASTCALL #endif #ifndef PTRCALL #define PTRCALL #endif #ifndef PTRFASTCALL #define PTRFASTCALL #endif #ifndef XML_MIN_SIZE #if !defined(__cplusplus) && !defined(inline) #ifdef __GNUC__ #define inline __inline #endif /* __GNUC__ */ #endif #endif /* XML_MIN_SIZE */ #ifdef __cplusplus #define inline inline #else #ifndef inline #define inline #endif #endif PyXML-0.8.2/extensions/expat/lib/latin1tab.h0100644000076400001440000000342507517567466020061 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ /* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, /* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, /* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, /* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, PyXML-0.8.2/extensions/expat/lib/macconfig.h0100644000076400001440000000522207513647337020115 0ustar martinusers/*================================================================ ** Copyright 2000, Clark Cooper ** All rights reserved. ** ** This is free software. You are permitted to copy, distribute, or modify ** it under the terms of the MIT/X license (contained in the COPYING file ** with this distribution.) ** */ #ifndef MACCONFIG_H #define MACCONFIG_H /* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ #define BYTEORDER 4321 /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #define HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS /* whether byteorder is bigendian */ #define WORDS_BIGENDIAN /* Define to specify how much context to retain around the current parse point. */ #undef XML_CONTEXT_BYTES /* Define to make parameter entity parsing functionality available. */ #define XML_DTD /* Define to make XML Namespaces functionality available. */ #define XML_NS /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `long' if does not define. */ #define off_t long /* Define to `unsigned' if does not define. */ #undef size_t #endif /* ifndef MACCONFIG_H */ PyXML-0.8.2/extensions/expat/lib/nametab.h0100644000076400001440000001561207335151677017601 0ustar martinusersstatic const unsigned namingBitmap[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, 0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, 0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, 0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, 0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, 0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, 0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, 0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, 0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, 0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, 0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, 0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, 0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, 0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, 0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, 0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, 0x40000000, 0xF580C900, 0x00000007, 0x02010800, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, 0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, 0x00000000, 0x00004C40, 0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, 0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, 0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, 0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, 0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, 0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, 0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, 0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, 0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, 0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, 0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, 0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, 0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, 0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, 0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, 0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, 0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, 0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, 0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, 0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, }; static const unsigned char nmstrtPages[] = { 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const unsigned char namePages[] = { 0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, 0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; PyXML-0.8.2/extensions/expat/lib/utf8tab.h0100644000076400001440000000334307517567466017556 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ /* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, /* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, /* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, PyXML-0.8.2/extensions/expat/lib/winconfig.h0100644000076400001440000000134307517567466020162 0ustar martinusers/*================================================================ ** Copyright 2000, Clark Cooper ** All rights reserved. ** ** This is free software. You are permitted to copy, distribute, or modify ** it under the terms of the MIT/X license (contained in the COPYING file ** with this distribution.) */ #ifndef WINCONFIG_H #define WINCONFIG_H #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #include #include #define XML_NS 1 #define XML_DTD 1 #define XML_CONTEXT_BYTES 1024 /* we will assume all Windows platforms are little endian */ #define BYTEORDER 1234 /* Windows has memmove() available. */ #define HAVE_MEMMOVE #endif /* ndef WINCONFIG_H */ PyXML-0.8.2/extensions/expat/lib/xmlparse.c0100644000076400001440000052263207614720025020012 0ustar martinusers/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #include #include /* memset(), memcpy() */ #ifdef COMPILED_FROM_DSP #include "winconfig.h" #define XMLPARSEAPI(type) type __cdecl #include "expat.h" #undef XMLPARSEAPI #elif defined(MACOS_CLASSIC) #include "macconfig.h" #include "expat.h" #else #ifdef __declspec #define XMLPARSEAPI(type) type __cdecl #endif #include "expat.h" #ifdef __declspec #undef XMLPARSEAPI #endif #endif /* ndef COMPILED_FROM_DSP */ #ifdef XML_UNICODE #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX #define XmlConvert XmlUtf16Convert #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS #define XmlEncode XmlUtf16Encode #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) typedef unsigned short ICHAR; #else #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX #define XmlConvert XmlUtf8Convert #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS #define XmlEncode XmlUtf8Encode #define MUST_CONVERT(enc, s) (!(enc)->isUtf8) typedef char ICHAR; #endif #ifndef XML_NS #define XmlInitEncodingNS XmlInitEncoding #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding #undef XmlGetInternalEncodingNS #define XmlGetInternalEncodingNS XmlGetInternalEncoding #define XmlParseXmlDeclNS XmlParseXmlDecl #endif #ifdef XML_UNICODE #ifdef XML_UNICODE_WCHAR_T #define XML_T(x) (const wchar_t)x #define XML_L(x) L ## x #else #define XML_T(x) (const unsigned short)x #define XML_L(x) x #endif #else #define XML_T(x) x #define XML_L(x) x #endif /* Round up n to be a multiple of sz, where sz is a power of 2. */ #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) #include "internal.h" #include "xmltok.h" #include "xmlrole.h" typedef const XML_Char *KEY; typedef struct { KEY name; } NAMED; typedef struct { NAMED **v; size_t size; size_t used; size_t usedLim; const XML_Memory_Handling_Suite *mem; } HASH_TABLE; typedef struct { NAMED **p; NAMED **end; } HASH_TABLE_ITER; #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ #define INIT_DATA_BUF_SIZE 1024 #define INIT_ATTS_SIZE 16 #define INIT_BLOCK_SIZE 1024 #define INIT_BUFFER_SIZE 1024 #define EXPAND_SPARE 24 typedef struct binding { struct prefix *prefix; struct binding *nextTagBinding; struct binding *prevPrefixBinding; const struct attribute_id *attId; XML_Char *uri; int uriLen; int uriAlloc; } BINDING; typedef struct prefix { const XML_Char *name; BINDING *binding; } PREFIX; typedef struct { const XML_Char *str; const XML_Char *localPart; const XML_Char *prefix; int strLen; int uriLen; int prefixLen; } TAG_NAME; /* TAG represents an open element. The name of the element is stored in both the document and API encodings. The memory buffer 'buf' is a separately-allocated memory area which stores the name. During the XML_Parse()/ XMLParseBuffer() when the element is open, the memory for the 'raw' version of the name (in the document encoding) is shared with the document buffer. If the element is open across calls to XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to contain the 'raw' name as well. A parser re-uses these structures, maintaining a list of allocated TAG objects in a free list. */ typedef struct tag { struct tag *parent; /* parent of this element */ const char *rawName; /* tagName in the original encoding */ int rawNameLength; TAG_NAME name; /* tagName in the API encoding */ char *buf; /* buffer for name components */ char *bufEnd; /* end of the buffer */ BINDING *bindings; } TAG; typedef struct { const XML_Char *name; const XML_Char *textPtr; int textLen; const XML_Char *systemId; const XML_Char *base; const XML_Char *publicId; const XML_Char *notation; XML_Bool open; XML_Bool is_param; XML_Bool is_internal; /* true if declared in internal subset outside PE */ } ENTITY; typedef struct { enum XML_Content_Type type; enum XML_Content_Quant quant; const XML_Char * name; int firstchild; int lastchild; int childcnt; int nextsib; } CONTENT_SCAFFOLD; #define INIT_SCAFFOLD_ELEMENTS 32 typedef struct block { struct block *next; int size; XML_Char s[1]; } BLOCK; typedef struct { BLOCK *blocks; BLOCK *freeBlocks; const XML_Char *end; XML_Char *ptr; XML_Char *start; const XML_Memory_Handling_Suite *mem; } STRING_POOL; /* The XML_Char before the name is used to determine whether an attribute has been specified. */ typedef struct attribute_id { XML_Char *name; PREFIX *prefix; XML_Bool maybeTokenized; XML_Bool xmlns; } ATTRIBUTE_ID; typedef struct { const ATTRIBUTE_ID *id; XML_Bool isCdata; const XML_Char *value; } DEFAULT_ATTRIBUTE; typedef struct { const XML_Char *name; PREFIX *prefix; const ATTRIBUTE_ID *idAtt; int nDefaultAtts; int allocDefaultAtts; DEFAULT_ATTRIBUTE *defaultAtts; } ELEMENT_TYPE; typedef struct { HASH_TABLE generalEntities; HASH_TABLE elementTypes; HASH_TABLE attributeIds; HASH_TABLE prefixes; STRING_POOL pool; STRING_POOL entityValuePool; /* false once a parameter entity reference has been skipped */ XML_Bool keepProcessing; /* true once an internal or external PE reference has been encountered; this includes the reference to an external subset */ XML_Bool hasParamEntityRefs; XML_Bool standalone; #ifdef XML_DTD /* indicates if external PE has been read */ XML_Bool paramEntityRead; HASH_TABLE paramEntities; #endif /* XML_DTD */ PREFIX defaultPrefix; /* === scaffolding for building content model === */ XML_Bool in_eldecl; CONTENT_SCAFFOLD *scaffold; unsigned contentStringLen; unsigned scaffSize; unsigned scaffCount; int scaffLevel; int *scaffIndex; } DTD; typedef struct open_internal_entity { const char *internalEventPtr; const char *internalEventEndPtr; struct open_internal_entity *next; ENTITY *entity; } OPEN_INTERNAL_ENTITY; typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start, const char *end, const char **endPtr); static Processor prologProcessor; static Processor prologInitProcessor; static Processor contentProcessor; static Processor cdataSectionProcessor; #ifdef XML_DTD static Processor ignoreSectionProcessor; static Processor externalParEntProcessor; static Processor externalParEntInitProcessor; static Processor entityValueProcessor; static Processor entityValueInitProcessor; #endif /* XML_DTD */ static Processor epilogProcessor; static Processor errorProcessor; static Processor externalEntityInitProcessor; static Processor externalEntityInitProcessor2; static Processor externalEntityInitProcessor3; static Processor externalEntityContentProcessor; static enum XML_Error handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *); static enum XML_Error initializeEncoding(XML_Parser parser); static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr); static enum XML_Error processInternalParamEntity(XML_Parser parser, ENTITY *entity); static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *start, const char *end, const char **endPtr); static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); #ifdef XML_DTD static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); #endif /* XML_DTD */ static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, TAG_NAME *tagNamePtr, BINDING **bindingsPtr); static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser); static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, const char *, const char *, STRING_POOL *); static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, const char *, const char *, STRING_POOL *); static ATTRIBUTE_ID * getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static void reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static const XML_Char * getContext(XML_Parser parser); static XML_Bool setContext(XML_Parser parser, const XML_Char *context); static void FASTCALL normalizePublicId(XML_Char *s); static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms); /* do not call if parentParser != NULL */ static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms); static void dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms); static int dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); static NAMED * lookup(HASH_TABLE *table, KEY name, size_t createSize); static void FASTCALL hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms); static void FASTCALL hashTableClear(HASH_TABLE *); static void FASTCALL hashTableDestroy(HASH_TABLE *); static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *); static void FASTCALL poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms); static void FASTCALL poolClear(STRING_POOL *); static void FASTCALL poolDestroy(STRING_POOL *); static XML_Char * poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end); static XML_Char * poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end); static XML_Bool FASTCALL poolGrow(STRING_POOL *pool); static const XML_Char * FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s); static const XML_Char * poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); static const XML_Char * FASTCALL poolAppendString(STRING_POOL *pool, const XML_Char *s); static int FASTCALL nextScaffoldPart(XML_Parser parser); static XML_Content * build_model(XML_Parser parser); static ELEMENT_TYPE * getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, const char *end); static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep, DTD *dtd); static void parserInit(XML_Parser parser, const XML_Char *encodingName); #define poolStart(pool) ((pool)->start) #define poolEnd(pool) ((pool)->ptr) #define poolLength(pool) ((pool)->ptr - (pool)->start) #define poolChop(pool) ((void)--(pool->ptr)) #define poolLastChar(pool) (((pool)->ptr)[-1]) #define poolDiscard(pool) ((pool)->ptr = (pool)->start) #define poolFinish(pool) ((pool)->start = (pool)->ptr) #define poolAppendChar(pool, c) \ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ ? 0 \ : ((*((pool)->ptr)++ = c), 1)) struct XML_ParserStruct { /* The first member must be userData so that the XML_GetUserData macro works. */ void *m_userData; void *m_handlerArg; char *m_buffer; const XML_Memory_Handling_Suite m_mem; /* first character to be parsed */ const char *m_bufferPtr; /* past last character to be parsed */ char *m_bufferEnd; /* allocated end of buffer */ const char *m_bufferLim; long m_parseEndByteIndex; const char *m_parseEndPtr; XML_Char *m_dataBuf; XML_Char *m_dataBufEnd; XML_StartElementHandler m_startElementHandler; XML_EndElementHandler m_endElementHandler; XML_CharacterDataHandler m_characterDataHandler; XML_ProcessingInstructionHandler m_processingInstructionHandler; XML_CommentHandler m_commentHandler; XML_StartCdataSectionHandler m_startCdataSectionHandler; XML_EndCdataSectionHandler m_endCdataSectionHandler; XML_DefaultHandler m_defaultHandler; XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; XML_NotationDeclHandler m_notationDeclHandler; XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; XML_NotStandaloneHandler m_notStandaloneHandler; XML_ExternalEntityRefHandler m_externalEntityRefHandler; XML_Parser m_externalEntityRefHandlerArg; XML_SkippedEntityHandler m_skippedEntityHandler; XML_UnknownEncodingHandler m_unknownEncodingHandler; XML_ElementDeclHandler m_elementDeclHandler; XML_AttlistDeclHandler m_attlistDeclHandler; XML_EntityDeclHandler m_entityDeclHandler; XML_XmlDeclHandler m_xmlDeclHandler; const ENCODING *m_encoding; INIT_ENCODING m_initEncoding; const ENCODING *m_internalEncoding; const XML_Char *m_protocolEncodingName; XML_Bool m_ns; XML_Bool m_ns_triplets; void *m_unknownEncodingMem; void *m_unknownEncodingData; void *m_unknownEncodingHandlerData; void (*m_unknownEncodingRelease)(void *); PROLOG_STATE m_prologState; Processor *m_processor; enum XML_Error m_errorCode; const char *m_eventPtr; const char *m_eventEndPtr; const char *m_positionPtr; OPEN_INTERNAL_ENTITY *m_openInternalEntities; XML_Bool m_defaultExpandInternalEntities; int m_tagLevel; ENTITY *m_declEntity; const XML_Char *m_doctypeName; const XML_Char *m_doctypeSysid; const XML_Char *m_doctypePubid; const XML_Char *m_declAttributeType; const XML_Char *m_declNotationName; const XML_Char *m_declNotationPublicId; ELEMENT_TYPE *m_declElementType; ATTRIBUTE_ID *m_declAttributeId; XML_Bool m_declAttributeIsCdata; XML_Bool m_declAttributeIsId; DTD *m_dtd; const XML_Char *m_curBase; TAG *m_tagStack; TAG *m_freeTagList; BINDING *m_inheritedBindings; BINDING *m_freeBindingList; int m_attsSize; int m_nSpecifiedAtts; int m_idAttIndex; ATTRIBUTE *m_atts; POSITION m_position; STRING_POOL m_tempPool; STRING_POOL m_temp2Pool; char *m_groupConnector; unsigned m_groupSize; XML_Char m_namespaceSeparator; XML_Parser m_parentParser; #ifdef XML_DTD XML_Bool m_isParamEntity; XML_Bool m_useForeignDTD; enum XML_ParamEntityParsing m_paramEntityParsing; #endif }; #define MALLOC(s) (parser->m_mem.malloc_fcn((s))) #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s))) #define FREE(p) (parser->m_mem.free_fcn((p))) #define userData (parser->m_userData) #define handlerArg (parser->m_handlerArg) #define startElementHandler (parser->m_startElementHandler) #define endElementHandler (parser->m_endElementHandler) #define characterDataHandler (parser->m_characterDataHandler) #define processingInstructionHandler \ (parser->m_processingInstructionHandler) #define commentHandler (parser->m_commentHandler) #define startCdataSectionHandler \ (parser->m_startCdataSectionHandler) #define endCdataSectionHandler (parser->m_endCdataSectionHandler) #define defaultHandler (parser->m_defaultHandler) #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler) #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler) #define unparsedEntityDeclHandler \ (parser->m_unparsedEntityDeclHandler) #define notationDeclHandler (parser->m_notationDeclHandler) #define startNamespaceDeclHandler \ (parser->m_startNamespaceDeclHandler) #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler) #define notStandaloneHandler (parser->m_notStandaloneHandler) #define externalEntityRefHandler \ (parser->m_externalEntityRefHandler) #define externalEntityRefHandlerArg \ (parser->m_externalEntityRefHandlerArg) #define internalEntityRefHandler \ (parser->m_internalEntityRefHandler) #define skippedEntityHandler (parser->m_skippedEntityHandler) #define unknownEncodingHandler (parser->m_unknownEncodingHandler) #define elementDeclHandler (parser->m_elementDeclHandler) #define attlistDeclHandler (parser->m_attlistDeclHandler) #define entityDeclHandler (parser->m_entityDeclHandler) #define xmlDeclHandler (parser->m_xmlDeclHandler) #define encoding (parser->m_encoding) #define initEncoding (parser->m_initEncoding) #define internalEncoding (parser->m_internalEncoding) #define unknownEncodingMem (parser->m_unknownEncodingMem) #define unknownEncodingData (parser->m_unknownEncodingData) #define unknownEncodingHandlerData \ (parser->m_unknownEncodingHandlerData) #define unknownEncodingRelease (parser->m_unknownEncodingRelease) #define protocolEncodingName (parser->m_protocolEncodingName) #define ns (parser->m_ns) #define ns_triplets (parser->m_ns_triplets) #define prologState (parser->m_prologState) #define processor (parser->m_processor) #define errorCode (parser->m_errorCode) #define eventPtr (parser->m_eventPtr) #define eventEndPtr (parser->m_eventEndPtr) #define positionPtr (parser->m_positionPtr) #define position (parser->m_position) #define openInternalEntities (parser->m_openInternalEntities) #define defaultExpandInternalEntities \ (parser->m_defaultExpandInternalEntities) #define tagLevel (parser->m_tagLevel) #define buffer (parser->m_buffer) #define bufferPtr (parser->m_bufferPtr) #define bufferEnd (parser->m_bufferEnd) #define parseEndByteIndex (parser->m_parseEndByteIndex) #define parseEndPtr (parser->m_parseEndPtr) #define bufferLim (parser->m_bufferLim) #define dataBuf (parser->m_dataBuf) #define dataBufEnd (parser->m_dataBufEnd) #define _dtd (parser->m_dtd) #define curBase (parser->m_curBase) #define declEntity (parser->m_declEntity) #define doctypeName (parser->m_doctypeName) #define doctypeSysid (parser->m_doctypeSysid) #define doctypePubid (parser->m_doctypePubid) #define declAttributeType (parser->m_declAttributeType) #define declNotationName (parser->m_declNotationName) #define declNotationPublicId (parser->m_declNotationPublicId) #define declElementType (parser->m_declElementType) #define declAttributeId (parser->m_declAttributeId) #define declAttributeIsCdata (parser->m_declAttributeIsCdata) #define declAttributeIsId (parser->m_declAttributeIsId) #define freeTagList (parser->m_freeTagList) #define freeBindingList (parser->m_freeBindingList) #define inheritedBindings (parser->m_inheritedBindings) #define tagStack (parser->m_tagStack) #define atts (parser->m_atts) #define attsSize (parser->m_attsSize) #define nSpecifiedAtts (parser->m_nSpecifiedAtts) #define idAttIndex (parser->m_idAttIndex) #define tempPool (parser->m_tempPool) #define temp2Pool (parser->m_temp2Pool) #define groupConnector (parser->m_groupConnector) #define groupSize (parser->m_groupSize) #define namespaceSeparator (parser->m_namespaceSeparator) #define parentParser (parser->m_parentParser) #ifdef XML_DTD #define isParamEntity (parser->m_isParamEntity) #define useForeignDTD (parser->m_useForeignDTD) #define paramEntityParsing (parser->m_paramEntityParsing) #endif /* XML_DTD */ #define parsing \ (parentParser \ ? \ (isParamEntity \ ? \ (processor != externalParEntInitProcessor) \ : \ (processor != externalEntityInitProcessor)) \ : \ (processor != prologInitProcessor)) XML_Parser XML_ParserCreate(const XML_Char *encodingName) { return XML_ParserCreate_MM(encodingName, NULL, NULL); } XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { XML_Char tmp[2]; *tmp = nsSep; return XML_ParserCreate_MM(encodingName, NULL, tmp); } static const XML_Char implicitContext[] = { 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', 'X', 'M', 'L', '/', '1', '9', '9', '8', '/', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' }; XML_Parser XML_ParserCreate_MM(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep) { XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL); if (parser != NULL && ns) { /* implicit context only set for root parser, since child parsers (i.e. external entity parsers) will inherit it */ if (!setContext(parser, implicitContext)) { XML_ParserFree(parser); return NULL; } } return parser; } static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep, DTD *dtd) { XML_Parser parser; if (memsuite) { XML_Memory_Handling_Suite *mtemp; parser = (XML_Parser) memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); if (parser != NULL) { mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = memsuite->malloc_fcn; mtemp->realloc_fcn = memsuite->realloc_fcn; mtemp->free_fcn = memsuite->free_fcn; } } else { XML_Memory_Handling_Suite *mtemp; parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); if (parser != NULL) { mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = malloc; mtemp->realloc_fcn = realloc; mtemp->free_fcn = free; } } if (!parser) return parser; buffer = NULL; bufferLim = NULL; attsSize = INIT_ATTS_SIZE; atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE)); if (atts == NULL) { FREE(parser); return NULL; } dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); if (dataBuf == NULL) { FREE(atts); FREE(parser); return NULL; } dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; if (dtd) _dtd = dtd; else { _dtd = dtdCreate(&parser->m_mem); if (_dtd == NULL) { FREE(dataBuf); FREE(atts); FREE(parser); return NULL; } } freeBindingList = NULL; freeTagList = NULL; groupSize = 0; groupConnector = NULL; unknownEncodingHandler = NULL; unknownEncodingHandlerData = NULL; namespaceSeparator = '!'; ns = XML_FALSE; ns_triplets = XML_FALSE; poolInit(&tempPool, &(parser->m_mem)); poolInit(&temp2Pool, &(parser->m_mem)); parserInit(parser, encodingName); if (encodingName && !protocolEncodingName) { XML_ParserFree(parser); return NULL; } if (nameSep) { ns = XML_TRUE; internalEncoding = XmlGetInternalEncodingNS(); namespaceSeparator = *nameSep; } else { internalEncoding = XmlGetInternalEncoding(); } return parser; } static void parserInit(XML_Parser parser, const XML_Char *encodingName) { processor = prologInitProcessor; XmlPrologStateInit(&prologState); protocolEncodingName = (encodingName != NULL ? poolCopyString(&tempPool, encodingName) : NULL); curBase = NULL; XmlInitEncoding(&initEncoding, &encoding, 0); userData = NULL; handlerArg = NULL; startElementHandler = NULL; endElementHandler = NULL; characterDataHandler = NULL; processingInstructionHandler = NULL; commentHandler = NULL; startCdataSectionHandler = NULL; endCdataSectionHandler = NULL; defaultHandler = NULL; startDoctypeDeclHandler = NULL; endDoctypeDeclHandler = NULL; unparsedEntityDeclHandler = NULL; notationDeclHandler = NULL; startNamespaceDeclHandler = NULL; endNamespaceDeclHandler = NULL; notStandaloneHandler = NULL; externalEntityRefHandler = NULL; externalEntityRefHandlerArg = parser; skippedEntityHandler = NULL; elementDeclHandler = NULL; attlistDeclHandler = NULL; entityDeclHandler = NULL; xmlDeclHandler = NULL; bufferPtr = buffer; bufferEnd = buffer; parseEndByteIndex = 0; parseEndPtr = NULL; declElementType = NULL; declAttributeId = NULL; declEntity = NULL; doctypeName = NULL; doctypeSysid = NULL; doctypePubid = NULL; declAttributeType = NULL; declNotationName = NULL; declNotationPublicId = NULL; declAttributeIsCdata = XML_FALSE; declAttributeIsId = XML_FALSE; memset(&position, 0, sizeof(POSITION)); errorCode = XML_ERROR_NONE; eventPtr = NULL; eventEndPtr = NULL; positionPtr = NULL; openInternalEntities = 0; defaultExpandInternalEntities = XML_TRUE; tagLevel = 0; tagStack = NULL; inheritedBindings = NULL; nSpecifiedAtts = 0; unknownEncodingMem = NULL; unknownEncodingRelease = NULL; unknownEncodingData = NULL; parentParser = NULL; #ifdef XML_DTD isParamEntity = XML_FALSE; useForeignDTD = XML_FALSE; paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif } /* moves list of bindings to freeBindingList */ static void FASTCALL moveToFreeBindingList(XML_Parser parser, BINDING *bindings) { while (bindings) { BINDING *b = bindings; bindings = bindings->nextTagBinding; b->nextTagBinding = freeBindingList; freeBindingList = b; } } XML_Bool XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { TAG *tStk; if (parentParser) return XML_FALSE; /* move tagStack to freeTagList */ tStk = tagStack; while (tStk) { TAG *tag = tStk; tStk = tStk->parent; tag->parent = freeTagList; moveToFreeBindingList(parser, tag->bindings); tag->bindings = NULL; freeTagList = tag; } moveToFreeBindingList(parser, inheritedBindings); if (unknownEncodingMem) FREE(unknownEncodingMem); if (unknownEncodingRelease) unknownEncodingRelease(unknownEncodingData); poolClear(&tempPool); poolClear(&temp2Pool); parserInit(parser, encodingName); dtdReset(_dtd, &parser->m_mem); return setContext(parser, implicitContext); } enum XML_Status XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { /* Block after XML_Parse()/XML_ParseBuffer() has been called. XXX There's no way for the caller to determine which of the XXX possible error cases caused the XML_STATUS_ERROR return. */ if (parsing) return XML_STATUS_ERROR; if (encodingName == NULL) protocolEncodingName = NULL; else { protocolEncodingName = poolCopyString(&tempPool, encodingName); if (!protocolEncodingName) return XML_STATUS_ERROR; } return XML_STATUS_OK; } XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, const XML_Char *encodingName) { XML_Parser parser = oldParser; DTD *newDtd = NULL; DTD *oldDtd = _dtd; XML_StartElementHandler oldStartElementHandler = startElementHandler; XML_EndElementHandler oldEndElementHandler = endElementHandler; XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler; XML_CommentHandler oldCommentHandler = commentHandler; XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler; XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler; XML_DefaultHandler oldDefaultHandler = defaultHandler; XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler; XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler; XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler; XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler; XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler; XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; ELEMENT_TYPE * oldDeclElementType = declElementType; void *oldUserData = userData; void *oldHandlerArg = handlerArg; XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; #ifdef XML_DTD enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; int oldInEntityValue = prologState.inEntityValue; #endif XML_Bool oldns_triplets = ns_triplets; #ifdef XML_DTD if (!context) newDtd = oldDtd; #endif /* XML_DTD */ /* Note that the magical uses of the pre-processor to make field access look more like C++ require that `parser' be overwritten here. This makes this function more painful to follow than it would be otherwise. */ if (ns) { XML_Char tmp[2]; *tmp = namespaceSeparator; parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); } else { parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); } if (!parser) return NULL; startElementHandler = oldStartElementHandler; endElementHandler = oldEndElementHandler; characterDataHandler = oldCharacterDataHandler; processingInstructionHandler = oldProcessingInstructionHandler; commentHandler = oldCommentHandler; startCdataSectionHandler = oldStartCdataSectionHandler; endCdataSectionHandler = oldEndCdataSectionHandler; defaultHandler = oldDefaultHandler; unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; notationDeclHandler = oldNotationDeclHandler; startNamespaceDeclHandler = oldStartNamespaceDeclHandler; endNamespaceDeclHandler = oldEndNamespaceDeclHandler; notStandaloneHandler = oldNotStandaloneHandler; externalEntityRefHandler = oldExternalEntityRefHandler; skippedEntityHandler = oldSkippedEntityHandler; unknownEncodingHandler = oldUnknownEncodingHandler; elementDeclHandler = oldElementDeclHandler; attlistDeclHandler = oldAttlistDeclHandler; entityDeclHandler = oldEntityDeclHandler; xmlDeclHandler = oldXmlDeclHandler; declElementType = oldDeclElementType; userData = oldUserData; if (oldUserData == oldHandlerArg) handlerArg = userData; else handlerArg = parser; if (oldExternalEntityRefHandlerArg != oldParser) externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; defaultExpandInternalEntities = oldDefaultExpandInternalEntities; ns_triplets = oldns_triplets; parentParser = oldParser; #ifdef XML_DTD paramEntityParsing = oldParamEntityParsing; prologState.inEntityValue = oldInEntityValue; if (context) { #endif /* XML_DTD */ if (!dtdCopy(_dtd, oldDtd, &parser->m_mem) || !setContext(parser, context)) { XML_ParserFree(parser); return NULL; } processor = externalEntityInitProcessor; #ifdef XML_DTD } else { /* The DTD instance referenced by _dtd is shared between the document's root parser and external PE parsers, therefore one does not need to call setContext. In addition, one also *must* not call setContext, because this would overwrite existing prefix->binding pointers in _dtd with ones that get destroyed with the external PE parser. This would leave those prefixes with dangling pointers. */ isParamEntity = XML_TRUE; XmlPrologStateInitExternalEntity(&prologState); processor = externalParEntInitProcessor; } #endif /* XML_DTD */ return parser; } static void FASTCALL destroyBindings(BINDING *bindings, XML_Parser parser) { for (;;) { BINDING *b = bindings; if (!b) break; bindings = b->nextTagBinding; FREE(b->uri); FREE(b); } } void XML_ParserFree(XML_Parser parser) { for (;;) { TAG *p; if (tagStack == NULL) { if (freeTagList == NULL) break; tagStack = freeTagList; freeTagList = NULL; } p = tagStack; tagStack = tagStack->parent; FREE(p->buf); destroyBindings(p->bindings, parser); FREE(p); } destroyBindings(freeBindingList, parser); destroyBindings(inheritedBindings, parser); poolDestroy(&tempPool); poolDestroy(&temp2Pool); #ifdef XML_DTD /* external parameter entity parsers share the DTD structure parser->m_dtd with the root parser, so we must not destroy it */ if (!isParamEntity && _dtd) #else if (_dtd) #endif /* XML_DTD */ dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem); FREE((void *)atts); if (groupConnector) FREE(groupConnector); if (buffer) FREE(buffer); FREE(dataBuf); if (unknownEncodingMem) FREE(unknownEncodingMem); if (unknownEncodingRelease) unknownEncodingRelease(unknownEncodingData); FREE(parser); } void XML_UseParserAsHandlerArg(XML_Parser parser) { handlerArg = parser; } enum XML_Error XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { #ifdef XML_DTD /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (parsing) return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; useForeignDTD = useDTD; return XML_ERROR_NONE; #else return XML_ERROR_FEATURE_REQUIRES_XML_DTD; #endif } void XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (parsing) return; ns_triplets = do_nst ? XML_TRUE : XML_FALSE; } void XML_SetUserData(XML_Parser parser, void *p) { if (handlerArg == userData) handlerArg = userData = p; else userData = p; } enum XML_Status XML_SetBase(XML_Parser parser, const XML_Char *p) { if (p) { p = poolCopyString(&_dtd->pool, p); if (!p) return XML_STATUS_ERROR; curBase = p; } else curBase = NULL; return XML_STATUS_OK; } const XML_Char * XML_GetBase(XML_Parser parser) { return curBase; } int XML_GetSpecifiedAttributeCount(XML_Parser parser) { return nSpecifiedAtts; } int XML_GetIdAttributeIndex(XML_Parser parser) { return idAttIndex; } void XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) { startElementHandler = start; endElementHandler = end; } void XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) { startElementHandler = start; } void XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) { endElementHandler = end; } void XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler) { characterDataHandler = handler; } void XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler) { processingInstructionHandler = handler; } void XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) { commentHandler = handler; } void XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end) { startCdataSectionHandler = start; endCdataSectionHandler = end; } void XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start) { startCdataSectionHandler = start; } void XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end) { endCdataSectionHandler = end; } void XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) { defaultHandler = handler; defaultExpandInternalEntities = XML_FALSE; } void XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) { defaultHandler = handler; defaultExpandInternalEntities = XML_TRUE; } void XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end) { startDoctypeDeclHandler = start; endDoctypeDeclHandler = end; } void XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start) { startDoctypeDeclHandler = start; } void XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) { endDoctypeDeclHandler = end; } void XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler) { unparsedEntityDeclHandler = handler; } void XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) { notationDeclHandler = handler; } void XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end) { startNamespaceDeclHandler = start; endNamespaceDeclHandler = end; } void XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start) { startNamespaceDeclHandler = start; } void XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end) { endNamespaceDeclHandler = end; } void XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler) { notStandaloneHandler = handler; } void XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler) { externalEntityRefHandler = handler; } void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) { if (arg) externalEntityRefHandlerArg = (XML_Parser)arg; else externalEntityRefHandlerArg = parser; } void XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler) { skippedEntityHandler = handler; } void XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *data) { unknownEncodingHandler = handler; unknownEncodingHandlerData = data; } void XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) { elementDeclHandler = eldecl; } void XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) { attlistDeclHandler = attdecl; } void XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) { entityDeclHandler = handler; } void XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) { xmlDeclHandler = handler; } int XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing peParsing) { /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (parsing) return 0; #ifdef XML_DTD paramEntityParsing = peParsing; return 1; #else return peParsing == XML_PARAM_ENTITY_PARSING_NEVER; #endif } enum XML_Status XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { if (len == 0) { if (!isFinal) return XML_STATUS_OK; positionPtr = bufferPtr; errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0); if (errorCode == XML_ERROR_NONE) return XML_STATUS_OK; eventEndPtr = eventPtr; processor = errorProcessor; return XML_STATUS_ERROR; } #ifndef XML_CONTEXT_BYTES else if (bufferPtr == bufferEnd) { const char *end; int nLeftOver; parseEndByteIndex += len; positionPtr = s; if (isFinal) { errorCode = processor(parser, s, parseEndPtr = s + len, 0); if (errorCode == XML_ERROR_NONE) return XML_STATUS_OK; eventEndPtr = eventPtr; processor = errorProcessor; return XML_STATUS_ERROR; } errorCode = processor(parser, s, parseEndPtr = s + len, &end); if (errorCode != XML_ERROR_NONE) { eventEndPtr = eventPtr; processor = errorProcessor; return XML_STATUS_ERROR; } XmlUpdatePosition(encoding, positionPtr, end, &position); positionPtr = end; nLeftOver = s + len - end; if (nLeftOver) { if (buffer == NULL || nLeftOver > bufferLim - buffer) { /* FIXME avoid integer overflow */ char *temp; temp = (buffer == NULL ? (char *)MALLOC(len * 2) : (char *)REALLOC(buffer, len * 2)); if (temp == NULL) { errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; } buffer = temp; if (!buffer) { errorCode = XML_ERROR_NO_MEMORY; eventPtr = eventEndPtr = NULL; processor = errorProcessor; return XML_STATUS_ERROR; } bufferLim = buffer + len * 2; } memcpy(buffer, end, nLeftOver); bufferPtr = buffer; bufferEnd = buffer + nLeftOver; } return XML_STATUS_OK; } #endif /* not defined XML_CONTEXT_BYTES */ else { void *buff = XML_GetBuffer(parser, len); if (buff == NULL) return XML_STATUS_ERROR; else { memcpy(buff, s, len); return XML_ParseBuffer(parser, len, isFinal); } } } enum XML_Status XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { const char *start = bufferPtr; positionPtr = start; bufferEnd += len; parseEndByteIndex += len; errorCode = processor(parser, start, parseEndPtr = bufferEnd, isFinal ? (const char **)NULL : &bufferPtr); if (errorCode == XML_ERROR_NONE) { if (!isFinal) { XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); positionPtr = bufferPtr; } return XML_STATUS_OK; } else { eventEndPtr = eventPtr; processor = errorProcessor; return XML_STATUS_ERROR; } } void * XML_GetBuffer(XML_Parser parser, int len) { if (len > bufferLim - bufferEnd) { /* FIXME avoid integer overflow */ int neededSize = len + (bufferEnd - bufferPtr); #ifdef XML_CONTEXT_BYTES int keep = bufferPtr - buffer; if (keep > XML_CONTEXT_BYTES) keep = XML_CONTEXT_BYTES; neededSize += keep; #endif /* defined XML_CONTEXT_BYTES */ if (neededSize <= bufferLim - buffer) { #ifdef XML_CONTEXT_BYTES if (keep < bufferPtr - buffer) { int offset = (bufferPtr - buffer) - keep; memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep); bufferEnd -= offset; bufferPtr -= offset; } #else memmove(buffer, bufferPtr, bufferEnd - bufferPtr); bufferEnd = buffer + (bufferEnd - bufferPtr); bufferPtr = buffer; #endif /* not defined XML_CONTEXT_BYTES */ } else { char *newBuf; int bufferSize = bufferLim - bufferPtr; if (bufferSize == 0) bufferSize = INIT_BUFFER_SIZE; do { bufferSize *= 2; } while (bufferSize < neededSize); newBuf = (char *)MALLOC(bufferSize); if (newBuf == 0) { errorCode = XML_ERROR_NO_MEMORY; return NULL; } bufferLim = newBuf + bufferSize; #ifdef XML_CONTEXT_BYTES if (bufferPtr) { int keep = bufferPtr - buffer; if (keep > XML_CONTEXT_BYTES) keep = XML_CONTEXT_BYTES; memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep); FREE(buffer); buffer = newBuf; bufferEnd = buffer + (bufferEnd - bufferPtr) + keep; bufferPtr = buffer + keep; } else { bufferEnd = newBuf + (bufferEnd - bufferPtr); bufferPtr = buffer = newBuf; } #else if (bufferPtr) { memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); FREE(buffer); } bufferEnd = newBuf + (bufferEnd - bufferPtr); bufferPtr = buffer = newBuf; #endif /* not defined XML_CONTEXT_BYTES */ } } return bufferEnd; } enum XML_Error XML_GetErrorCode(XML_Parser parser) { return errorCode; } long XML_GetCurrentByteIndex(XML_Parser parser) { if (eventPtr) return parseEndByteIndex - (parseEndPtr - eventPtr); return -1; } int XML_GetCurrentByteCount(XML_Parser parser) { if (eventEndPtr && eventPtr) return eventEndPtr - eventPtr; return 0; } const char * XML_GetInputContext(XML_Parser parser, int *offset, int *size) { #ifdef XML_CONTEXT_BYTES if (eventPtr && buffer) { *offset = eventPtr - buffer; *size = bufferEnd - buffer; return buffer; } #endif /* defined XML_CONTEXT_BYTES */ return (char *) 0; } int XML_GetCurrentLineNumber(XML_Parser parser) { if (eventPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; } return position.lineNumber + 1; } int XML_GetCurrentColumnNumber(XML_Parser parser) { if (eventPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; } return position.columnNumber; } void XML_FreeContentModel(XML_Parser parser, XML_Content *model) { FREE(model); } void * XML_MemMalloc(XML_Parser parser, size_t size) { return MALLOC(size); } void * XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { return REALLOC(ptr, size); } void XML_MemFree(XML_Parser parser, void *ptr) { FREE(ptr); } void XML_DefaultCurrent(XML_Parser parser) { if (defaultHandler) { if (openInternalEntities) reportDefault(parser, internalEncoding, openInternalEntities->internalEventPtr, openInternalEntities->internalEventEndPtr); else reportDefault(parser, encoding, eventPtr, eventEndPtr); } } const XML_LChar * XML_ErrorString(enum XML_Error code) { static const XML_LChar *message[] = { 0, XML_L("out of memory"), XML_L("syntax error"), XML_L("no element found"), XML_L("not well-formed (invalid token)"), XML_L("unclosed token"), XML_L("partial character"), XML_L("mismatched tag"), XML_L("duplicate attribute"), XML_L("junk after document element"), XML_L("illegal parameter entity reference"), XML_L("undefined entity"), XML_L("recursive entity reference"), XML_L("asynchronous entity"), XML_L("reference to invalid character number"), XML_L("reference to binary entity"), XML_L("reference to external entity in attribute"), XML_L("xml declaration not at start of external entity"), XML_L("unknown encoding"), XML_L("encoding specified in XML declaration is incorrect"), XML_L("unclosed CDATA section"), XML_L("error in processing external entity reference"), XML_L("document is not standalone"), XML_L("unexpected parser state - please send a bug report"), XML_L("entity declared in parameter entity"), XML_L("requested feature requires XML_DTD support in Expat"), XML_L("cannot change setting once parsing has begun") }; if (code > 0 && code < sizeof(message)/sizeof(message[0])) return message[code]; return NULL; } const XML_LChar * XML_ExpatVersion(void) { /* V1 is used to string-ize the version number. However, it would string-ize the actual version macro *names* unless we get them substituted before being passed to V1. CPP is defined to expand a macro, then rescan for more expansions. Thus, we use V2 to expand the version macros, then CPP will expand the resulting V1() macro with the correct numerals. */ /* ### I'm assuming cpp is portable in this respect... */ #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c) #define V2(a,b,c) XML_L("expat_")V1(a,b,c) return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); #undef V1 #undef V2 } XML_Expat_Version XML_ExpatVersionInfo(void) { XML_Expat_Version version; version.major = XML_MAJOR_VERSION; version.minor = XML_MINOR_VERSION; version.micro = XML_MICRO_VERSION; return version; } const XML_Feature * XML_GetFeatureList(void) { static XML_Feature features[] = { {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)")}, {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)")}, #ifdef XML_UNICODE {XML_FEATURE_UNICODE, XML_L("XML_UNICODE")}, #endif #ifdef XML_UNICODE_WCHAR_T {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T")}, #endif #ifdef XML_DTD {XML_FEATURE_DTD, XML_L("XML_DTD")}, #endif #ifdef XML_CONTEXT_BYTES {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), XML_CONTEXT_BYTES}, #endif #ifdef XML_MIN_SIZE {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE")}, #endif {XML_FEATURE_END, NULL} }; features[0].value = sizeof(XML_Char); features[1].value = sizeof(XML_LChar); return features; } /* Initially tag->rawName always points into the parse buffer; for those TAG instances opened while the current parse buffer was processed, and not yet closed, we need to store tag->rawName in a more permanent location, since the parse buffer is about to be discarded. */ static XML_Bool storeRawNames(XML_Parser parser) { TAG *tag = tagStack; while (tag) { int bufSize; int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); char *rawNameBuf = tag->buf + nameLen; /* Stop if already stored. Since tagStack is a stack, we can stop at the first entry that has already been copied; everything below it in the stack is already been accounted for in a previous call to this function. */ if (tag->rawName == rawNameBuf) break; /* For re-use purposes we need to ensure that the size of tag->buf is a multiple of sizeof(XML_Char). */ bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); if (bufSize > tag->bufEnd - tag->buf) { char *temp = (char *)REALLOC(tag->buf, bufSize); if (temp == NULL) return XML_FALSE; /* if tag->name.str points to tag->buf (only when namespace processing is off) then we have to update it */ if (tag->name.str == (XML_Char *)tag->buf) tag->name.str = (XML_Char *)temp; /* if tag->name.localPart is set (when namespace processing is on) then update it as well, since it will always point into tag->buf */ if (tag->name.localPart) tag->name.localPart = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf); tag->buf = temp; tag->bufEnd = temp + bufSize; rawNameBuf = temp + nameLen; } memcpy(rawNameBuf, tag->rawName, tag->rawNameLength); tag->rawName = rawNameBuf; tag = tag->parent; } return XML_TRUE; } static enum XML_Error PTRCALL contentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doContent(parser, 0, encoding, start, end, endPtr); if (result != XML_ERROR_NONE) return result; if (!storeRawNames(parser)) return XML_ERROR_NO_MEMORY; return result; } static enum XML_Error PTRCALL externalEntityInitProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; processor = externalEntityInitProcessor2; return externalEntityInitProcessor2(parser, start, end, endPtr); } static enum XML_Error PTRCALL externalEntityInitProcessor2(XML_Parser parser, const char *start, const char *end, const char **endPtr) { const char *next = start; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(encoding, start, end, &next); switch (tok) { case XML_TOK_BOM: /* If we are at the end of the buffer, this would cause the next stage, i.e. externalEntityInitProcessor3, to pass control directly to doContent (by detecting XML_TOK_NONE) without processing any xml text declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. */ if (next == end && endPtr) { *endPtr = next; return XML_ERROR_NONE; } start = next; break; case XML_TOK_PARTIAL: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_PARTIAL_CHAR; } processor = externalEntityInitProcessor3; return externalEntityInitProcessor3(parser, start, end, endPtr); } static enum XML_Error PTRCALL externalEntityInitProcessor3(XML_Parser parser, const char *start, const char *end, const char **endPtr) { const char *next = start; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(encoding, start, end, &next); switch (tok) { case XML_TOK_XML_DECL: { enum XML_Error result = processXmlDecl(parser, 1, start, next); if (result != XML_ERROR_NONE) return result; start = next; } break; case XML_TOK_PARTIAL: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_PARTIAL_CHAR; } processor = externalEntityContentProcessor; tagLevel = 1; return externalEntityContentProcessor(parser, start, end, endPtr); } static enum XML_Error PTRCALL externalEntityContentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doContent(parser, 1, encoding, start, end, endPtr); if (result != XML_ERROR_NONE) return result; if (!storeRawNames(parser)) return XML_ERROR_NO_MEMORY; return result; } static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *s, const char *end, const char **nextPtr) { DTD * const dtd = _dtd; /* save one level of indirection */ const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } *eventPP = s; for (;;) { const char *next = s; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(enc, s, end, &next); *eventEndPP = next; switch (tok) { case XML_TOK_TRAILING_CR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } *eventEndPP = end; if (characterDataHandler) { XML_Char c = 0xA; characterDataHandler(handlerArg, &c, 1); } else if (defaultHandler) reportDefault(parser, enc, s, end); if (startTagLevel == 0) return XML_ERROR_NO_ELEMENTS; if (tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; return XML_ERROR_NONE; case XML_TOK_NONE: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } if (startTagLevel > 0) { if (tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; return XML_ERROR_NONE; } return XML_ERROR_NO_ELEMENTS; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { if (characterDataHandler) characterDataHandler(handlerArg, &ch, 1); else if (defaultHandler) reportDefault(parser, enc, s, next); break; } name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); poolDiscard(&dtd->pool); /* First, determine if a check for an existing declaration is needed; if yes, check that the entity exists, and that it is internal, otherwise call the skipped entity or default handler. */ if (!dtd->hasParamEntityRefs || dtd->standalone) { if (!entity) return XML_ERROR_UNDEFINED_ENTITY; else if (!entity->is_internal) return XML_ERROR_ENTITY_DECLARED_IN_PE; } else if (!entity) { if (skippedEntityHandler) skippedEntityHandler(handlerArg, name, 0); else if (defaultHandler) reportDefault(parser, enc, s, next); break; } if (entity->open) return XML_ERROR_RECURSIVE_ENTITY_REF; if (entity->notation) return XML_ERROR_BINARY_ENTITY_REF; if (entity->textPtr) { enum XML_Error result; OPEN_INTERNAL_ENTITY openEntity; if (!defaultExpandInternalEntities) { if (skippedEntityHandler) skippedEntityHandler(handlerArg, entity->name, 0); else if (defaultHandler) reportDefault(parser, enc, s, next); break; } entity->open = XML_TRUE; openEntity.next = openInternalEntities; openInternalEntities = &openEntity; openEntity.entity = entity; openEntity.internalEventPtr = NULL; openEntity.internalEventEndPtr = NULL; result = doContent(parser, tagLevel, internalEncoding, (char *)entity->textPtr, (char *)(entity->textPtr + entity->textLen), 0); entity->open = XML_FALSE; openInternalEntities = openEntity.next; if (result) return result; } else if (externalEntityRefHandler) { const XML_Char *context; entity->open = XML_TRUE; context = getContext(parser); entity->open = XML_FALSE; if (!context) return XML_ERROR_NO_MEMORY; if (!externalEntityRefHandler((XML_Parser)externalEntityRefHandlerArg, context, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; poolDiscard(&tempPool); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; } case XML_TOK_START_TAG_NO_ATTS: /* fall through */ case XML_TOK_START_TAG_WITH_ATTS: { TAG *tag; enum XML_Error result; XML_Char *toPtr; if (freeTagList) { tag = freeTagList; freeTagList = freeTagList->parent; } else { tag = (TAG *)MALLOC(sizeof(TAG)); if (!tag) return XML_ERROR_NO_MEMORY; tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE); if (!tag->buf) { FREE(tag); return XML_ERROR_NO_MEMORY; } tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; } tag->bindings = NULL; tag->parent = tagStack; tagStack = tag; tag->name.localPart = NULL; tag->name.prefix = NULL; tag->rawName = s + enc->minBytesPerChar; tag->rawNameLength = XmlNameLength(enc, tag->rawName); ++tagLevel; { const char *rawNameEnd = tag->rawName + tag->rawNameLength; const char *fromPtr = tag->rawName; toPtr = (XML_Char *)tag->buf; for (;;) { int bufSize; int convLen; XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); convLen = toPtr - (XML_Char *)tag->buf; if (fromPtr == rawNameEnd) { tag->name.strLen = convLen; break; } bufSize = (tag->bufEnd - tag->buf) << 1; { char *temp = (char *)REALLOC(tag->buf, bufSize); if (temp == NULL) return XML_ERROR_NO_MEMORY; tag->buf = temp; tag->bufEnd = temp + bufSize; toPtr = (XML_Char *)temp + convLen; } } } tag->name.str = (XML_Char *)tag->buf; *toPtr = XML_T('\0'); if (!startElementHandler && (tok == XML_TOK_START_TAG_NO_ATTS)) { if (defaultHandler) reportDefault(parser, enc, s, next); break; } result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); if (result) return result; if (startElementHandler) startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts); else if (defaultHandler) reportDefault(parser, enc, s, next); poolClear(&tempPool); break; } case XML_TOK_EMPTY_ELEMENT_NO_ATTS: if (!startElementHandler && !endElementHandler) { if (defaultHandler) reportDefault(parser, enc, s, next); if (tagLevel == 0) return epilogProcessor(parser, next, end, nextPtr); break; } /* fall through */ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: { const char *rawName = s + enc->minBytesPerChar; enum XML_Error result; BINDING *bindings = NULL; XML_Bool noElmHandlers = XML_TRUE; TAG_NAME name; name.str = poolStoreString(&tempPool, enc, rawName, rawName + XmlNameLength(enc, rawName)); if (!name.str) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); if (startElementHandler || (tok == XML_TOK_EMPTY_ELEMENT_WITH_ATTS)) { result = storeAtts(parser, enc, s, &name, &bindings); if (result) return result; poolFinish(&tempPool); } if (startElementHandler) { startElementHandler(handlerArg, name.str, (const XML_Char **)atts); noElmHandlers = XML_FALSE; } if (endElementHandler) { if (startElementHandler) *eventPP = *eventEndPP; endElementHandler(handlerArg, name.str); noElmHandlers = XML_FALSE; } if (noElmHandlers && defaultHandler) reportDefault(parser, enc, s, next); poolClear(&tempPool); while (bindings) { BINDING *b = bindings; if (endNamespaceDeclHandler) endNamespaceDeclHandler(handlerArg, b->prefix->name); bindings = bindings->nextTagBinding; b->nextTagBinding = freeBindingList; freeBindingList = b; b->prefix->binding = b->prevPrefixBinding; } } if (tagLevel == 0) return epilogProcessor(parser, next, end, nextPtr); break; case XML_TOK_END_TAG: if (tagLevel == startTagLevel) return XML_ERROR_ASYNC_ENTITY; else { int len; const char *rawName; TAG *tag = tagStack; tagStack = tag->parent; tag->parent = freeTagList; freeTagList = tag; rawName = s + enc->minBytesPerChar*2; len = XmlNameLength(enc, rawName); if (len != tag->rawNameLength || memcmp(tag->rawName, rawName, len) != 0) { *eventPP = rawName; return XML_ERROR_TAG_MISMATCH; } --tagLevel; if (endElementHandler) { const XML_Char *localPart; const XML_Char *prefix; XML_Char *uri; localPart = tag->name.localPart; if (ns && localPart) { /* localPart and prefix may have been overwritten in tag->name.str, since this points to the binding->uri buffer which gets re-used; so we have to add them again */ uri = (XML_Char *)tag->name.str + tag->name.uriLen; /* don't need to check for space - already done in storeAtts() */ while (*localPart) *uri++ = *localPart++; prefix = (XML_Char *)tag->name.prefix; if (ns_triplets && prefix) { *uri++ = namespaceSeparator; while (*prefix) *uri++ = *prefix++; } *uri = XML_T('\0'); } endElementHandler(handlerArg, tag->name.str); } else if (defaultHandler) reportDefault(parser, enc, s, next); while (tag->bindings) { BINDING *b = tag->bindings; if (endNamespaceDeclHandler) endNamespaceDeclHandler(handlerArg, b->prefix->name); tag->bindings = tag->bindings->nextTagBinding; b->nextTagBinding = freeBindingList; freeBindingList = b; b->prefix->binding = b->prevPrefixBinding; } if (tagLevel == 0) return epilogProcessor(parser, next, end, nextPtr); } break; case XML_TOK_CHAR_REF: { int n = XmlCharRefNumber(enc, s); if (n < 0) return XML_ERROR_BAD_CHAR_REF; if (characterDataHandler) { XML_Char buf[XML_ENCODE_MAX]; characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); } else if (defaultHandler) reportDefault(parser, enc, s, next); } break; case XML_TOK_XML_DECL: return XML_ERROR_MISPLACED_XML_PI; case XML_TOK_DATA_NEWLINE: if (characterDataHandler) { XML_Char c = 0xA; characterDataHandler(handlerArg, &c, 1); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_CDATA_SECT_OPEN: { enum XML_Error result; if (startCdataSectionHandler) startCdataSectionHandler(handlerArg); #if 0 /* Suppose you doing a transformation on a document that involves changing only the character data. You set up a defaultHandler and a characterDataHandler. The defaultHandler simply copies characters through. The characterDataHandler does the transformation and writes the characters out escaping them as necessary. This case will fail to work if we leave out the following two lines (because & and < inside CDATA sections will be incorrectly escaped). However, now we have a start/endCdataSectionHandler, so it seems easier to let the user deal with this. */ else if (characterDataHandler) characterDataHandler(handlerArg, dataBuf, 0); #endif else if (defaultHandler) reportDefault(parser, enc, s, next); result = doCdataSection(parser, enc, &next, end, nextPtr); if (!next) { processor = cdataSectionProcessor; return result; } } break; case XML_TOK_TRAILING_RSQB: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } if (characterDataHandler) { if (MUST_CONVERT(enc, s)) { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); } else characterDataHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); } else if (defaultHandler) reportDefault(parser, enc, s, end); if (startTagLevel == 0) { *eventPP = end; return XML_ERROR_NO_ELEMENTS; } if (tagLevel != startTagLevel) { *eventPP = end; return XML_ERROR_ASYNC_ENTITY; } return XML_ERROR_NONE; case XML_TOK_DATA_CHARS: if (characterDataHandler) { if (MUST_CONVERT(enc, s)) { for (;;) { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = s; characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); if (s == next) break; *eventPP = s; } } else characterDataHandler(handlerArg, (XML_Char *)s, (XML_Char *)next - (XML_Char *)s); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_PI: if (!reportProcessingInstruction(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_COMMENT: if (!reportComment(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; default: if (defaultHandler) reportDefault(parser, enc, s, next); break; } *eventPP = s = next; } /* not reached */ } /* If tagNamePtr is non-null, build a real list of attributes, otherwise just check the attributes for well-formedness. */ static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, TAG_NAME *tagNamePtr, BINDING **bindingsPtr) { DTD * const dtd = _dtd; /* save one level of indirection */ ELEMENT_TYPE *elementType = NULL; int nDefaultAtts = 0; const XML_Char **appAtts; /* the attribute list for the application */ int attIndex = 0; int prefixLen; int i; int n; XML_Char *uri; int nPrefixes = 0; BINDING *binding; const XML_Char *localPart; /* lookup the element type name */ if (tagNamePtr) { elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0); if (!elementType) { const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); if (!name) return XML_ERROR_NO_MEMORY; elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); if (!elementType) return XML_ERROR_NO_MEMORY; if (ns && !setElementTypePrefix(parser, elementType)) return XML_ERROR_NO_MEMORY; } nDefaultAtts = elementType->nDefaultAtts; } /* get the attributes from the tokenizer */ n = XmlGetAttributes(enc, attStr, attsSize, atts); if (n + nDefaultAtts > attsSize) { int oldAttsSize = attsSize; ATTRIBUTE *temp; attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); if (temp == NULL) return XML_ERROR_NO_MEMORY; atts = temp; if (n > oldAttsSize) XmlGetAttributes(enc, attStr, n, atts); } appAtts = (const XML_Char **)atts; for (i = 0; i < n; i++) { /* add the name and value to the attribute list */ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, atts[i].name + XmlNameLength(enc, atts[i].name)); if (!attId) return XML_ERROR_NO_MEMORY; /* detect duplicate attributes */ if ((attId->name)[-1]) { if (enc == encoding) eventPtr = atts[i].name; return XML_ERROR_DUPLICATE_ATTRIBUTE; } (attId->name)[-1] = 1; appAtts[attIndex++] = attId->name; if (!atts[i].normalized) { enum XML_Error result; XML_Bool isCdata = XML_TRUE; /* figure out whether declared as other than CDATA */ if (attId->maybeTokenized) { int j; for (j = 0; j < nDefaultAtts; j++) { if (attId == elementType->defaultAtts[j].id) { isCdata = elementType->defaultAtts[j].isCdata; break; } } } /* normalize the attribute value */ result = storeAttributeValue(parser, enc, isCdata, atts[i].valuePtr, atts[i].valueEnd, &tempPool); if (result) return result; if (tagNamePtr) { appAtts[attIndex] = poolStart(&tempPool); poolFinish(&tempPool); } else poolDiscard(&tempPool); } else if (tagNamePtr) { /* the value did not need normalizing */ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd); if (appAtts[attIndex] == 0) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); } /* handle prefixed attribute names */ if (attId->prefix && tagNamePtr) { if (attId->xmlns) { /* deal with namespace declarations here */ enum XML_Error result = addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr); if (result) return result; --attIndex; } else { /* deal with other prefixed names later */ attIndex++; nPrefixes++; (attId->name)[-1] = 2; } } else attIndex++; } if (tagNamePtr) { int j; nSpecifiedAtts = attIndex; if (elementType->idAtt && (elementType->idAtt->name)[-1]) { for (i = 0; i < attIndex; i += 2) if (appAtts[i] == elementType->idAtt->name) { idAttIndex = i; break; } } else idAttIndex = -1; /* do attribute defaulting */ for (j = 0; j < nDefaultAtts; j++) { const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j; if (!(da->id->name)[-1] && da->value) { if (da->id->prefix) { if (da->id->xmlns) { enum XML_Error result = addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr); if (result) return result; } else { (da->id->name)[-1] = 2; nPrefixes++; appAtts[attIndex++] = da->id->name; appAtts[attIndex++] = da->value; } } else { (da->id->name)[-1] = 1; appAtts[attIndex++] = da->id->name; appAtts[attIndex++] = da->value; } } } appAtts[attIndex] = 0; } i = 0; if (nPrefixes) { /* expand prefixed attribute names */ for (; i < attIndex; i += 2) { if (appAtts[i][-1] == 2) { ATTRIBUTE_ID *id; ((XML_Char *)(appAtts[i]))[-1] = 0; id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, appAtts[i], 0); if (id->prefix->binding) { int j; const BINDING *b = id->prefix->binding; const XML_Char *s = appAtts[i]; for (j = 0; j < b->uriLen; j++) { if (!poolAppendChar(&tempPool, b->uri[j])) return XML_ERROR_NO_MEMORY; } while (*s++ != XML_T(':')) ; do { if (!poolAppendChar(&tempPool, *s)) return XML_ERROR_NO_MEMORY; } while (*s++); if (ns_triplets) { tempPool.ptr[-1] = namespaceSeparator; s = b->prefix->name; do { if (!poolAppendChar(&tempPool, *s)) return XML_ERROR_NO_MEMORY; } while (*s++); } appAtts[i] = poolStart(&tempPool); poolFinish(&tempPool); } if (!--nPrefixes) break; } else ((XML_Char *)(appAtts[i]))[-1] = 0; } } /* clear the flags that say whether attributes were specified */ for (; i < attIndex; i += 2) ((XML_Char *)(appAtts[i]))[-1] = 0; if (!tagNamePtr) return XML_ERROR_NONE; for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) binding->attId->name[-1] = 0; /* expand the element type name */ if (elementType->prefix) { binding = elementType->prefix->binding; if (!binding) return XML_ERROR_NONE; localPart = tagNamePtr->str; while (*localPart++ != XML_T(':')) ; } else if (dtd->defaultPrefix.binding) { binding = dtd->defaultPrefix.binding; localPart = tagNamePtr->str; } else return XML_ERROR_NONE; prefixLen = 0; if (ns && ns_triplets && binding->prefix->name) { for (; binding->prefix->name[prefixLen++];) ; } tagNamePtr->localPart = localPart; tagNamePtr->uriLen = binding->uriLen; tagNamePtr->prefix = binding->prefix->name; tagNamePtr->prefixLen = prefixLen; for (i = 0; localPart[i++];) ; n = i + binding->uriLen + prefixLen; if (n > binding->uriAlloc) { TAG *p; uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char)); if (!uri) return XML_ERROR_NO_MEMORY; binding->uriAlloc = n + EXPAND_SPARE; memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); for (p = tagStack; p; p = p->parent) if (p->name.str == binding->uri) p->name.str = uri; FREE(binding->uri); binding->uri = uri; } uri = binding->uri + binding->uriLen; memcpy(uri, localPart, i * sizeof(XML_Char)); if (prefixLen) { uri = uri + (i - 1); if (namespaceSeparator) { *(uri) = namespaceSeparator; } memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); } tagNamePtr->str = binding->uri; return XML_ERROR_NONE; } /* addBinding() overwrites the value of prefix->binding without checking. Therefore one must keep track of the old value outside of addBinding(). */ static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) { BINDING *b; int len; /* empty string is only valid when there is no prefix per XML NS 1.0 */ if (*uri == XML_T('\0') && prefix->name) return XML_ERROR_SYNTAX; for (len = 0; uri[len]; len++) ; if (namespaceSeparator) len++; if (freeBindingList) { b = freeBindingList; if (len > b->uriAlloc) { XML_Char *temp = (XML_Char *)REALLOC(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (temp == NULL) return XML_ERROR_NO_MEMORY; b->uri = temp; b->uriAlloc = len + EXPAND_SPARE; } freeBindingList = b->nextTagBinding; } else { b = (BINDING *)MALLOC(sizeof(BINDING)); if (!b) return XML_ERROR_NO_MEMORY; b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE)); if (!b->uri) { FREE(b); return XML_ERROR_NO_MEMORY; } b->uriAlloc = len + EXPAND_SPARE; } b->uriLen = len; memcpy(b->uri, uri, len * sizeof(XML_Char)); if (namespaceSeparator) b->uri[len - 1] = namespaceSeparator; b->prefix = prefix; b->attId = attId; b->prevPrefixBinding = prefix->binding; if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix) prefix->binding = NULL; else prefix->binding = b; b->nextTagBinding = *bindingsPtr; *bindingsPtr = b; if (startNamespaceDeclHandler) startNamespaceDeclHandler(handlerArg, prefix->name, prefix->binding ? uri : 0); return XML_ERROR_NONE; } /* The idea here is to avoid using stack for each CDATA section when the whole file is parsed with one call. */ static enum XML_Error PTRCALL cdataSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr); if (start) { if (parentParser) { /* we are parsing an external entity */ processor = externalEntityContentProcessor; return externalEntityContentProcessor(parser, start, end, endPtr); } else { processor = contentProcessor; return contentProcessor(parser, start, end, endPtr); } } return result; } /* startPtr gets set to non-null is the section is closed, and to null if the section is not yet closed. */ static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr) { const char *s = *startPtr; const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; *eventPP = s; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } *eventPP = s; *startPtr = NULL; for (;;) { const char *next; int tok = XmlCdataSectionTok(enc, s, end, &next); *eventEndPP = next; switch (tok) { case XML_TOK_CDATA_SECT_CLOSE: if (endCdataSectionHandler) endCdataSectionHandler(handlerArg); #if 0 /* see comment under XML_TOK_CDATA_SECT_OPEN */ else if (characterDataHandler) characterDataHandler(handlerArg, dataBuf, 0); #endif else if (defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; return XML_ERROR_NONE; case XML_TOK_DATA_NEWLINE: if (characterDataHandler) { XML_Char c = 0xA; characterDataHandler(handlerArg, &c, 1); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_DATA_CHARS: if (characterDataHandler) { if (MUST_CONVERT(enc, s)) { for (;;) { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = next; characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); if (s == next) break; *eventPP = s; } } else characterDataHandler(handlerArg, (XML_Char *)s, (XML_Char *)next - (XML_Char *)s); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_CDATA_SECTION; default: *eventPP = next; return XML_ERROR_UNEXPECTED_STATE; } *eventPP = s = next; } /* not reached */ } #ifdef XML_DTD /* The idea here is to avoid using stack for each IGNORE section when the whole file is parsed with one call. */ static enum XML_Error PTRCALL ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, endPtr); if (start) { processor = prologProcessor; return prologProcessor(parser, start, end, endPtr); } return result; } /* startPtr gets set to non-null is the section is closed, and to null if the section is not yet closed. */ static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr) { const char *next; int tok; const char *s = *startPtr; const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; *eventPP = s; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } *eventPP = s; *startPtr = NULL; tok = XmlIgnoreSectionTok(enc, s, end, &next); *eventEndPP = next; switch (tok) { case XML_TOK_IGNORE_SECT: if (defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; return XML_ERROR_NONE; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ default: *eventPP = next; return XML_ERROR_UNEXPECTED_STATE; } /* not reached */ } #endif /* XML_DTD */ static enum XML_Error initializeEncoding(XML_Parser parser) { const char *s; #ifdef XML_UNICODE char encodingBuf[128]; if (!protocolEncodingName) s = NULL; else { int i; for (i = 0; protocolEncodingName[i]; i++) { if (i == sizeof(encodingBuf) - 1 || (protocolEncodingName[i] & ~0x7f) != 0) { encodingBuf[0] = '\0'; break; } encodingBuf[i] = (char)protocolEncodingName[i]; } encodingBuf[i] = '\0'; s = encodingBuf; } #else s = protocolEncodingName; #endif if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) return XML_ERROR_NONE; return handleUnknownEncoding(parser, protocolEncodingName); } static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s, const char *next) { const char *encodingName = NULL; const XML_Char *storedEncName = NULL; const ENCODING *newEncoding = NULL; const char *version = NULL; const char *versionend; const XML_Char *storedversion = NULL; int standalone = -1; if (!(ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(isGeneralTextEntity, encoding, s, next, &eventPtr, &version, &versionend, &encodingName, &newEncoding, &standalone)) return XML_ERROR_SYNTAX; if (!isGeneralTextEntity && standalone == 1) { _dtd->standalone = XML_TRUE; #ifdef XML_DTD if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif /* XML_DTD */ } if (xmlDeclHandler) { if (encodingName != NULL) { storedEncName = poolStoreString(&temp2Pool, encoding, encodingName, encodingName + XmlNameLength(encoding, encodingName)); if (!storedEncName) return XML_ERROR_NO_MEMORY; poolFinish(&temp2Pool); } if (version) { storedversion = poolStoreString(&temp2Pool, encoding, version, versionend - encoding->minBytesPerChar); if (!storedversion) return XML_ERROR_NO_MEMORY; } xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone); } else if (defaultHandler) reportDefault(parser, encoding, s, next); if (protocolEncodingName == NULL) { if (newEncoding) { if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { eventPtr = encodingName; return XML_ERROR_INCORRECT_ENCODING; } encoding = newEncoding; } else if (encodingName) { enum XML_Error result; if (!storedEncName) { storedEncName = poolStoreString( &temp2Pool, encoding, encodingName, encodingName + XmlNameLength(encoding, encodingName)); if (!storedEncName) return XML_ERROR_NO_MEMORY; } result = handleUnknownEncoding(parser, storedEncName); poolClear(&temp2Pool); if (result == XML_ERROR_UNKNOWN_ENCODING) eventPtr = encodingName; return result; } } if (storedEncName || storedversion) poolClear(&temp2Pool); return XML_ERROR_NONE; } static enum XML_Error handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) { if (unknownEncodingHandler) { XML_Encoding info; int i; for (i = 0; i < 256; i++) info.map[i] = -1; info.convert = NULL; info.data = NULL; info.release = NULL; if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) { ENCODING *enc; unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding()); if (!unknownEncodingMem) { if (info.release) info.release(info.data); return XML_ERROR_NO_MEMORY; } enc = (ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)(unknownEncodingMem, info.map, info.convert, info.data); if (enc) { unknownEncodingData = info.data; unknownEncodingRelease = info.release; encoding = enc; return XML_ERROR_NONE; } } if (info.release != NULL) info.release(info.data); } return XML_ERROR_UNKNOWN_ENCODING; } static enum XML_Error PTRCALL prologInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; processor = prologProcessor; return prologProcessor(parser, s, end, nextPtr); } #ifdef XML_DTD static enum XML_Error PTRCALL externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; /* we know now that XML_Parse(Buffer) has been called, so we consider the external parameter entity read */ _dtd->paramEntityRead = XML_TRUE; if (prologState.inEntityValue) { processor = entityValueInitProcessor; return entityValueInitProcessor(parser, s, end, nextPtr); } else { processor = externalParEntProcessor; return externalParEntProcessor(parser, s, end, nextPtr); } } static enum XML_Error PTRCALL entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *start = s; const char *next = s; int tok; for (;;) { tok = XmlPrologTok(encoding, start, end, &next); if (tok <= 0) { if (nextPtr != 0 && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } return storeEntityValue(parser, encoding, s, end); } else if (tok == XML_TOK_XML_DECL) { enum XML_Error result = processXmlDecl(parser, 0, start, next); if (result != XML_ERROR_NONE) return result; if (nextPtr) *nextPtr = next; /* stop scanning for text declaration - we found one */ processor = entityValueProcessor; return entityValueProcessor(parser, next, end, nextPtr); } /* If we are at the end of the buffer, this would cause XmlPrologTok to return XML_TOK_NONE on the next call, which would then cause the function to exit with *nextPtr set to s - that is what we want for other tokens, but not for the BOM - we would rather like to skip it; then, when this routine is entered the next time, XmlPrologTok will return XML_TOK_INVALID, since the BOM is still in the buffer */ else if (tok == XML_TOK_BOM && next == end && nextPtr) { *nextPtr = next; return XML_ERROR_NONE; } start = next; } } static enum XML_Error PTRCALL externalParEntProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *start = s; const char *next = s; int tok; tok = XmlPrologTok(encoding, start, end, &next); if (tok <= 0) { if (nextPtr != 0 && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } } /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. However, when parsing an external subset, doProlog will not accept a BOM as valid, and report a syntax error, so we have to skip the BOM */ else if (tok == XML_TOK_BOM) { s = next; tok = XmlPrologTok(encoding, s, end, &next); } processor = prologProcessor; return doProlog(parser, encoding, s, end, tok, next, nextPtr); } static enum XML_Error PTRCALL entityValueProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *start = s; const char *next = s; const ENCODING *enc = encoding; int tok; for (;;) { tok = XmlPrologTok(enc, start, end, &next); if (tok <= 0) { if (nextPtr != 0 && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } return storeEntityValue(parser, enc, s, end); } start = next; } } #endif /* XML_DTD */ static enum XML_Error PTRCALL prologProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *next = s; int tok = XmlPrologTok(encoding, s, end, &next); return doProlog(parser, encoding, s, end, tok, next, nextPtr); } static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr) { #ifdef XML_DTD static const XML_Char externalSubsetName[] = { '#' , '\0' }; #endif /* XML_DTD */ static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' }; static const XML_Char atypeID[] = { 'I', 'D', '\0' }; static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' }; static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' }; static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' }; static const XML_Char atypeENTITIES[] = { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' }; static const XML_Char atypeNMTOKEN[] = { 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' }; static const XML_Char atypeNMTOKENS[] = { 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' }; static const XML_Char notationPrefix[] = { 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' }; static const XML_Char enumValueSep[] = { '|', '\0' }; static const XML_Char enumValueStart[] = { '(', '\0' }; DTD * const dtd = _dtd; /* save one level of indirection */ const char **eventPP; const char **eventEndPP; enum XML_Content_Quant quant; if (enc == encoding) { eventPP = &eventPtr; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } for (;;) { int role; XML_Bool handleDefault = XML_TRUE; *eventPP = s; *eventEndPP = next; if (tok <= 0) { if (nextPtr != 0 && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: #ifdef XML_DTD if (enc != encoding) return XML_ERROR_NONE; if (isParamEntity) { if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) == XML_ROLE_ERROR) return XML_ERROR_SYNTAX; return XML_ERROR_NONE; } #endif /* XML_DTD */ return XML_ERROR_NO_ELEMENTS; default: tok = -tok; next = end; break; } } role = XmlTokenRole(&prologState, tok, s, next, enc); switch (role) { case XML_ROLE_XML_DECL: { enum XML_Error result = processXmlDecl(parser, 0, s, next); if (result != XML_ERROR_NONE) return result; enc = encoding; handleDefault = XML_FALSE; } break; case XML_ROLE_DOCTYPE_NAME: if (startDoctypeDeclHandler) { doctypeName = poolStoreString(&tempPool, enc, s, next); if (!doctypeName) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); doctypePubid = NULL; handleDefault = XML_FALSE; } doctypeSysid = NULL; /* always initialize to NULL */ break; case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: if (startDoctypeDeclHandler) { startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, doctypePubid, 1); doctypeName = NULL; poolClear(&tempPool); handleDefault = XML_FALSE; } break; #ifdef XML_DTD case XML_ROLE_TEXT_DECL: { enum XML_Error result = processXmlDecl(parser, 1, s, next); if (result != XML_ERROR_NONE) return result; enc = encoding; handleDefault = XML_FALSE; } break; #endif /* XML_DTD */ case XML_ROLE_DOCTYPE_PUBLIC_ID: #ifdef XML_DTD useForeignDTD = XML_FALSE; #endif /* XML_DTD */ dtd->hasParamEntityRefs = XML_TRUE; if (startDoctypeDeclHandler) { doctypePubid = poolStoreString(&tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!doctypePubid) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); handleDefault = XML_FALSE; } #ifdef XML_DTD declEntity = (ENTITY *)lookup(&dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; #endif /* XML_DTD */ /* fall through */ case XML_ROLE_ENTITY_PUBLIC_ID: if (!XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_SYNTAX; if (dtd->keepProcessing && declEntity) { XML_Char *tem = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!tem) return XML_ERROR_NO_MEMORY; normalizePublicId(tem); declEntity->publicId = tem; poolFinish(&dtd->pool); if (entityDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_DOCTYPE_CLOSE: if (doctypeName) { startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, doctypePubid, 0); poolClear(&tempPool); handleDefault = XML_FALSE; } /* doctypeSysid will be non-NULL in the case of a previous XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler was not set, indicating an external subset */ #ifdef XML_DTD if (doctypeSysid || useForeignDTD) { dtd->hasParamEntityRefs = XML_TRUE; /* when docTypeSysid == NULL */ if (paramEntityParsing && externalEntityRefHandler) { ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (!entity) return XML_ERROR_NO_MEMORY; if (useForeignDTD) entity->base = curBase; dtd->paramEntityRead = XML_FALSE; if (!externalEntityRefHandler(externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; if (dtd->paramEntityRead && !dtd->standalone && notStandaloneHandler && !notStandaloneHandler(handlerArg)) return XML_ERROR_NOT_STANDALONE; /* end of DTD - no need to update dtd->keepProcessing */ } useForeignDTD = XML_FALSE; } #endif /* XML_DTD */ if (endDoctypeDeclHandler) { endDoctypeDeclHandler(handlerArg); handleDefault = XML_FALSE; } break; case XML_ROLE_INSTANCE_START: #ifdef XML_DTD /* if there is no DOCTYPE declaration then now is the last chance to read the foreign DTD */ if (useForeignDTD) { dtd->hasParamEntityRefs = XML_TRUE; if (paramEntityParsing && externalEntityRefHandler) { ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (!entity) return XML_ERROR_NO_MEMORY; entity->base = curBase; dtd->paramEntityRead = XML_FALSE; if (!externalEntityRefHandler(externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; if (dtd->paramEntityRead && !dtd->standalone && notStandaloneHandler && !notStandaloneHandler(handlerArg)) return XML_ERROR_NOT_STANDALONE; /* end of DTD - no need to update dtd->keepProcessing */ } } #endif /* XML_DTD */ processor = contentProcessor; return contentProcessor(parser, s, end, nextPtr); case XML_ROLE_ATTLIST_ELEMENT_NAME: declElementType = getElementType(parser, enc, s, next); if (!declElementType) return XML_ERROR_NO_MEMORY; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_NAME: declAttributeId = getAttributeId(parser, enc, s, next); if (!declAttributeId) return XML_ERROR_NO_MEMORY; declAttributeIsCdata = XML_FALSE; declAttributeType = NULL; declAttributeIsId = XML_FALSE; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_CDATA: declAttributeIsCdata = XML_TRUE; declAttributeType = atypeCDATA; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_ID: declAttributeIsId = XML_TRUE; declAttributeType = atypeID; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_IDREF: declAttributeType = atypeIDREF; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: declAttributeType = atypeIDREFS; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: declAttributeType = atypeENTITY; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: declAttributeType = atypeENTITIES; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: declAttributeType = atypeNMTOKEN; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: declAttributeType = atypeNMTOKENS; checkAttListDeclHandler: if (dtd->keepProcessing && attlistDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ATTRIBUTE_ENUM_VALUE: case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: if (dtd->keepProcessing && attlistDeclHandler) { const XML_Char *prefix; if (declAttributeType) { prefix = enumValueSep; } else { prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE ? notationPrefix : enumValueStart); } if (!poolAppendString(&tempPool, prefix)) return XML_ERROR_NO_MEMORY; if (!poolAppend(&tempPool, enc, s, next)) return XML_ERROR_NO_MEMORY; declAttributeType = tempPool.start; handleDefault = XML_FALSE; } break; case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: if (dtd->keepProcessing) { if (!defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, declAttributeIsId, 0, parser)) return XML_ERROR_NO_MEMORY; if (attlistDeclHandler && declAttributeType) { if (*declAttributeType == XML_T('(') || (*declAttributeType == XML_T('N') && declAttributeType[1] == XML_T('O'))) { /* Enumerated or Notation type */ if (!poolAppendChar(&tempPool, XML_T(')')) || !poolAppendChar(&tempPool, XML_T('\0'))) return XML_ERROR_NO_MEMORY; declAttributeType = tempPool.start; poolFinish(&tempPool); } *eventEndPP = s; attlistDeclHandler(handlerArg, declElementType->name, declAttributeId->name, declAttributeType, 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); poolClear(&tempPool); handleDefault = XML_FALSE; } } break; case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: case XML_ROLE_FIXED_ATTRIBUTE_VALUE: if (dtd->keepProcessing) { const XML_Char *attVal; enum XML_Error result = storeAttributeValue(parser, enc, declAttributeIsCdata, s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool); if (result) return result; attVal = poolStart(&dtd->pool); poolFinish(&dtd->pool); /* ID attributes aren't allowed to have a default */ if (!defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, XML_FALSE, attVal, parser)) return XML_ERROR_NO_MEMORY; if (attlistDeclHandler && declAttributeType) { if (*declAttributeType == XML_T('(') || (*declAttributeType == XML_T('N') && declAttributeType[1] == XML_T('O'))) { /* Enumerated or Notation type */ if (!poolAppendChar(&tempPool, XML_T(')')) || !poolAppendChar(&tempPool, XML_T('\0'))) return XML_ERROR_NO_MEMORY; declAttributeType = tempPool.start; poolFinish(&tempPool); } *eventEndPP = s; attlistDeclHandler(handlerArg, declElementType->name, declAttributeId->name, declAttributeType, attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); poolClear(&tempPool); handleDefault = XML_FALSE; } } break; case XML_ROLE_ENTITY_VALUE: if (dtd->keepProcessing) { enum XML_Error result = storeEntityValue(parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (declEntity) { declEntity->textPtr = poolStart(&dtd->entityValuePool); declEntity->textLen = poolLength(&dtd->entityValuePool); poolFinish(&dtd->entityValuePool); if (entityDeclHandler) { *eventEndPP = s; entityDeclHandler(handlerArg, declEntity->name, declEntity->is_param, declEntity->textPtr, declEntity->textLen, curBase, 0, 0, 0); handleDefault = XML_FALSE; } } else poolDiscard(&dtd->entityValuePool); if (result != XML_ERROR_NONE) return result; } break; case XML_ROLE_DOCTYPE_SYSTEM_ID: #ifdef XML_DTD useForeignDTD = XML_FALSE; #endif /* XML_DTD */ dtd->hasParamEntityRefs = XML_TRUE; if (startDoctypeDeclHandler) { doctypeSysid = poolStoreString(&tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (doctypeSysid == NULL) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); handleDefault = XML_FALSE; } #ifdef XML_DTD else /* use externalSubsetName to make doctypeSysid non-NULL for the case where no startDoctypeDeclHandler is set */ doctypeSysid = externalSubsetName; #endif /* XML_DTD */ if (!dtd->standalone #ifdef XML_DTD && !paramEntityParsing #endif /* XML_DTD */ && notStandaloneHandler && !notStandaloneHandler(handlerArg)) return XML_ERROR_NOT_STANDALONE; #ifndef XML_DTD break; #else /* XML_DTD */ if (!declEntity) { declEntity = (ENTITY *)lookup(&dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; declEntity->publicId = NULL; } /* fall through */ #endif /* XML_DTD */ case XML_ROLE_ENTITY_SYSTEM_ID: if (dtd->keepProcessing && declEntity) { declEntity->systemId = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!declEntity->systemId) return XML_ERROR_NO_MEMORY; declEntity->base = curBase; poolFinish(&dtd->pool); if (entityDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_ENTITY_COMPLETE: if (dtd->keepProcessing && declEntity && entityDeclHandler) { *eventEndPP = s; entityDeclHandler(handlerArg, declEntity->name, declEntity->is_param, 0,0, declEntity->base, declEntity->systemId, declEntity->publicId, 0); handleDefault = XML_FALSE; } break; case XML_ROLE_ENTITY_NOTATION_NAME: if (dtd->keepProcessing && declEntity) { declEntity->notation = poolStoreString(&dtd->pool, enc, s, next); if (!declEntity->notation) return XML_ERROR_NO_MEMORY; poolFinish(&dtd->pool); if (unparsedEntityDeclHandler) { *eventEndPP = s; unparsedEntityDeclHandler(handlerArg, declEntity->name, declEntity->base, declEntity->systemId, declEntity->publicId, declEntity->notation); handleDefault = XML_FALSE; } else if (entityDeclHandler) { *eventEndPP = s; entityDeclHandler(handlerArg, declEntity->name, 0,0,0, declEntity->base, declEntity->systemId, declEntity->publicId, declEntity->notation); handleDefault = XML_FALSE; } } break; case XML_ROLE_GENERAL_ENTITY_NAME: { if (XmlPredefinedEntityName(enc, s, next)) { declEntity = NULL; break; } if (dtd->keepProcessing) { const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY; declEntity = (ENTITY *)lookup(&dtd->generalEntities, name, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; if (declEntity->name != name) { poolDiscard(&dtd->pool); declEntity = NULL; } else { poolFinish(&dtd->pool); declEntity->publicId = NULL; declEntity->is_param = XML_FALSE; /* if we have a parent parser or are reading an internal parameter entity, then the entity declaration is not considered "internal" */ declEntity->is_internal = !(parentParser || openInternalEntities); if (entityDeclHandler) handleDefault = XML_FALSE; } } else { poolDiscard(&dtd->pool); declEntity = NULL; } } break; case XML_ROLE_PARAM_ENTITY_NAME: #ifdef XML_DTD if (dtd->keepProcessing) { const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY; declEntity = (ENTITY *)lookup(&dtd->paramEntities, name, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; if (declEntity->name != name) { poolDiscard(&dtd->pool); declEntity = NULL; } else { poolFinish(&dtd->pool); declEntity->publicId = NULL; declEntity->is_param = XML_TRUE; /* if we have a parent parser or are reading an internal parameter entity, then the entity declaration is not considered "internal" */ declEntity->is_internal = !(parentParser || openInternalEntities); if (entityDeclHandler) handleDefault = XML_FALSE; } } else { poolDiscard(&dtd->pool); declEntity = NULL; } #else /* not XML_DTD */ declEntity = NULL; #endif /* XML_DTD */ break; case XML_ROLE_NOTATION_NAME: declNotationPublicId = NULL; declNotationName = NULL; if (notationDeclHandler) { declNotationName = poolStoreString(&tempPool, enc, s, next); if (!declNotationName) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); handleDefault = XML_FALSE; } break; case XML_ROLE_NOTATION_PUBLIC_ID: if (!XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_SYNTAX; if (declNotationName) { /* means notationDeclHandler != NULL */ XML_Char *tem = poolStoreString(&tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!tem) return XML_ERROR_NO_MEMORY; normalizePublicId(tem); declNotationPublicId = tem; poolFinish(&tempPool); handleDefault = XML_FALSE; } break; case XML_ROLE_NOTATION_SYSTEM_ID: if (declNotationName && notationDeclHandler) { const XML_Char *systemId = poolStoreString(&tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!systemId) return XML_ERROR_NO_MEMORY; *eventEndPP = s; notationDeclHandler(handlerArg, declNotationName, curBase, systemId, declNotationPublicId); handleDefault = XML_FALSE; } poolClear(&tempPool); break; case XML_ROLE_NOTATION_NO_SYSTEM_ID: if (declNotationPublicId && notationDeclHandler) { *eventEndPP = s; notationDeclHandler(handlerArg, declNotationName, curBase, 0, declNotationPublicId); handleDefault = XML_FALSE; } poolClear(&tempPool); break; case XML_ROLE_ERROR: switch (tok) { case XML_TOK_PARAM_ENTITY_REF: return XML_ERROR_PARAM_ENTITY_REF; case XML_TOK_XML_DECL: return XML_ERROR_MISPLACED_XML_PI; default: return XML_ERROR_SYNTAX; } #ifdef XML_DTD case XML_ROLE_IGNORE_SECT: { enum XML_Error result; if (defaultHandler) reportDefault(parser, enc, s, next); handleDefault = XML_FALSE; result = doIgnoreSection(parser, enc, &next, end, nextPtr); if (!next) { processor = ignoreSectionProcessor; return result; } } break; #endif /* XML_DTD */ case XML_ROLE_GROUP_OPEN: if (prologState.level >= groupSize) { if (groupSize) { char *temp = (char *)REALLOC(groupConnector, groupSize *= 2); if (temp == NULL) return XML_ERROR_NO_MEMORY; groupConnector = temp; if (dtd->scaffIndex) { int *temp = (int *)REALLOC(dtd->scaffIndex, groupSize * sizeof(int)); if (temp == NULL) return XML_ERROR_NO_MEMORY; dtd->scaffIndex = temp; } } else { groupConnector = (char *)MALLOC(groupSize = 32); if (!groupConnector) return XML_ERROR_NO_MEMORY; } } groupConnector[prologState.level] = 0; if (dtd->in_eldecl) { int myindex = nextScaffoldPart(parser); if (myindex < 0) return XML_ERROR_NO_MEMORY; dtd->scaffIndex[dtd->scaffLevel] = myindex; dtd->scaffLevel++; dtd->scaffold[myindex].type = XML_CTYPE_SEQ; if (elementDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_GROUP_SEQUENCE: if (groupConnector[prologState.level] == '|') return XML_ERROR_SYNTAX; groupConnector[prologState.level] = ','; if (dtd->in_eldecl && elementDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_GROUP_CHOICE: if (groupConnector[prologState.level] == ',') return XML_ERROR_SYNTAX; if (dtd->in_eldecl && !groupConnector[prologState.level] && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type != XML_CTYPE_MIXED) ) { dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type = XML_CTYPE_CHOICE; if (elementDeclHandler) handleDefault = XML_FALSE; } groupConnector[prologState.level] = '|'; break; case XML_ROLE_PARAM_ENTITY_REF: #ifdef XML_DTD case XML_ROLE_INNER_PARAM_ENTITY_REF: /* PE references in internal subset are not allowed within declarations */ if (prologState.documentEntity && role == XML_ROLE_INNER_PARAM_ENTITY_REF) return XML_ERROR_PARAM_ENTITY_REF; dtd->hasParamEntityRefs = XML_TRUE; if (!paramEntityParsing) dtd->keepProcessing = dtd->standalone; else { const XML_Char *name; ENTITY *entity; name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); poolDiscard(&dtd->pool); /* first, determine if a check for an existing declaration is needed; if yes, check that the entity exists, and that it is internal, otherwise call the skipped entity handler */ if (prologState.documentEntity && (dtd->standalone ? !openInternalEntities : !dtd->hasParamEntityRefs)) { if (!entity) return XML_ERROR_UNDEFINED_ENTITY; else if (!entity->is_internal) return XML_ERROR_ENTITY_DECLARED_IN_PE; } else if (!entity) { dtd->keepProcessing = dtd->standalone; /* cannot report skipped entities in declarations */ if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) { skippedEntityHandler(handlerArg, name, 1); handleDefault = XML_FALSE; } break; } if (entity->open) return XML_ERROR_RECURSIVE_ENTITY_REF; if (entity->textPtr) { enum XML_Error result; result = processInternalParamEntity(parser, entity); if (result != XML_ERROR_NONE) return result; handleDefault = XML_FALSE; break; } if (externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; if (!externalEntityRefHandler(externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { entity->open = XML_FALSE; return XML_ERROR_EXTERNAL_ENTITY_HANDLING; } entity->open = XML_FALSE; handleDefault = XML_FALSE; if (!dtd->paramEntityRead) { dtd->keepProcessing = dtd->standalone; break; } } else { dtd->keepProcessing = dtd->standalone; break; } } #endif /* XML_DTD */ if (!dtd->standalone && notStandaloneHandler && !notStandaloneHandler(handlerArg)) return XML_ERROR_NOT_STANDALONE; break; /* Element declaration stuff */ case XML_ROLE_ELEMENT_NAME: if (elementDeclHandler) { declElementType = getElementType(parser, enc, s, next); if (!declElementType) return XML_ERROR_NO_MEMORY; dtd->scaffLevel = 0; dtd->scaffCount = 0; dtd->in_eldecl = XML_TRUE; handleDefault = XML_FALSE; } break; case XML_ROLE_CONTENT_ANY: case XML_ROLE_CONTENT_EMPTY: if (dtd->in_eldecl) { if (elementDeclHandler) { XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content)); if (!content) return XML_ERROR_NO_MEMORY; content->quant = XML_CQUANT_NONE; content->name = NULL; content->numchildren = 0; content->children = NULL; content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY : XML_CTYPE_EMPTY); *eventEndPP = s; elementDeclHandler(handlerArg, declElementType->name, content); handleDefault = XML_FALSE; } dtd->in_eldecl = XML_FALSE; } break; case XML_ROLE_CONTENT_PCDATA: if (dtd->in_eldecl) { dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type = XML_CTYPE_MIXED; if (elementDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_CONTENT_ELEMENT: quant = XML_CQUANT_NONE; goto elementContent; case XML_ROLE_CONTENT_ELEMENT_OPT: quant = XML_CQUANT_OPT; goto elementContent; case XML_ROLE_CONTENT_ELEMENT_REP: quant = XML_CQUANT_REP; goto elementContent; case XML_ROLE_CONTENT_ELEMENT_PLUS: quant = XML_CQUANT_PLUS; elementContent: if (dtd->in_eldecl) { ELEMENT_TYPE *el; const XML_Char *name; int nameLen; const char *nxt = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar); int myindex = nextScaffoldPart(parser); if (myindex < 0) return XML_ERROR_NO_MEMORY; dtd->scaffold[myindex].type = XML_CTYPE_NAME; dtd->scaffold[myindex].quant = quant; el = getElementType(parser, enc, s, nxt); if (!el) return XML_ERROR_NO_MEMORY; name = el->name; dtd->scaffold[myindex].name = name; nameLen = 0; for (; name[nameLen++]; ); dtd->contentStringLen += nameLen; if (elementDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_GROUP_CLOSE: quant = XML_CQUANT_NONE; goto closeGroup; case XML_ROLE_GROUP_CLOSE_OPT: quant = XML_CQUANT_OPT; goto closeGroup; case XML_ROLE_GROUP_CLOSE_REP: quant = XML_CQUANT_REP; goto closeGroup; case XML_ROLE_GROUP_CLOSE_PLUS: quant = XML_CQUANT_PLUS; closeGroup: if (dtd->in_eldecl) { if (elementDeclHandler) handleDefault = XML_FALSE; dtd->scaffLevel--; dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant; if (dtd->scaffLevel == 0) { if (!handleDefault) { XML_Content *model = build_model(parser); if (!model) return XML_ERROR_NO_MEMORY; *eventEndPP = s; elementDeclHandler(handlerArg, declElementType->name, model); } dtd->in_eldecl = XML_FALSE; dtd->contentStringLen = 0; } } break; /* End element declaration stuff */ case XML_ROLE_PI: if (!reportProcessingInstruction(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; handleDefault = XML_FALSE; break; case XML_ROLE_COMMENT: if (!reportComment(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; handleDefault = XML_FALSE; break; case XML_ROLE_NONE: switch (tok) { case XML_TOK_BOM: handleDefault = XML_FALSE; break; } break; case XML_ROLE_DOCTYPE_NONE: if (startDoctypeDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ENTITY_NONE: if (dtd->keepProcessing && entityDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_NOTATION_NONE: if (notationDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ATTLIST_NONE: if (dtd->keepProcessing && attlistDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ELEMENT_NONE: if (elementDeclHandler) handleDefault = XML_FALSE; break; } /* end of big switch */ if (handleDefault && defaultHandler) reportDefault(parser, enc, s, next); s = next; tok = XmlPrologTok(enc, s, end, &next); } /* not reached */ } static enum XML_Error PTRCALL epilogProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { processor = epilogProcessor; eventPtr = s; for (;;) { const char *next = NULL; int tok = XmlPrologTok(encoding, s, end, &next); eventEndPtr = next; switch (tok) { /* report partial linebreak - it might be the last token */ case -XML_TOK_PROLOG_S: if (defaultHandler) { eventEndPtr = next; reportDefault(parser, encoding, s, next); } if (nextPtr) *nextPtr = next; return XML_ERROR_NONE; case XML_TOK_NONE: if (nextPtr) *nextPtr = s; return XML_ERROR_NONE; case XML_TOK_PROLOG_S: if (defaultHandler) reportDefault(parser, encoding, s, next); break; case XML_TOK_PI: if (!reportProcessingInstruction(parser, encoding, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_COMMENT: if (!reportComment(parser, encoding, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_INVALID: eventPtr = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; default: return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; } eventPtr = s = next; } } #ifdef XML_DTD static enum XML_Error processInternalParamEntity(XML_Parser parser, ENTITY *entity) { const char *s, *end, *next; int tok; enum XML_Error result; OPEN_INTERNAL_ENTITY openEntity; entity->open = XML_TRUE; openEntity.next = openInternalEntities; openInternalEntities = &openEntity; openEntity.entity = entity; openEntity.internalEventPtr = NULL; openEntity.internalEventEndPtr = NULL; s = (char *)entity->textPtr; end = (char *)(entity->textPtr + entity->textLen); tok = XmlPrologTok(internalEncoding, s, end, &next); result = doProlog(parser, internalEncoding, s, end, tok, next, 0); entity->open = XML_FALSE; openInternalEntities = openEntity.next; return result; } #endif /* XML_DTD */ static enum XML_Error PTRCALL errorProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { return errorCode; } static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool) { enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); if (result) return result; if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) poolChop(pool); if (!poolAppendChar(pool, XML_T('\0'))) return XML_ERROR_NO_MEMORY; return XML_ERROR_NONE; } static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool) { DTD * const dtd = _dtd; /* save one level of indirection */ for (;;) { const char *next; int tok = XmlAttributeValueTok(enc, ptr, end, &next); switch (tok) { case XML_TOK_NONE: return XML_ERROR_NONE; case XML_TOK_INVALID: if (enc == encoding) eventPtr = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (enc == encoding) eventPtr = ptr; return XML_ERROR_INVALID_TOKEN; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; int i; int n = XmlCharRefNumber(enc, ptr); if (n < 0) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_BAD_CHAR_REF; } if (!isCdata && n == 0x20 /* space */ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) break; n = XmlEncode(n, (ICHAR *)buf); if (!n) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_BAD_CHAR_REF; } for (i = 0; i < n; i++) { if (!poolAppendChar(pool, buf[i])) return XML_ERROR_NO_MEMORY; } } break; case XML_TOK_DATA_CHARS: if (!poolAppend(pool, enc, ptr, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_TRAILING_CR: next = ptr + enc->minBytesPerChar; /* fall through */ case XML_TOK_ATTRIBUTE_VALUE_S: case XML_TOK_DATA_NEWLINE: if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) break; if (!poolAppendChar(pool, 0x20)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; char checkEntityDecl; XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { if (!poolAppendChar(pool, ch)) return XML_ERROR_NO_MEMORY; break; } name = poolStoreString(&temp2Pool, enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); poolDiscard(&temp2Pool); /* first, determine if a check for an existing declaration is needed; if yes, check that the entity exists, and that it is internal, otherwise call the default handler (if called from content) */ if (pool == &dtd->pool) /* are we called from prolog? */ checkEntityDecl = #ifdef XML_DTD prologState.documentEntity && #endif /* XML_DTD */ (dtd->standalone ? !openInternalEntities : !dtd->hasParamEntityRefs); else /* if (pool == &tempPool): we are called from content */ checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone; if (checkEntityDecl) { if (!entity) return XML_ERROR_UNDEFINED_ENTITY; else if (!entity->is_internal) return XML_ERROR_ENTITY_DECLARED_IN_PE; } else if (!entity) { /* cannot report skipped entity here - see comments on skippedEntityHandler if (skippedEntityHandler) skippedEntityHandler(handlerArg, name, 0); */ if ((pool == &tempPool) && defaultHandler) reportDefault(parser, enc, ptr, next); break; } if (entity->open) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_RECURSIVE_ENTITY_REF; } if (entity->notation) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_BINARY_ENTITY_REF; } if (!entity->textPtr) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; } else { enum XML_Error result; const XML_Char *textEnd = entity->textPtr + entity->textLen; entity->open = XML_TRUE; result = appendAttributeValue(parser, internalEncoding, isCdata, (char *)entity->textPtr, (char *)textEnd, pool); entity->open = XML_FALSE; if (result) return result; } } break; default: if (enc == encoding) eventPtr = ptr; return XML_ERROR_UNEXPECTED_STATE; } ptr = next; } /* not reached */ } static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *entityTextPtr, const char *entityTextEnd) { DTD * const dtd = _dtd; /* save one level of indirection */ STRING_POOL *pool = &(dtd->entityValuePool); enum XML_Error result = XML_ERROR_NONE; #ifdef XML_DTD int oldInEntityValue = prologState.inEntityValue; prologState.inEntityValue = 1; #endif /* XML_DTD */ /* never return Null for the value argument in EntityDeclHandler, since this would indicate an external entity; therefore we have to make sure that entityValuePool.start is not null */ if (!pool->blocks) { if (!poolGrow(pool)) return XML_ERROR_NO_MEMORY; } for (;;) { const char *next; int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); switch (tok) { case XML_TOK_PARAM_ENTITY_REF: #ifdef XML_DTD if (isParamEntity || enc != encoding) { const XML_Char *name; ENTITY *entity; name = poolStoreString(&tempPool, enc, entityTextPtr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); poolDiscard(&tempPool); if (!entity) { /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ /* cannot report skipped entity here - see comments on skippedEntityHandler if (skippedEntityHandler) skippedEntityHandler(handlerArg, name, 0); */ dtd->keepProcessing = dtd->standalone; goto endEntityValue; } if (entity->open) { if (enc == encoding) eventPtr = entityTextPtr; result = XML_ERROR_RECURSIVE_ENTITY_REF; goto endEntityValue; } if (entity->systemId) { if (externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; if (!externalEntityRefHandler(externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { entity->open = XML_FALSE; result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; goto endEntityValue; } entity->open = XML_FALSE; if (!dtd->paramEntityRead) dtd->keepProcessing = dtd->standalone; } else dtd->keepProcessing = dtd->standalone; } else { entity->open = XML_TRUE; result = storeEntityValue(parser, internalEncoding, (char *)entity->textPtr, (char *)(entity->textPtr + entity->textLen)); entity->open = XML_FALSE; if (result) goto endEntityValue; } break; } #endif /* XML_DTD */ /* in the internal subset, PE references are not legal within markup declarations, e.g entity values in this case */ eventPtr = entityTextPtr; result = XML_ERROR_PARAM_ENTITY_REF; goto endEntityValue; case XML_TOK_NONE: result = XML_ERROR_NONE; goto endEntityValue; case XML_TOK_ENTITY_REF: case XML_TOK_DATA_CHARS: if (!poolAppend(pool, enc, entityTextPtr, next)) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } break; case XML_TOK_TRAILING_CR: next = entityTextPtr + enc->minBytesPerChar; /* fall through */ case XML_TOK_DATA_NEWLINE: if (pool->end == pool->ptr && !poolGrow(pool)) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } *(pool->ptr)++ = 0xA; break; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; int i; int n = XmlCharRefNumber(enc, entityTextPtr); if (n < 0) { if (enc == encoding) eventPtr = entityTextPtr; result = XML_ERROR_BAD_CHAR_REF; goto endEntityValue; } n = XmlEncode(n, (ICHAR *)buf); if (!n) { if (enc == encoding) eventPtr = entityTextPtr; result = XML_ERROR_BAD_CHAR_REF; goto endEntityValue; } for (i = 0; i < n; i++) { if (pool->end == pool->ptr && !poolGrow(pool)) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } *(pool->ptr)++ = buf[i]; } } break; case XML_TOK_PARTIAL: if (enc == encoding) eventPtr = entityTextPtr; result = XML_ERROR_INVALID_TOKEN; goto endEntityValue; case XML_TOK_INVALID: if (enc == encoding) eventPtr = next; result = XML_ERROR_INVALID_TOKEN; goto endEntityValue; default: if (enc == encoding) eventPtr = entityTextPtr; result = XML_ERROR_UNEXPECTED_STATE; goto endEntityValue; } entityTextPtr = next; } endEntityValue: #ifdef XML_DTD prologState.inEntityValue = oldInEntityValue; #endif /* XML_DTD */ return result; } static void FASTCALL normalizeLines(XML_Char *s) { XML_Char *p; for (;; s++) { if (*s == XML_T('\0')) return; if (*s == 0xD) break; } p = s; do { if (*s == 0xD) { *p++ = 0xA; if (*++s == 0xA) s++; } else *p++ = *s++; } while (*s); *p = XML_T('\0'); } static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { const XML_Char *target; XML_Char *data; const char *tem; if (!processingInstructionHandler) { if (defaultHandler) reportDefault(parser, enc, start, end); return 1; } start += enc->minBytesPerChar * 2; tem = start + XmlNameLength(enc, start); target = poolStoreString(&tempPool, enc, start, tem); if (!target) return 0; poolFinish(&tempPool); data = poolStoreString(&tempPool, enc, XmlSkipS(enc, tem), end - enc->minBytesPerChar*2); if (!data) return 0; normalizeLines(data); processingInstructionHandler(handlerArg, target, data); poolClear(&tempPool); return 1; } static int reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { XML_Char *data; if (!commentHandler) { if (defaultHandler) reportDefault(parser, enc, start, end); return 1; } data = poolStoreString(&tempPool, enc, start + enc->minBytesPerChar * 4, end - enc->minBytesPerChar * 3); if (!data) return 0; normalizeLines(data); commentHandler(handlerArg, data); poolClear(&tempPool); return 1; } static void reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) { if (MUST_CONVERT(enc, s)) { const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } do { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = s; defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); *eventPP = s; } while (s != end); } else defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); } static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, XML_Bool isId, const XML_Char *value, XML_Parser parser) { DEFAULT_ATTRIBUTE *att; if (value || isId) { /* The handling of default attributes gets messed up if we have a default which duplicates a non-default. */ int i; for (i = 0; i < type->nDefaultAtts; i++) if (attId == type->defaultAtts[i].id) return 1; if (isId && !type->idAtt && !attId->xmlns) type->idAtt = attId; } if (type->nDefaultAtts == type->allocDefaultAtts) { if (type->allocDefaultAtts == 0) { type->allocDefaultAtts = 8; type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (!type->defaultAtts) return 0; } else { DEFAULT_ATTRIBUTE *temp; int count = type->allocDefaultAtts * 2; temp = (DEFAULT_ATTRIBUTE *) REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); if (temp == NULL) return 0; type->allocDefaultAtts = count; type->defaultAtts = temp; } } att = type->defaultAtts + type->nDefaultAtts; att->id = attId; att->value = value; att->isCdata = isCdata; if (!isCdata) attId->maybeTokenized = XML_TRUE; type->nDefaultAtts += 1; return 1; } static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) { DTD * const dtd = _dtd; /* save one level of indirection */ const XML_Char *name; for (name = elementType->name; *name; name++) { if (*name == XML_T(':')) { PREFIX *prefix; const XML_Char *s; for (s = elementType->name; s != name; s++) { if (!poolAppendChar(&dtd->pool, *s)) return 0; } if (!poolAppendChar(&dtd->pool, XML_T('\0'))) return 0; prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), sizeof(PREFIX)); if (!prefix) return 0; if (prefix->name == poolStart(&dtd->pool)) poolFinish(&dtd->pool); else poolDiscard(&dtd->pool); elementType->prefix = prefix; } } return 1; } static ATTRIBUTE_ID * getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { DTD * const dtd = _dtd; /* save one level of indirection */ ATTRIBUTE_ID *id; const XML_Char *name; if (!poolAppendChar(&dtd->pool, XML_T('\0'))) return NULL; name = poolStoreString(&dtd->pool, enc, start, end); if (!name) return NULL; ++name; id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); if (!id) return NULL; if (id->name != name) poolDiscard(&dtd->pool); else { poolFinish(&dtd->pool); if (!ns) ; else if (name[0] == XML_T('x') && name[1] == XML_T('m') && name[2] == XML_T('l') && name[3] == XML_T('n') && name[4] == XML_T('s') && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { if (name[5] == XML_T('\0')) id->prefix = &dtd->defaultPrefix; else id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX)); id->xmlns = XML_TRUE; } else { int i; for (i = 0; name[i]; i++) { if (name[i] == XML_T(':')) { int j; for (j = 0; j < i; j++) { if (!poolAppendChar(&dtd->pool, name[j])) return NULL; } if (!poolAppendChar(&dtd->pool, XML_T('\0'))) return NULL; id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), sizeof(PREFIX)); if (id->prefix->name == poolStart(&dtd->pool)) poolFinish(&dtd->pool); else poolDiscard(&dtd->pool); break; } } } } return id; } #define CONTEXT_SEP XML_T('\f') static const XML_Char * getContext(XML_Parser parser) { DTD * const dtd = _dtd; /* save one level of indirection */ HASH_TABLE_ITER iter; XML_Bool needSep = XML_FALSE; if (dtd->defaultPrefix.binding) { int i; int len; if (!poolAppendChar(&tempPool, XML_T('='))) return NULL; len = dtd->defaultPrefix.binding->uriLen; if (namespaceSeparator != XML_T('\0')) len--; for (i = 0; i < len; i++) if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) return NULL; needSep = XML_TRUE; } hashTableIterInit(&iter, &(dtd->prefixes)); for (;;) { int i; int len; const XML_Char *s; PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); if (!prefix) break; if (!prefix->binding) continue; if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) return NULL; for (s = prefix->name; *s; s++) if (!poolAppendChar(&tempPool, *s)) return NULL; if (!poolAppendChar(&tempPool, XML_T('='))) return NULL; len = prefix->binding->uriLen; if (namespaceSeparator != XML_T('\0')) len--; for (i = 0; i < len; i++) if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) return NULL; needSep = XML_TRUE; } hashTableIterInit(&iter, &(dtd->generalEntities)); for (;;) { const XML_Char *s; ENTITY *e = (ENTITY *)hashTableIterNext(&iter); if (!e) break; if (!e->open) continue; if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) return NULL; for (s = e->name; *s; s++) if (!poolAppendChar(&tempPool, *s)) return 0; needSep = XML_TRUE; } if (!poolAppendChar(&tempPool, XML_T('\0'))) return NULL; return tempPool.start; } static XML_Bool setContext(XML_Parser parser, const XML_Char *context) { DTD * const dtd = _dtd; /* save one level of indirection */ const XML_Char *s = context; while (*context != XML_T('\0')) { if (*s == CONTEXT_SEP || *s == XML_T('\0')) { ENTITY *e; if (!poolAppendChar(&tempPool, XML_T('\0'))) return XML_FALSE; e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0); if (e) e->open = XML_TRUE; if (*s != XML_T('\0')) s++; context = s; poolDiscard(&tempPool); } else if (*s == XML_T('=')) { PREFIX *prefix; if (poolLength(&tempPool) == 0) prefix = &dtd->defaultPrefix; else { if (!poolAppendChar(&tempPool, XML_T('\0'))) return XML_FALSE; prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool), sizeof(PREFIX)); if (!prefix) return XML_FALSE; if (prefix->name == poolStart(&tempPool)) { prefix->name = poolCopyString(&dtd->pool, prefix->name); if (!prefix->name) return XML_FALSE; } poolDiscard(&tempPool); } for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++) if (!poolAppendChar(&tempPool, *context)) return XML_FALSE; if (!poolAppendChar(&tempPool, XML_T('\0'))) return XML_FALSE; if (addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings) != XML_ERROR_NONE) return XML_FALSE; poolDiscard(&tempPool); if (*context != XML_T('\0')) ++context; s = context; } else { if (!poolAppendChar(&tempPool, *s)) return XML_FALSE; s++; } } return XML_TRUE; } static void FASTCALL normalizePublicId(XML_Char *publicId) { XML_Char *p = publicId; XML_Char *s; for (s = publicId; *s; s++) { switch (*s) { case 0x20: case 0xD: case 0xA: if (p != publicId && p[-1] != 0x20) *p++ = 0x20; break; default: *p++ = *s; } } if (p != publicId && p[-1] == 0x20) --p; *p = XML_T('\0'); } static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms) { DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD)); if (p == NULL) return p; poolInit(&(p->pool), ms); #ifdef XML_DTD poolInit(&(p->entityValuePool), ms); #endif /* XML_DTD */ hashTableInit(&(p->generalEntities), ms); hashTableInit(&(p->elementTypes), ms); hashTableInit(&(p->attributeIds), ms); hashTableInit(&(p->prefixes), ms); #ifdef XML_DTD p->paramEntityRead = XML_FALSE; hashTableInit(&(p->paramEntities), ms); #endif /* XML_DTD */ p->defaultPrefix.name = NULL; p->defaultPrefix.binding = NULL; p->in_eldecl = XML_FALSE; p->scaffIndex = NULL; p->scaffold = NULL; p->scaffLevel = 0; p->scaffSize = 0; p->scaffCount = 0; p->contentStringLen = 0; p->keepProcessing = XML_TRUE; p->hasParamEntityRefs = XML_FALSE; p->standalone = XML_FALSE; return p; } static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (!e) break; if (e->allocDefaultAtts != 0) ms->free_fcn(e->defaultAtts); } hashTableClear(&(p->generalEntities)); #ifdef XML_DTD p->paramEntityRead = XML_FALSE; hashTableClear(&(p->paramEntities)); #endif /* XML_DTD */ hashTableClear(&(p->elementTypes)); hashTableClear(&(p->attributeIds)); hashTableClear(&(p->prefixes)); poolClear(&(p->pool)); #ifdef XML_DTD poolClear(&(p->entityValuePool)); #endif /* XML_DTD */ p->defaultPrefix.name = NULL; p->defaultPrefix.binding = NULL; p->in_eldecl = XML_FALSE; if (p->scaffIndex) { ms->free_fcn(p->scaffIndex); p->scaffIndex = NULL; } if (p->scaffold) { ms->free_fcn(p->scaffold); p->scaffold = NULL; } p->scaffLevel = 0; p->scaffSize = 0; p->scaffCount = 0; p->contentStringLen = 0; p->keepProcessing = XML_TRUE; p->hasParamEntityRefs = XML_FALSE; p->standalone = XML_FALSE; } static void dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (!e) break; if (e->allocDefaultAtts != 0) ms->free_fcn(e->defaultAtts); } hashTableDestroy(&(p->generalEntities)); #ifdef XML_DTD hashTableDestroy(&(p->paramEntities)); #endif /* XML_DTD */ hashTableDestroy(&(p->elementTypes)); hashTableDestroy(&(p->attributeIds)); hashTableDestroy(&(p->prefixes)); poolDestroy(&(p->pool)); #ifdef XML_DTD poolDestroy(&(p->entityValuePool)); #endif /* XML_DTD */ if (isDocEntity) { if (p->scaffIndex) ms->free_fcn(p->scaffIndex); if (p->scaffold) ms->free_fcn(p->scaffold); } ms->free_fcn(p); } /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. The new DTD has already been initialized. */ static int dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) { HASH_TABLE_ITER iter; /* Copy the prefix table. */ hashTableIterInit(&iter, &(oldDtd->prefixes)); for (;;) { const XML_Char *name; const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); if (!oldP) break; name = poolCopyString(&(newDtd->pool), oldP->name); if (!name) return 0; if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) return 0; } hashTableIterInit(&iter, &(oldDtd->attributeIds)); /* Copy the attribute id table. */ for (;;) { ATTRIBUTE_ID *newA; const XML_Char *name; const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); if (!oldA) break; /* Remember to allocate the scratch byte before the name. */ if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) return 0; name = poolCopyString(&(newDtd->pool), oldA->name); if (!name) return 0; ++name; newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); if (!newA) return 0; newA->maybeTokenized = oldA->maybeTokenized; if (oldA->prefix) { newA->xmlns = oldA->xmlns; if (oldA->prefix == &oldDtd->defaultPrefix) newA->prefix = &newDtd->defaultPrefix; else newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0); } } /* Copy the element type table. */ hashTableIterInit(&iter, &(oldDtd->elementTypes)); for (;;) { int i; ELEMENT_TYPE *newE; const XML_Char *name; const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (!oldE) break; name = poolCopyString(&(newDtd->pool), oldE->name); if (!name) return 0; newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); if (!newE) return 0; if (oldE->nDefaultAtts) { newE->defaultAtts = (DEFAULT_ATTRIBUTE *) ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (!newE->defaultAtts) { ms->free_fcn(newE); return 0; } } if (oldE->idAtt) newE->idAtt = (ATTRIBUTE_ID *) lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; if (oldE->prefix) newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0); for (i = 0; i < newE->nDefaultAtts; i++) { newE->defaultAtts[i].id = (ATTRIBUTE_ID *) lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; if (oldE->defaultAtts[i].value) { newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); if (!newE->defaultAtts[i].value) return 0; } else newE->defaultAtts[i].value = NULL; } } /* Copy the entity tables. */ if (!copyEntityTable(&(newDtd->generalEntities), &(newDtd->pool), &(oldDtd->generalEntities))) return 0; #ifdef XML_DTD if (!copyEntityTable(&(newDtd->paramEntities), &(newDtd->pool), &(oldDtd->paramEntities))) return 0; newDtd->paramEntityRead = oldDtd->paramEntityRead; #endif /* XML_DTD */ newDtd->keepProcessing = oldDtd->keepProcessing; newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs; newDtd->standalone = oldDtd->standalone; /* Don't want deep copying for scaffolding */ newDtd->in_eldecl = oldDtd->in_eldecl; newDtd->scaffold = oldDtd->scaffold; newDtd->contentStringLen = oldDtd->contentStringLen; newDtd->scaffSize = oldDtd->scaffSize; newDtd->scaffLevel = oldDtd->scaffLevel; newDtd->scaffIndex = oldDtd->scaffIndex; return 1; } /* End dtdCopy */ static int copyEntityTable(HASH_TABLE *newTable, STRING_POOL *newPool, const HASH_TABLE *oldTable) { HASH_TABLE_ITER iter; const XML_Char *cachedOldBase = NULL; const XML_Char *cachedNewBase = NULL; hashTableIterInit(&iter, oldTable); for (;;) { ENTITY *newE; const XML_Char *name; const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); if (!oldE) break; name = poolCopyString(newPool, oldE->name); if (!name) return 0; newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); if (!newE) return 0; if (oldE->systemId) { const XML_Char *tem = poolCopyString(newPool, oldE->systemId); if (!tem) return 0; newE->systemId = tem; if (oldE->base) { if (oldE->base == cachedOldBase) newE->base = cachedNewBase; else { cachedOldBase = oldE->base; tem = poolCopyString(newPool, cachedOldBase); if (!tem) return 0; cachedNewBase = newE->base = tem; } } if (oldE->publicId) { tem = poolCopyString(newPool, oldE->publicId); if (!tem) return 0; newE->publicId = tem; } } else { const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen); if (!tem) return 0; newE->textPtr = tem; newE->textLen = oldE->textLen; } if (oldE->notation) { const XML_Char *tem = poolCopyString(newPool, oldE->notation); if (!tem) return 0; newE->notation = tem; } newE->is_param = oldE->is_param; newE->is_internal = oldE->is_internal; } return 1; } #define INIT_SIZE 64 static int FASTCALL keyeq(KEY s1, KEY s2) { for (; *s1 == *s2; s1++, s2++) if (*s1 == 0) return 1; return 0; } static unsigned long FASTCALL hash(KEY s) { unsigned long h = 0; while (*s) h = (h << 5) + h + (unsigned char)*s++; return h; } static NAMED * lookup(HASH_TABLE *table, KEY name, size_t createSize) { size_t i; if (table->size == 0) { size_t tsize; if (!createSize) return NULL; tsize = INIT_SIZE * sizeof(NAMED *); table->v = (NAMED **)table->mem->malloc_fcn(tsize); if (!table->v) return NULL; memset(table->v, 0, tsize); table->size = INIT_SIZE; table->usedLim = INIT_SIZE / 2; i = hash(name) & (table->size - 1); } else { unsigned long h = hash(name); for (i = h & (table->size - 1); table->v[i]; i == 0 ? i = table->size - 1 : --i) { if (keyeq(name, table->v[i]->name)) return table->v[i]; } if (!createSize) return NULL; if (table->used == table->usedLim) { /* check for overflow */ size_t newSize = table->size * 2; size_t tsize = newSize * sizeof(NAMED *); NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); if (!newV) return NULL; memset(newV, 0, tsize); for (i = 0; i < table->size; i++) if (table->v[i]) { size_t j; for (j = hash(table->v[i]->name) & (newSize - 1); newV[j]; j == 0 ? j = newSize - 1 : --j) ; newV[j] = table->v[i]; } table->mem->free_fcn(table->v); table->v = newV; table->size = newSize; table->usedLim = newSize/2; for (i = h & (table->size - 1); table->v[i]; i == 0 ? i = table->size - 1 : --i) ; } } table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize); if (!table->v[i]) return NULL; memset(table->v[i], 0, createSize); table->v[i]->name = name; (table->used)++; return table->v[i]; } static void FASTCALL hashTableClear(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) { NAMED *p = table->v[i]; if (p) { table->mem->free_fcn(p); table->v[i] = NULL; } } table->usedLim = table->size / 2; table->used = 0; } static void FASTCALL hashTableDestroy(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) { NAMED *p = table->v[i]; if (p) table->mem->free_fcn(p); } if (table->v) table->mem->free_fcn(table->v); } static void FASTCALL hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) { p->size = 0; p->usedLim = 0; p->used = 0; p->v = NULL; p->mem = ms; } static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) { iter->p = table->v; iter->end = iter->p + table->size; } static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter) { while (iter->p != iter->end) { NAMED *tem = *(iter->p)++; if (tem) return tem; } return NULL; } static void FASTCALL poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) { pool->blocks = NULL; pool->freeBlocks = NULL; pool->start = NULL; pool->ptr = NULL; pool->end = NULL; pool->mem = ms; } static void FASTCALL poolClear(STRING_POOL *pool) { if (!pool->freeBlocks) pool->freeBlocks = pool->blocks; else { BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; p->next = pool->freeBlocks; pool->freeBlocks = p; p = tem; } } pool->blocks = NULL; pool->start = NULL; pool->ptr = NULL; pool->end = NULL; } static void FASTCALL poolDestroy(STRING_POOL *pool) { BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; pool->mem->free_fcn(p); p = tem; } p = pool->freeBlocks; while (p) { BLOCK *tem = p->next; pool->mem->free_fcn(p); p = tem; } } static XML_Char * poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { if (!pool->ptr && !poolGrow(pool)) return NULL; for (;;) { XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); if (ptr == end) break; if (!poolGrow(pool)) return NULL; } return pool->start; } static const XML_Char * FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s) { do { if (!poolAppendChar(pool, *s)) return NULL; } while (*s++); s = pool->start; poolFinish(pool); return s; } static const XML_Char * poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) { if (!pool->ptr && !poolGrow(pool)) return NULL; for (; n > 0; --n, s++) { if (!poolAppendChar(pool, *s)) return NULL; } s = pool->start; poolFinish(pool); return s; } static const XML_Char * FASTCALL poolAppendString(STRING_POOL *pool, const XML_Char *s) { while (*s) { if (!poolAppendChar(pool, *s)) return NULL; s++; } return pool->start; } static XML_Char * poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { if (!poolAppend(pool, enc, ptr, end)) return NULL; if (pool->ptr == pool->end && !poolGrow(pool)) return NULL; *(pool->ptr)++ = 0; return pool->start; } static XML_Bool FASTCALL poolGrow(STRING_POOL *pool) { if (pool->freeBlocks) { if (pool->start == 0) { pool->blocks = pool->freeBlocks; pool->freeBlocks = pool->freeBlocks->next; pool->blocks->next = NULL; pool->start = pool->blocks->s; pool->end = pool->start + pool->blocks->size; pool->ptr = pool->start; return XML_TRUE; } if (pool->end - pool->start < pool->freeBlocks->size) { BLOCK *tem = pool->freeBlocks->next; pool->freeBlocks->next = pool->blocks; pool->blocks = pool->freeBlocks; pool->freeBlocks = tem; memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char)); pool->ptr = pool->blocks->s + (pool->ptr - pool->start); pool->start = pool->blocks->s; pool->end = pool->start + pool->blocks->size; return XML_TRUE; } } if (pool->blocks && pool->start == pool->blocks->s) { int blockSize = (pool->end - pool->start)*2; pool->blocks = (BLOCK *) pool->mem->realloc_fcn(pool->blocks, (offsetof(BLOCK, s) + blockSize * sizeof(XML_Char))); if (pool->blocks == NULL) return XML_FALSE; pool->blocks->size = blockSize; pool->ptr = pool->blocks->s + (pool->ptr - pool->start); pool->start = pool->blocks->s; pool->end = pool->start + blockSize; } else { BLOCK *tem; int blockSize = pool->end - pool->start; if (blockSize < INIT_BLOCK_SIZE) blockSize = INIT_BLOCK_SIZE; else blockSize *= 2; tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); if (!tem) return XML_FALSE; tem->size = blockSize; tem->next = pool->blocks; pool->blocks = tem; if (pool->ptr != pool->start) memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char)); pool->ptr = tem->s + (pool->ptr - pool->start); pool->start = tem->s; pool->end = tem->s + blockSize; } return XML_TRUE; } static int FASTCALL nextScaffoldPart(XML_Parser parser) { DTD * const dtd = _dtd; /* save one level of indirection */ CONTENT_SCAFFOLD * me; int next; if (!dtd->scaffIndex) { dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int)); if (!dtd->scaffIndex) return -1; dtd->scaffIndex[0] = 0; } if (dtd->scaffCount >= dtd->scaffSize) { CONTENT_SCAFFOLD *temp; if (dtd->scaffold) { temp = (CONTENT_SCAFFOLD *) REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize *= 2; } else { temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; } dtd->scaffold = temp; } next = dtd->scaffCount++; me = &dtd->scaffold[next]; if (dtd->scaffLevel) { CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]]; if (parent->lastchild) { dtd->scaffold[parent->lastchild].nextsib = next; } if (!parent->childcnt) parent->firstchild = next; parent->lastchild = next; parent->childcnt++; } me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; return next; } static void build_node(XML_Parser parser, int src_node, XML_Content *dest, XML_Content **contpos, XML_Char **strpos) { DTD * const dtd = _dtd; /* save one level of indirection */ dest->type = dtd->scaffold[src_node].type; dest->quant = dtd->scaffold[src_node].quant; if (dest->type == XML_CTYPE_NAME) { const XML_Char *src; dest->name = *strpos; src = dtd->scaffold[src_node].name; for (;;) { *(*strpos)++ = *src; if (!*src) break; src++; } dest->numchildren = 0; dest->children = NULL; } else { unsigned int i; int cn; dest->numchildren = dtd->scaffold[src_node].childcnt; dest->children = *contpos; *contpos += dest->numchildren; for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) { build_node(parser, cn, &(dest->children[i]), contpos, strpos); } dest->name = NULL; } } static XML_Content * build_model (XML_Parser parser) { DTD * const dtd = _dtd; /* save one level of indirection */ XML_Content *ret; XML_Content *cpos; XML_Char * str; int allocsize = (dtd->scaffCount * sizeof(XML_Content) + (dtd->contentStringLen * sizeof(XML_Char))); ret = (XML_Content *)MALLOC(allocsize); if (!ret) return NULL; str = (XML_Char *) (&ret[dtd->scaffCount]); cpos = &ret[1]; build_node(parser, 0, ret, &cpos, &str); return ret; } static ELEMENT_TYPE * getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, const char *end) { DTD * const dtd = _dtd; /* save one level of indirection */ const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end); ELEMENT_TYPE *ret; if (!name) return NULL; ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); if (!ret) return NULL; if (ret->name != name) poolDiscard(&dtd->pool); else { poolFinish(&dtd->pool); if (!setElementTypePrefix(parser, ret)) return NULL; } return ret; } PyXML-0.8.2/extensions/expat/lib/xmlrole.c0100644000076400001440000007664307614720046017652 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) #include "macconfig.h" #else #endif /* ndef COMPILED_FROM_DSP */ #include "internal.h" #include "xmlrole.h" #include "ascii.h" /* Doesn't check: that ,| are not mixed in a model group content of literals */ static const char KW_ANY[] = { ASCII_A, ASCII_N, ASCII_Y, '\0' }; static const char KW_ATTLIST[] = { ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' }; static const char KW_CDATA[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; static const char KW_DOCTYPE[] = { ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' }; static const char KW_ELEMENT[] = { ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' }; static const char KW_EMPTY[] = { ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' }; static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' }; static const char KW_ENTITY[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' }; static const char KW_FIXED[] = { ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' }; static const char KW_ID[] = { ASCII_I, ASCII_D, '\0' }; static const char KW_IDREF[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' }; static const char KW_IDREFS[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' }; static const char KW_IGNORE[] = { ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' }; static const char KW_IMPLIED[] = { ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' }; static const char KW_INCLUDE[] = { ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' }; static const char KW_NDATA[] = { ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; static const char KW_NMTOKEN[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' }; static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' }; static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0' }; static const char KW_PCDATA[] = { ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; static const char KW_PUBLIC[] = { ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' }; static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0' }; static const char KW_SYSTEM[] = { ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' }; #ifndef MIN_BYTES_PER_CHAR #define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) #endif #ifdef XML_DTD #define setTopLevel(state) \ ((state)->handler = ((state)->documentEntity \ ? internalSubset \ : externalSubset1)) #else /* not XML_DTD */ #define setTopLevel(state) ((state)->handler = internalSubset) #endif /* not XML_DTD */ typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc); static PROLOG_HANDLER prolog0, prolog1, prolog2, doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, internalSubset, entity0, entity1, entity2, entity3, entity4, entity5, entity6, entity7, entity8, entity9, entity10, notation0, notation1, notation2, notation3, notation4, attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, attlist7, attlist8, attlist9, element0, element1, element2, element3, element4, element5, element6, element7, #ifdef XML_DTD externalSubset0, externalSubset1, condSect0, condSect1, condSect2, #endif /* XML_DTD */ declClose, error; static int FASTCALL common(PROLOG_STATE *state, int tok); static int PTRCALL prolog0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: state->handler = prolog1; return XML_ROLE_NONE; case XML_TOK_XML_DECL: state->handler = prolog1; return XML_ROLE_XML_DECL; case XML_TOK_PI: state->handler = prolog1; return XML_ROLE_PI; case XML_TOK_COMMENT: state->handler = prolog1; return XML_ROLE_COMMENT; case XML_TOK_BOM: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (!XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_DOCTYPE)) break; state->handler = doctype0; return XML_ROLE_DOCTYPE_NONE; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int PTRCALL prolog1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_PI: return XML_ROLE_PI; case XML_TOK_COMMENT: return XML_ROLE_COMMENT; case XML_TOK_BOM: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (!XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_DOCTYPE)) break; state->handler = doctype0; return XML_ROLE_DOCTYPE_NONE; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int PTRCALL prolog2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_PI: return XML_ROLE_PI; case XML_TOK_COMMENT: return XML_ROLE_COMMENT; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int PTRCALL doctype0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = doctype1; return XML_ROLE_DOCTYPE_NAME; } return common(state, tok); } static int PTRCALL doctype1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = internalSubset; return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = doctype3; return XML_ROLE_DOCTYPE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = doctype2; return XML_ROLE_DOCTYPE_NONE; } break; } return common(state, tok); } static int PTRCALL doctype2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_LITERAL: state->handler = doctype3; return XML_ROLE_DOCTYPE_PUBLIC_ID; } return common(state, tok); } static int PTRCALL doctype3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_LITERAL: state->handler = doctype4; return XML_ROLE_DOCTYPE_SYSTEM_ID; } return common(state, tok); } static int PTRCALL doctype4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = internalSubset; return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; } return common(state, tok); } static int PTRCALL doctype5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; } return common(state, tok); } static int PTRCALL internalSubset(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ENTITY)) { state->handler = entity0; return XML_ROLE_ENTITY_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ATTLIST)) { state->handler = attlist0; return XML_ROLE_ATTLIST_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ELEMENT)) { state->handler = element0; return XML_ROLE_ELEMENT_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_NOTATION)) { state->handler = notation0; return XML_ROLE_NOTATION_NONE; } break; case XML_TOK_PI: return XML_ROLE_PI; case XML_TOK_COMMENT: return XML_ROLE_COMMENT; case XML_TOK_PARAM_ENTITY_REF: return XML_ROLE_PARAM_ENTITY_REF; case XML_TOK_CLOSE_BRACKET: state->handler = doctype5; return XML_ROLE_DOCTYPE_NONE; } return common(state, tok); } #ifdef XML_DTD static int PTRCALL externalSubset0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { state->handler = externalSubset1; if (tok == XML_TOK_XML_DECL) return XML_ROLE_TEXT_DECL; return externalSubset1(state, tok, ptr, end, enc); } static int PTRCALL externalSubset1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_COND_SECT_OPEN: state->handler = condSect0; return XML_ROLE_NONE; case XML_TOK_COND_SECT_CLOSE: if (state->includeLevel == 0) break; state->includeLevel -= 1; return XML_ROLE_NONE; case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_BRACKET: break; case XML_TOK_NONE: if (state->includeLevel) break; return XML_ROLE_NONE; default: return internalSubset(state, tok, ptr, end, enc); } return common(state, tok); } #endif /* XML_DTD */ static int PTRCALL entity0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_PERCENT: state->handler = entity1; return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: state->handler = entity2; return XML_ROLE_GENERAL_ENTITY_NAME; } return common(state, tok); } static int PTRCALL entity1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: state->handler = entity7; return XML_ROLE_PARAM_ENTITY_NAME; } return common(state, tok); } static int PTRCALL entity2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = entity4; return XML_ROLE_ENTITY_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = entity3; return XML_ROLE_ENTITY_NONE; } break; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_ENTITY_NONE; return XML_ROLE_ENTITY_VALUE; } return common(state, tok); } static int PTRCALL entity3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity4; return XML_ROLE_ENTITY_PUBLIC_ID; } return common(state, tok); } static int PTRCALL entity4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity5; return XML_ROLE_ENTITY_SYSTEM_ID; } return common(state, tok); } static int PTRCALL entity5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_ENTITY_COMPLETE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) { state->handler = entity6; return XML_ROLE_ENTITY_NONE; } break; } return common(state, tok); } static int PTRCALL entity6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: state->handler = declClose; state->role_none = XML_ROLE_ENTITY_NONE; return XML_ROLE_ENTITY_NOTATION_NAME; } return common(state, tok); } static int PTRCALL entity7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = entity9; return XML_ROLE_ENTITY_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = entity8; return XML_ROLE_ENTITY_NONE; } break; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_ENTITY_NONE; return XML_ROLE_ENTITY_VALUE; } return common(state, tok); } static int PTRCALL entity8(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity9; return XML_ROLE_ENTITY_PUBLIC_ID; } return common(state, tok); } static int PTRCALL entity9(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity10; return XML_ROLE_ENTITY_SYSTEM_ID; } return common(state, tok); } static int PTRCALL entity10(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_ENTITY_COMPLETE; } return common(state, tok); } static int PTRCALL notation0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_NAME: state->handler = notation1; return XML_ROLE_NOTATION_NAME; } return common(state, tok); } static int PTRCALL notation1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = notation3; return XML_ROLE_NOTATION_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = notation2; return XML_ROLE_NOTATION_NONE; } break; } return common(state, tok); } static int PTRCALL notation2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_LITERAL: state->handler = notation4; return XML_ROLE_NOTATION_PUBLIC_ID; } return common(state, tok); } static int PTRCALL notation3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_NOTATION_NONE; return XML_ROLE_NOTATION_SYSTEM_ID; } return common(state, tok); } static int PTRCALL notation4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_NOTATION_NONE; return XML_ROLE_NOTATION_SYSTEM_ID; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_NOTATION_NO_SYSTEM_ID; } return common(state, tok); } static int PTRCALL attlist0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist1; return XML_ROLE_ATTLIST_ELEMENT_NAME; } return common(state, tok); } static int PTRCALL attlist1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist2; return XML_ROLE_ATTRIBUTE_NAME; } return common(state, tok); } static int PTRCALL attlist2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: { static const char *types[] = { KW_CDATA, KW_ID, KW_IDREF, KW_IDREFS, KW_ENTITY, KW_ENTITIES, KW_NMTOKEN, KW_NMTOKENS, }; int i; for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) if (XmlNameMatchesAscii(enc, ptr, end, types[i])) { state->handler = attlist8; return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; } } if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) { state->handler = attlist5; return XML_ROLE_ATTLIST_NONE; } break; case XML_TOK_OPEN_PAREN: state->handler = attlist3; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } static int PTRCALL attlist3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NMTOKEN: case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist4; return XML_ROLE_ATTRIBUTE_ENUM_VALUE; } return common(state, tok); } static int PTRCALL attlist4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_CLOSE_PAREN: state->handler = attlist8; return XML_ROLE_ATTLIST_NONE; case XML_TOK_OR: state->handler = attlist3; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } static int PTRCALL attlist5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_OPEN_PAREN: state->handler = attlist6; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } static int PTRCALL attlist6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: state->handler = attlist7; return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; } return common(state, tok); } static int PTRCALL attlist7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_CLOSE_PAREN: state->handler = attlist8; return XML_ROLE_ATTLIST_NONE; case XML_TOK_OR: state->handler = attlist6; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } /* default value */ static int PTRCALL attlist8(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_POUND_NAME: if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_IMPLIED)) { state->handler = attlist1; return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; } if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_REQUIRED)) { state->handler = attlist1; return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; } if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_FIXED)) { state->handler = attlist9; return XML_ROLE_ATTLIST_NONE; } break; case XML_TOK_LITERAL: state->handler = attlist1; return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; } return common(state, tok); } static int PTRCALL attlist9(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_LITERAL: state->handler = attlist1; return XML_ROLE_FIXED_ATTRIBUTE_VALUE; } return common(state, tok); } static int PTRCALL element0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element1; return XML_ROLE_ELEMENT_NAME; } return common(state, tok); } static int PTRCALL element1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_CONTENT_EMPTY; } if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_CONTENT_ANY; } break; case XML_TOK_OPEN_PAREN: state->handler = element2; state->level = 1; return XML_ROLE_GROUP_OPEN; } return common(state, tok); } static int PTRCALL element2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_POUND_NAME: if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_PCDATA)) { state->handler = element3; return XML_ROLE_CONTENT_PCDATA; } break; case XML_TOK_OPEN_PAREN: state->level = 2; state->handler = element6; return XML_ROLE_GROUP_OPEN; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT; case XML_TOK_NAME_QUESTION: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_OPT; case XML_TOK_NAME_ASTERISK: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_REP; case XML_TOK_NAME_PLUS: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_PLUS; } return common(state, tok); } static int PTRCALL element3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_CLOSE_PAREN: state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_GROUP_CLOSE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_OR: state->handler = element4; return XML_ROLE_ELEMENT_NONE; } return common(state, tok); } static int PTRCALL element4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element5; return XML_ROLE_CONTENT_ELEMENT; } return common(state, tok); } static int PTRCALL element5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_OR: state->handler = element4; return XML_ROLE_ELEMENT_NONE; } return common(state, tok); } static int PTRCALL element6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_OPEN_PAREN: state->level += 1; return XML_ROLE_GROUP_OPEN; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT; case XML_TOK_NAME_QUESTION: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_OPT; case XML_TOK_NAME_ASTERISK: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_REP; case XML_TOK_NAME_PLUS: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_PLUS; } return common(state, tok); } static int PTRCALL element7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_CLOSE_PAREN: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_CLOSE_PAREN_QUESTION: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE_OPT; case XML_TOK_CLOSE_PAREN_PLUS: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE_PLUS; case XML_TOK_COMMA: state->handler = element6; return XML_ROLE_GROUP_SEQUENCE; case XML_TOK_OR: state->handler = element6; return XML_ROLE_GROUP_CHOICE; } return common(state, tok); } #ifdef XML_DTD static int PTRCALL condSect0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) { state->handler = condSect1; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) { state->handler = condSect2; return XML_ROLE_NONE; } break; } return common(state, tok); } static int PTRCALL condSect1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = externalSubset1; state->includeLevel += 1; return XML_ROLE_NONE; } return common(state, tok); } static int PTRCALL condSect2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = externalSubset1; return XML_ROLE_IGNORE_SECT; } return common(state, tok); } #endif /* XML_DTD */ static int PTRCALL declClose(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return state->role_none; case XML_TOK_DECL_CLOSE: setTopLevel(state); return state->role_none; } return common(state, tok); } static int PTRCALL error(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { return XML_ROLE_NONE; } static int FASTCALL common(PROLOG_STATE *state, int tok) { #ifdef XML_DTD if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) return XML_ROLE_INNER_PARAM_ENTITY_REF; #endif state->handler = error; return XML_ROLE_ERROR; } void XmlPrologStateInit(PROLOG_STATE *state) { state->handler = prolog0; #ifdef XML_DTD state->documentEntity = 1; state->includeLevel = 0; state->inEntityValue = 0; #endif /* XML_DTD */ } #ifdef XML_DTD void XmlPrologStateInitExternalEntity(PROLOG_STATE *state) { state->handler = externalSubset0; state->documentEntity = 0; state->includeLevel = 0; } #endif /* XML_DTD */ PyXML-0.8.2/extensions/expat/lib/xmlrole.h0100644000076400001440000000571707614471161017652 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #ifndef XmlRole_INCLUDED #define XmlRole_INCLUDED 1 #ifdef __VMS /* 0 1 2 3 0 1 2 3 1234567890123456789012345678901 1234567890123456789012345678901 */ #define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt #endif #include "xmltok.h" #ifdef __cplusplus extern "C" { #endif enum { XML_ROLE_ERROR = -1, XML_ROLE_NONE = 0, XML_ROLE_XML_DECL, XML_ROLE_INSTANCE_START, XML_ROLE_DOCTYPE_NONE, XML_ROLE_DOCTYPE_NAME, XML_ROLE_DOCTYPE_SYSTEM_ID, XML_ROLE_DOCTYPE_PUBLIC_ID, XML_ROLE_DOCTYPE_INTERNAL_SUBSET, XML_ROLE_DOCTYPE_CLOSE, XML_ROLE_GENERAL_ENTITY_NAME, XML_ROLE_PARAM_ENTITY_NAME, XML_ROLE_ENTITY_NONE, XML_ROLE_ENTITY_VALUE, XML_ROLE_ENTITY_SYSTEM_ID, XML_ROLE_ENTITY_PUBLIC_ID, XML_ROLE_ENTITY_COMPLETE, XML_ROLE_ENTITY_NOTATION_NAME, XML_ROLE_NOTATION_NONE, XML_ROLE_NOTATION_NAME, XML_ROLE_NOTATION_SYSTEM_ID, XML_ROLE_NOTATION_NO_SYSTEM_ID, XML_ROLE_NOTATION_PUBLIC_ID, XML_ROLE_ATTRIBUTE_NAME, XML_ROLE_ATTRIBUTE_TYPE_CDATA, XML_ROLE_ATTRIBUTE_TYPE_ID, XML_ROLE_ATTRIBUTE_TYPE_IDREF, XML_ROLE_ATTRIBUTE_TYPE_IDREFS, XML_ROLE_ATTRIBUTE_TYPE_ENTITY, XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, XML_ROLE_ATTRIBUTE_ENUM_VALUE, XML_ROLE_ATTRIBUTE_NOTATION_VALUE, XML_ROLE_ATTLIST_NONE, XML_ROLE_ATTLIST_ELEMENT_NAME, XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, XML_ROLE_FIXED_ATTRIBUTE_VALUE, XML_ROLE_ELEMENT_NONE, XML_ROLE_ELEMENT_NAME, XML_ROLE_CONTENT_ANY, XML_ROLE_CONTENT_EMPTY, XML_ROLE_CONTENT_PCDATA, XML_ROLE_GROUP_OPEN, XML_ROLE_GROUP_CLOSE, XML_ROLE_GROUP_CLOSE_REP, XML_ROLE_GROUP_CLOSE_OPT, XML_ROLE_GROUP_CLOSE_PLUS, XML_ROLE_GROUP_CHOICE, XML_ROLE_GROUP_SEQUENCE, XML_ROLE_CONTENT_ELEMENT, XML_ROLE_CONTENT_ELEMENT_REP, XML_ROLE_CONTENT_ELEMENT_OPT, XML_ROLE_CONTENT_ELEMENT_PLUS, XML_ROLE_PI, XML_ROLE_COMMENT, #ifdef XML_DTD XML_ROLE_TEXT_DECL, XML_ROLE_IGNORE_SECT, XML_ROLE_INNER_PARAM_ENTITY_REF, #endif /* XML_DTD */ XML_ROLE_PARAM_ENTITY_REF }; typedef struct prolog_state { int (PTRCALL *handler) (struct prolog_state *state, int tok, const char *ptr, const char *end, const ENCODING *enc); unsigned level; int role_none; #ifdef XML_DTD unsigned includeLevel; int documentEntity; int inEntityValue; #endif /* XML_DTD */ } PROLOG_STATE; void XmlPrologStateInit(PROLOG_STATE *); #ifdef XML_DTD void XmlPrologStateInitExternalEntity(PROLOG_STATE *); #endif /* XML_DTD */ #define XmlTokenRole(state, tok, ptr, end, enc) \ (((state)->handler)(state, tok, ptr, end, enc)) #ifdef __cplusplus } #endif #endif /* not XmlRole_INCLUDED */ PyXML-0.8.2/extensions/expat/lib/xmltok.c0100644000076400001440000012003607614720073017470 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) #include "macconfig.h" #else #endif /* ndef COMPILED_FROM_DSP */ #include "internal.h" #include "xmltok.h" #include "nametab.h" #ifdef XML_DTD #define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok) #else #define IGNORE_SECTION_TOK_VTABLE /* as nothing */ #endif #define VTABLE1 \ { PREFIX(prologTok), PREFIX(contentTok), \ PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \ { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ PREFIX(sameName), \ PREFIX(nameMatchesAscii), \ PREFIX(nameLength), \ PREFIX(skipS), \ PREFIX(getAtts), \ PREFIX(charRefNumber), \ PREFIX(predefinedEntityName), \ PREFIX(updatePosition), \ PREFIX(isPublicId) #define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) #define UCS2_GET_NAMING(pages, hi, lo) \ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) /* A 2 byte UTF-8 representation splits the characters 11 bits between the bottom 5 and 6 bits of the bytes. We need 8 bits to index into pages, 3 bits to add to that index and 5 bits to generate the mask. */ #define UTF8_GET_NAMING2(pages, byte) \ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ + ((((byte)[0]) & 3) << 1) \ + ((((byte)[1]) >> 5) & 1)] \ & (1 << (((byte)[1]) & 0x1F))) /* A 3 byte UTF-8 representation splits the characters 16 bits between the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index into pages, 3 bits to add to that index and 5 bits to generate the mask. */ #define UTF8_GET_NAMING3(pages, byte) \ (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ + ((((byte)[1]) >> 2) & 0xF)] \ << 3) \ + ((((byte)[1]) & 3) << 1) \ + ((((byte)[2]) >> 5) & 1)] \ & (1 << (((byte)[2]) & 0x1F))) #define UTF8_GET_NAMING(pages, p, n) \ ((n) == 2 \ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ : ((n) == 3 \ ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ : 0)) /* Detection of invalid UTF-8 sequences is based on Table 3.1B of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/ with the additional restriction of not allowing the Unicode code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE). Implementation details: (A & 0x80) == 0 means A < 0x80 and (A & 0xC0) == 0xC0 means A > 0xBF */ #define UTF8_INVALID2(p) \ ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0) #define UTF8_INVALID3(p) \ (((p)[2] & 0x80) == 0 \ || \ ((*p) == 0xEF && (p)[1] == 0xBF \ ? \ (p)[2] > 0xBD \ : \ ((p)[2] & 0xC0) == 0xC0) \ || \ ((*p) == 0xE0 \ ? \ (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \ : \ ((p)[1] & 0x80) == 0 \ || \ ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0))) #define UTF8_INVALID4(p) \ (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 \ || \ ((p)[2] & 0x80) == 0 || ((p)[2] & 0xC0) == 0xC0 \ || \ ((*p) == 0xF0 \ ? \ (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \ : \ ((p)[1] & 0x80) == 0 \ || \ ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0))) static int PTRFASTCALL isNever(const ENCODING *enc, const char *p) { return 0; } static int PTRFASTCALL utf8_isName2(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); } static int PTRFASTCALL utf8_isName3(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); } #define utf8_isName4 isNever static int PTRFASTCALL utf8_isNmstrt2(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); } static int PTRFASTCALL utf8_isNmstrt3(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); } #define utf8_isNmstrt4 isNever static int PTRFASTCALL utf8_isInvalid2(const ENCODING *enc, const char *p) { return UTF8_INVALID2((const unsigned char *)p); } static int PTRFASTCALL utf8_isInvalid3(const ENCODING *enc, const char *p) { return UTF8_INVALID3((const unsigned char *)p); } static int PTRFASTCALL utf8_isInvalid4(const ENCODING *enc, const char *p) { return UTF8_INVALID4((const unsigned char *)p); } struct normal_encoding { ENCODING enc; unsigned char type[256]; #ifdef XML_MIN_SIZE int (PTRFASTCALL *byteType)(const ENCODING *, const char *); int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *); int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *); int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *); int (PTRCALL *charMatches)(const ENCODING *, const char *, int); #endif /* XML_MIN_SIZE */ int (PTRFASTCALL *isName2)(const ENCODING *, const char *); int (PTRFASTCALL *isName3)(const ENCODING *, const char *); int (PTRFASTCALL *isName4)(const ENCODING *, const char *); int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *); int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *); int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *); int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *); int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *); int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *); }; #define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *) (enc)) #ifdef XML_MIN_SIZE #define STANDARD_VTABLE(E) \ E ## byteType, \ E ## isNameMin, \ E ## isNmstrtMin, \ E ## byteToAscii, \ E ## charMatches, #else #define STANDARD_VTABLE(E) /* as nothing */ #endif #define NORMAL_VTABLE(E) \ E ## isName2, \ E ## isName3, \ E ## isName4, \ E ## isNmstrt2, \ E ## isNmstrt3, \ E ## isNmstrt4, \ E ## isInvalid2, \ E ## isInvalid3, \ E ## isInvalid4 static int FASTCALL checkCharRefNumber(int); #include "xmltok_impl.h" #include "ascii.h" #ifdef XML_MIN_SIZE #define sb_isNameMin isNever #define sb_isNmstrtMin isNever #endif #ifdef XML_MIN_SIZE #define MINBPC(enc) ((enc)->minBytesPerChar) #else /* minimum bytes per character */ #define MINBPC(enc) 1 #endif #define SB_BYTE_TYPE(enc, p) \ (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) #ifdef XML_MIN_SIZE static int PTRFASTCALL sb_byteType(const ENCODING *enc, const char *p) { return SB_BYTE_TYPE(enc, p); } #define BYTE_TYPE(enc, p) \ (AS_NORMAL_ENCODING(enc)->byteType(enc, p)) #else #define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) #endif #ifdef XML_MIN_SIZE #define BYTE_TO_ASCII(enc, p) \ (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p)) static int PTRFASTCALL sb_byteToAscii(const ENCODING *enc, const char *p) { return *p; } #else #define BYTE_TO_ASCII(enc, p) (*(p)) #endif #define IS_NAME_CHAR(enc, p, n) \ (AS_NORMAL_ENCODING(enc)->isName ## n(enc, p)) #define IS_NMSTRT_CHAR(enc, p, n) \ (AS_NORMAL_ENCODING(enc)->isNmstrt ## n(enc, p)) #define IS_INVALID_CHAR(enc, p, n) \ (AS_NORMAL_ENCODING(enc)->isInvalid ## n(enc, p)) #ifdef XML_MIN_SIZE #define IS_NAME_CHAR_MINBPC(enc, p) \ (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p)) #define IS_NMSTRT_CHAR_MINBPC(enc, p) \ (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p)) #else #define IS_NAME_CHAR_MINBPC(enc, p) (0) #define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) #endif #ifdef XML_MIN_SIZE #define CHAR_MATCHES(enc, p, c) \ (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c)) static int PTRCALL sb_charMatches(const ENCODING *enc, const char *p, int c) { return *p == c; } #else /* c is an ASCII character */ #define CHAR_MATCHES(enc, p, c) (*(p) == c) #endif #define PREFIX(ident) normal_ ## ident #include "xmltok_impl.c" #undef MINBPC #undef BYTE_TYPE #undef BYTE_TO_ASCII #undef CHAR_MATCHES #undef IS_NAME_CHAR #undef IS_NAME_CHAR_MINBPC #undef IS_NMSTRT_CHAR #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ UTF8_cval1 = 0x00, UTF8_cval2 = 0xc0, UTF8_cval3 = 0xe0, UTF8_cval4 = 0xf0 }; static void PTRCALL utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { char *to; const char *from; if (fromLim - *fromP > toLim - *toP) { /* Avoid copying partial characters. */ for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) break; } for (to = *toP, from = *fromP; from != fromLim; from++, to++) *to = *from; *fromP = from; *toP = to; } static void PTRCALL utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { unsigned short *to = *toP; const char *from = *fromP; while (from != fromLim && to != toLim) { switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { case BT_LEAD2: *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f)); from += 2; break; case BT_LEAD3: *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f)); from += 3; break; case BT_LEAD4: { unsigned long n; if (to + 1 == toLim) goto after; n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); n -= 0x10000; to[0] = (unsigned short)((n >> 10) | 0xD800); to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); to += 2; from += 4; } break; default: *to++ = *from++; break; } } after: *fromP = from; *toP = to; } #ifdef XML_NS static const struct normal_encoding utf8_encoding_ns = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #include "asciitab.h" #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #endif static const struct normal_encoding utf8_encoding = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #ifdef XML_NS static const struct normal_encoding internal_utf8_encoding_ns = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #include "iasciitab.h" #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #endif static const struct normal_encoding internal_utf8_encoding = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; static void PTRCALL latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { for (;;) { unsigned char c; if (*fromP == fromLim) break; c = (unsigned char)**fromP; if (c & 0x80) { if (toLim - *toP < 2) break; *(*toP)++ = (char)((c >> 6) | UTF8_cval2); *(*toP)++ = (char)((c & 0x3f) | 0x80); (*fromP)++; } else { if (*toP == toLim) break; *(*toP)++ = *(*fromP)++; } } } static void PTRCALL latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { while (*fromP != fromLim && *toP != toLim) *(*toP)++ = (unsigned char)*(*fromP)++; } #ifdef XML_NS static const struct normal_encoding latin1_encoding_ns = { { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, { #include "asciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(sb_) }; #endif static const struct normal_encoding latin1_encoding = { { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(sb_) }; static void PTRCALL ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { while (*fromP != fromLim && *toP != toLim) *(*toP)++ = *(*fromP)++; } #ifdef XML_NS static const struct normal_encoding ascii_encoding_ns = { { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, { #include "asciitab.h" /* BT_NONXML == 0 */ }, STANDARD_VTABLE(sb_) }; #endif static const struct normal_encoding ascii_encoding = { { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON /* BT_NONXML == 0 */ }, STANDARD_VTABLE(sb_) }; static int PTRFASTCALL unicode_byte_type(char hi, char lo) { switch ((unsigned char)hi) { case 0xD8: case 0xD9: case 0xDA: case 0xDB: return BT_LEAD4; case 0xDC: case 0xDD: case 0xDE: case 0xDF: return BT_TRAIL; case 0xFF: switch ((unsigned char)lo) { case 0xFF: case 0xFE: return BT_NONXML; } break; } return BT_NONASCII; } #define DEFINE_UTF16_TO_UTF8(E) \ static void PTRCALL \ E ## toUtf8(const ENCODING *enc, \ const char **fromP, const char *fromLim, \ char **toP, const char *toLim) \ { \ const char *from; \ for (from = *fromP; from != fromLim; from += 2) { \ int plane; \ unsigned char lo2; \ unsigned char lo = GET_LO(from); \ unsigned char hi = GET_HI(from); \ switch (hi) { \ case 0: \ if (lo < 0x80) { \ if (*toP == toLim) { \ *fromP = from; \ return; \ } \ *(*toP)++ = lo; \ break; \ } \ /* fall through */ \ case 0x1: case 0x2: case 0x3: \ case 0x4: case 0x5: case 0x6: case 0x7: \ if (toLim - *toP < 2) { \ *fromP = from; \ return; \ } \ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ *(*toP)++ = ((lo & 0x3f) | 0x80); \ break; \ default: \ if (toLim - *toP < 3) { \ *fromP = from; \ return; \ } \ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ *(*toP)++ = ((lo & 0x3f) | 0x80); \ break; \ case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ if (toLim - *toP < 4) { \ *fromP = from; \ return; \ } \ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ from += 2; \ lo2 = GET_LO(from); \ *(*toP)++ = (((lo & 0x3) << 4) \ | ((GET_HI(from) & 0x3) << 2) \ | (lo2 >> 6) \ | 0x80); \ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ break; \ } \ } \ *fromP = from; \ } #define DEFINE_UTF16_TO_UTF16(E) \ static void PTRCALL \ E ## toUtf16(const ENCODING *enc, \ const char **fromP, const char *fromLim, \ unsigned short **toP, const unsigned short *toLim) \ { \ /* Avoid copying first half only of surrogate */ \ if (fromLim - *fromP > ((toLim - *toP) << 1) \ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ fromLim -= 2; \ for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ } #define SET2(ptr, ch) \ (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) #define GET_LO(ptr) ((unsigned char)(ptr)[0]) #define GET_HI(ptr) ((unsigned char)(ptr)[1]) DEFINE_UTF16_TO_UTF8(little2_) DEFINE_UTF16_TO_UTF16(little2_) #undef SET2 #undef GET_LO #undef GET_HI #define SET2(ptr, ch) \ (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) #define GET_LO(ptr) ((unsigned char)(ptr)[1]) #define GET_HI(ptr) ((unsigned char)(ptr)[0]) DEFINE_UTF16_TO_UTF8(big2_) DEFINE_UTF16_TO_UTF16(big2_) #undef SET2 #undef GET_LO #undef GET_HI #define LITTLE2_BYTE_TYPE(enc, p) \ ((p)[1] == 0 \ ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ : unicode_byte_type((p)[1], (p)[0])) #define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) #define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) #define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) #define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) #ifdef XML_MIN_SIZE static int PTRFASTCALL little2_byteType(const ENCODING *enc, const char *p) { return LITTLE2_BYTE_TYPE(enc, p); } static int PTRFASTCALL little2_byteToAscii(const ENCODING *enc, const char *p) { return LITTLE2_BYTE_TO_ASCII(enc, p); } static int PTRCALL little2_charMatches(const ENCODING *enc, const char *p, int c) { return LITTLE2_CHAR_MATCHES(enc, p, c); } static int PTRFASTCALL little2_isNameMin(const ENCODING *enc, const char *p) { return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); } static int PTRFASTCALL little2_isNmstrtMin(const ENCODING *enc, const char *p) { return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); } #undef VTABLE #define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 #else /* not XML_MIN_SIZE */ #undef PREFIX #define PREFIX(ident) little2_ ## ident #define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ #define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) #define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) #define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) #define IS_NAME_CHAR(enc, p, n) 0 #define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) #define IS_NMSTRT_CHAR(enc, p, n) (0) #define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) #include "xmltok_impl.c" #undef MINBPC #undef BYTE_TYPE #undef BYTE_TO_ASCII #undef CHAR_MATCHES #undef IS_NAME_CHAR #undef IS_NAME_CHAR_MINBPC #undef IS_NMSTRT_CHAR #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR #endif /* not XML_MIN_SIZE */ #ifdef XML_NS static const struct normal_encoding little2_encoding_ns = { { VTABLE, 2, 0, #if BYTEORDER == 1234 1 #else 0 #endif }, { #include "asciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #endif static const struct normal_encoding little2_encoding = { { VTABLE, 2, 0, #if BYTEORDER == 1234 1 #else 0 #endif }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #if BYTEORDER != 4321 #ifdef XML_NS static const struct normal_encoding internal_little2_encoding_ns = { { VTABLE, 2, 0, 1 }, { #include "iasciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #endif static const struct normal_encoding internal_little2_encoding = { { VTABLE, 2, 0, 1 }, { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #endif #define BIG2_BYTE_TYPE(enc, p) \ ((p)[0] == 0 \ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ : unicode_byte_type((p)[0], (p)[1])) #define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) #define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) #define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) #define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) #ifdef XML_MIN_SIZE static int PTRFASTCALL big2_byteType(const ENCODING *enc, const char *p) { return BIG2_BYTE_TYPE(enc, p); } static int PTRFASTCALL big2_byteToAscii(const ENCODING *enc, const char *p) { return BIG2_BYTE_TO_ASCII(enc, p); } static int PTRCALL big2_charMatches(const ENCODING *enc, const char *p, int c) { return BIG2_CHAR_MATCHES(enc, p, c); } static int PTRFASTCALL big2_isNameMin(const ENCODING *enc, const char *p) { return BIG2_IS_NAME_CHAR_MINBPC(enc, p); } static int PTRFASTCALL big2_isNmstrtMin(const ENCODING *enc, const char *p) { return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); } #undef VTABLE #define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 #else /* not XML_MIN_SIZE */ #undef PREFIX #define PREFIX(ident) big2_ ## ident #define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ #define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) #define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) #define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) #define IS_NAME_CHAR(enc, p, n) 0 #define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) #define IS_NMSTRT_CHAR(enc, p, n) (0) #define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) #include "xmltok_impl.c" #undef MINBPC #undef BYTE_TYPE #undef BYTE_TO_ASCII #undef CHAR_MATCHES #undef IS_NAME_CHAR #undef IS_NAME_CHAR_MINBPC #undef IS_NMSTRT_CHAR #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR #endif /* not XML_MIN_SIZE */ #ifdef XML_NS static const struct normal_encoding big2_encoding_ns = { { VTABLE, 2, 0, #if BYTEORDER == 4321 1 #else 0 #endif }, { #include "asciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #endif static const struct normal_encoding big2_encoding = { { VTABLE, 2, 0, #if BYTEORDER == 4321 1 #else 0 #endif }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #if BYTEORDER != 1234 #ifdef XML_NS static const struct normal_encoding internal_big2_encoding_ns = { { VTABLE, 2, 0, 1 }, { #include "iasciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #endif static const struct normal_encoding internal_big2_encoding = { { VTABLE, 2, 0, 1 }, { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #endif #undef PREFIX static int FASTCALL streqci(const char *s1, const char *s2) { for (;;) { char c1 = *s1++; char c2 = *s2++; if (ASCII_a <= c1 && c1 <= ASCII_z) c1 += ASCII_A - ASCII_a; if (ASCII_a <= c2 && c2 <= ASCII_z) c2 += ASCII_A - ASCII_a; if (c1 != c2) return 0; if (!c1) break; } return 1; } static void PTRCALL initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end, POSITION *pos) { normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); } static int toAscii(const ENCODING *enc, const char *ptr, const char *end) { char buf[1]; char *p = buf; XmlUtf8Convert(enc, &ptr, end, &p, p + 1); if (p == buf) return -1; else return buf[0]; } static int FASTCALL isSpace(int c) { switch (c) { case 0x20: case 0xD: case 0xA: case 0x9: return 1; } return 0; } /* Return 1 if there's just optional white space or there's an S followed by name=val. */ static int parsePseudoAttribute(const ENCODING *enc, const char *ptr, const char *end, const char **namePtr, const char **nameEndPtr, const char **valPtr, const char **nextTokPtr) { int c; char open; if (ptr == end) { *namePtr = NULL; return 1; } if (!isSpace(toAscii(enc, ptr, end))) { *nextTokPtr = ptr; return 0; } do { ptr += enc->minBytesPerChar; } while (isSpace(toAscii(enc, ptr, end))); if (ptr == end) { *namePtr = NULL; return 1; } *namePtr = ptr; for (;;) { c = toAscii(enc, ptr, end); if (c == -1) { *nextTokPtr = ptr; return 0; } if (c == ASCII_EQUALS) { *nameEndPtr = ptr; break; } if (isSpace(c)) { *nameEndPtr = ptr; do { ptr += enc->minBytesPerChar; } while (isSpace(c = toAscii(enc, ptr, end))); if (c != ASCII_EQUALS) { *nextTokPtr = ptr; return 0; } break; } ptr += enc->minBytesPerChar; } if (ptr == *namePtr) { *nextTokPtr = ptr; return 0; } ptr += enc->minBytesPerChar; c = toAscii(enc, ptr, end); while (isSpace(c)) { ptr += enc->minBytesPerChar; c = toAscii(enc, ptr, end); } if (c != ASCII_QUOT && c != ASCII_APOS) { *nextTokPtr = ptr; return 0; } open = (char)c; ptr += enc->minBytesPerChar; *valPtr = ptr; for (;; ptr += enc->minBytesPerChar) { c = toAscii(enc, ptr, end); if (c == open) break; if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z) && !(ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD && c != ASCII_MINUS && c != ASCII_UNDERSCORE) { *nextTokPtr = ptr; return 0; } } *nextTokPtr = ptr + enc->minBytesPerChar; return 1; } static const char KW_version[] = { ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0' }; static const char KW_encoding[] = { ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0' }; static const char KW_standalone[] = { ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0' }; static const char KW_yes[] = { ASCII_y, ASCII_e, ASCII_s, '\0' }; static const char KW_no[] = { ASCII_n, ASCII_o, '\0' }; static int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *, const char *), int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingName, const ENCODING **encoding, int *standalone) { const char *val = NULL; const char *name = NULL; const char *nameEnd = NULL; ptr += 5 * enc->minBytesPerChar; end -= 2 * enc->minBytesPerChar; if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || !name) { *badPtr = ptr; return 0; } if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) { if (!isGeneralTextEntity) { *badPtr = name; return 0; } } else { if (versionPtr) *versionPtr = val; if (versionEndPtr) *versionEndPtr = ptr; if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { *badPtr = ptr; return 0; } if (!name) { if (isGeneralTextEntity) { /* a TextDecl must have an EncodingDecl */ *badPtr = ptr; return 0; } return 1; } } if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) { int c = toAscii(enc, val, end); if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) { *badPtr = val; return 0; } if (encodingName) *encodingName = val; if (encoding) *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { *badPtr = ptr; return 0; } if (!name) return 1; } if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) { *badPtr = name; return 0; } if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) { if (standalone) *standalone = 1; } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) { if (standalone) *standalone = 0; } else { *badPtr = val; return 0; } while (isSpace(toAscii(enc, ptr, end))) ptr += enc->minBytesPerChar; if (ptr != end) { *badPtr = ptr; return 0; } return 1; } static int FASTCALL checkCharRefNumber(int result) { switch (result >> 8) { case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: return -1; case 0: if (latin1_encoding.type[result] == BT_NONXML) return -1; break; case 0xFF: if (result == 0xFFFE || result == 0xFFFF) return -1; break; } return result; } int FASTCALL XmlUtf8Encode(int c, char *buf) { enum { /* minN is minimum legal resulting value for N byte sequence */ min2 = 0x80, min3 = 0x800, min4 = 0x10000 }; if (c < 0) return 0; if (c < min2) { buf[0] = (char)(c | UTF8_cval1); return 1; } if (c < min3) { buf[0] = (char)((c >> 6) | UTF8_cval2); buf[1] = (char)((c & 0x3f) | 0x80); return 2; } if (c < min4) { buf[0] = (char)((c >> 12) | UTF8_cval3); buf[1] = (char)(((c >> 6) & 0x3f) | 0x80); buf[2] = (char)((c & 0x3f) | 0x80); return 3; } if (c < 0x110000) { buf[0] = (char)((c >> 18) | UTF8_cval4); buf[1] = (char)(((c >> 12) & 0x3f) | 0x80); buf[2] = (char)(((c >> 6) & 0x3f) | 0x80); buf[3] = (char)((c & 0x3f) | 0x80); return 4; } return 0; } int FASTCALL XmlUtf16Encode(int charNum, unsigned short *buf) { if (charNum < 0) return 0; if (charNum < 0x10000) { buf[0] = (unsigned short)charNum; return 1; } if (charNum < 0x110000) { charNum -= 0x10000; buf[0] = (unsigned short)((charNum >> 10) + 0xD800); buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00); return 2; } return 0; } struct unknown_encoding { struct normal_encoding normal; int (*convert)(void *userData, const char *p); void *userData; unsigned short utf16[256]; char utf8[256][4]; }; #define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *) (enc)) int XmlSizeOfUnknownEncoding(void) { return sizeof(struct unknown_encoding); } static int PTRFASTCALL unknown_isName(const ENCODING *enc, const char *p) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); int c = uenc->convert(uenc->userData, p); if (c & ~0xFFFF) return 0; return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); } static int PTRFASTCALL unknown_isNmstrt(const ENCODING *enc, const char *p) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); int c = uenc->convert(uenc->userData, p); if (c & ~0xFFFF) return 0; return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); } static int PTRFASTCALL unknown_isInvalid(const ENCODING *enc, const char *p) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); int c = uenc->convert(uenc->userData, p); return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; } static void PTRCALL unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); char buf[XML_UTF8_ENCODE_MAX]; for (;;) { const char *utf8; int n; if (*fromP == fromLim) break; utf8 = uenc->utf8[(unsigned char)**fromP]; n = *utf8++; if (n == 0) { int c = uenc->convert(uenc->userData, *fromP); n = XmlUtf8Encode(c, buf); if (n > toLim - *toP) break; utf8 = buf; *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] - (BT_LEAD2 - 2)); } else { if (n > toLim - *toP) break; (*fromP)++; } do { *(*toP)++ = *utf8++; } while (--n != 0); } } static void PTRCALL unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); while (*fromP != fromLim && *toP != toLim) { unsigned short c = uenc->utf16[(unsigned char)**fromP]; if (c == 0) { c = (unsigned short) uenc->convert(uenc->userData, *fromP); *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] - (BT_LEAD2 - 2)); } else (*fromP)++; *(*toP)++ = c; } } ENCODING * XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, void *userData) { int i; struct unknown_encoding *e = (struct unknown_encoding *)mem; for (i = 0; i < (int)sizeof(struct normal_encoding); i++) ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; for (i = 0; i < 128; i++) if (latin1_encoding.type[i] != BT_OTHER && latin1_encoding.type[i] != BT_NONXML && table[i] != i) return 0; for (i = 0; i < 256; i++) { int c = table[i]; if (c == -1) { e->normal.type[i] = BT_MALFORM; /* This shouldn't really get used. */ e->utf16[i] = 0xFFFF; e->utf8[i][0] = 1; e->utf8[i][1] = 0; } else if (c < 0) { if (c < -4) return 0; e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2)); e->utf8[i][0] = 0; e->utf16[i] = 0; } else if (c < 0x80) { if (latin1_encoding.type[c] != BT_OTHER && latin1_encoding.type[c] != BT_NONXML && c != i) return 0; e->normal.type[i] = latin1_encoding.type[c]; e->utf8[i][0] = 1; e->utf8[i][1] = (char)c; e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c); } else if (checkCharRefNumber(c) < 0) { e->normal.type[i] = BT_NONXML; /* This shouldn't really get used. */ e->utf16[i] = 0xFFFF; e->utf8[i][0] = 1; e->utf8[i][1] = 0; } else { if (c > 0xFFFF) return 0; if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) e->normal.type[i] = BT_NMSTRT; else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) e->normal.type[i] = BT_NAME; else e->normal.type[i] = BT_OTHER; e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); e->utf16[i] = (unsigned short)c; } } e->userData = userData; e->convert = convert; if (convert) { e->normal.isName2 = unknown_isName; e->normal.isName3 = unknown_isName; e->normal.isName4 = unknown_isName; e->normal.isNmstrt2 = unknown_isNmstrt; e->normal.isNmstrt3 = unknown_isNmstrt; e->normal.isNmstrt4 = unknown_isNmstrt; e->normal.isInvalid2 = unknown_isInvalid; e->normal.isInvalid3 = unknown_isInvalid; e->normal.isInvalid4 = unknown_isInvalid; } e->normal.enc.utf8Convert = unknown_toUtf8; e->normal.enc.utf16Convert = unknown_toUtf16; return &(e->normal.enc); } /* If this enumeration is changed, getEncodingIndex and encodings must also be changed. */ enum { UNKNOWN_ENC = -1, ISO_8859_1_ENC = 0, US_ASCII_ENC, UTF_8_ENC, UTF_16_ENC, UTF_16BE_ENC, UTF_16LE_ENC, /* must match encodingNames up to here */ NO_ENC }; static const char KW_ISO_8859_1[] = { ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0' }; static const char KW_US_ASCII[] = { ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0' }; static const char KW_UTF_8[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0' }; static const char KW_UTF_16[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0' }; static const char KW_UTF_16BE[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0' }; static const char KW_UTF_16LE[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0' }; static int FASTCALL getEncodingIndex(const char *name) { static const char *encodingNames[] = { KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE, }; int i; if (name == NULL) return NO_ENC; for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) if (streqci(name, encodingNames[i])) return i; return UNKNOWN_ENC; } /* For binary compatibility, we store the index of the encoding specified at initialization in the isUtf16 member. */ #define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16) #define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i) /* This is what detects the encoding. encodingTable maps from encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; state is XML_CONTENT_STATE if we're parsing an external text entity, and XML_PROLOG_STATE otherwise. */ static int initScan(const ENCODING **encodingTable, const INIT_ENCODING *enc, int state, const char *ptr, const char *end, const char **nextTokPtr) { const ENCODING **encPtr; if (ptr == end) return XML_TOK_NONE; encPtr = enc->encPtr; if (ptr + 1 == end) { /* only a single byte available for auto-detection */ #ifndef XML_DTD /* FIXME */ /* a well-formed document entity must have more than one byte */ if (state != XML_CONTENT_STATE) return XML_TOK_PARTIAL; #endif /* so we're parsing an external text entity... */ /* if UTF-16 was externally specified, then we need at least 2 bytes */ switch (INIT_ENC_INDEX(enc)) { case UTF_16_ENC: case UTF_16LE_ENC: case UTF_16BE_ENC: return XML_TOK_PARTIAL; } switch ((unsigned char)*ptr) { case 0xFE: case 0xFF: case 0xEF: /* possibly first byte of UTF-8 BOM */ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; /* fall through */ case 0x00: case 0x3C: return XML_TOK_PARTIAL; } } else { switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { case 0xFEFF: if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; *nextTokPtr = ptr + 2; *encPtr = encodingTable[UTF_16BE_ENC]; return XML_TOK_BOM; /* 00 3C is handled in the default case */ case 0x3C00: if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC || INIT_ENC_INDEX(enc) == UTF_16_ENC) && state == XML_CONTENT_STATE) break; *encPtr = encodingTable[UTF_16LE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); case 0xFFFE: if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; *nextTokPtr = ptr + 2; *encPtr = encodingTable[UTF_16LE_ENC]; return XML_TOK_BOM; case 0xEFBB: /* Maybe a UTF-8 BOM (EF BB BF) */ /* If there's an explicitly specified (external) encoding of ISO-8859-1 or some flavour of UTF-16 and this is an external text entity, don't look for the BOM, because it might be a legal data. */ if (state == XML_CONTENT_STATE) { int e = INIT_ENC_INDEX(enc); if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) break; } if (ptr + 2 == end) return XML_TOK_PARTIAL; if ((unsigned char)ptr[2] == 0xBF) { *nextTokPtr = ptr + 3; *encPtr = encodingTable[UTF_8_ENC]; return XML_TOK_BOM; } break; default: if (ptr[0] == '\0') { /* 0 isn't a legal data character. Furthermore a document entity can only start with ASCII characters. So the only way this can fail to be big-endian UTF-16 if it it's an external parsed general entity that's labelled as UTF-16LE. */ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) break; *encPtr = encodingTable[UTF_16BE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } else if (ptr[1] == '\0') { /* We could recover here in the case: - parsing an external entity - second byte is 0 - no externally specified encoding - no encoding declaration by assuming UTF-16LE. But we don't, because this would mean when presented just with a single byte, we couldn't reliably determine whether we needed further bytes. */ if (state == XML_CONTENT_STATE) break; *encPtr = encodingTable[UTF_16LE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } break; } } *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } #define NS(x) x #define ns(x) x #include "xmltok_ns.c" #undef NS #undef ns #ifdef XML_NS #define NS(x) x ## NS #define ns(x) x ## _ns #include "xmltok_ns.c" #undef NS #undef ns ENCODING * XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, void *userData) { ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); if (enc) ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; return enc; } #endif /* XML_NS */ PyXML-0.8.2/extensions/expat/lib/xmltok.h0100644000076400001440000002566007614471161017505 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #ifndef XmlTok_INCLUDED #define XmlTok_INCLUDED 1 #ifdef __cplusplus extern "C" { #endif /* The following token may be returned by XmlContentTok */ #define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of illegal ]]> sequence */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ #define XML_TOK_NONE -4 /* The string to be scanned is empty */ #define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; might be part of CRLF sequence */ #define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ #define XML_TOK_PARTIAL -1 /* only part of a token */ #define XML_TOK_INVALID 0 /* The following tokens are returned by XmlContentTok; some are also returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. */ #define XML_TOK_START_TAG_WITH_ATTS 1 #define XML_TOK_START_TAG_NO_ATTS 2 #define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ #define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 #define XML_TOK_END_TAG 5 #define XML_TOK_DATA_CHARS 6 #define XML_TOK_DATA_NEWLINE 7 #define XML_TOK_CDATA_SECT_OPEN 8 #define XML_TOK_ENTITY_REF 9 #define XML_TOK_CHAR_REF 10 /* numeric character reference */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ #define XML_TOK_PI 11 /* processing instruction */ #define XML_TOK_XML_DECL 12 /* XML decl or text decl */ #define XML_TOK_COMMENT 13 #define XML_TOK_BOM 14 /* Byte order mark */ /* The following tokens are returned only by XmlPrologTok */ #define XML_TOK_PROLOG_S 15 #define XML_TOK_DECL_OPEN 16 /* */ #define XML_TOK_NAME 18 #define XML_TOK_NMTOKEN 19 #define XML_TOK_POUND_NAME 20 /* #name */ #define XML_TOK_OR 21 /* | */ #define XML_TOK_PERCENT 22 #define XML_TOK_OPEN_PAREN 23 #define XML_TOK_CLOSE_PAREN 24 #define XML_TOK_OPEN_BRACKET 25 #define XML_TOK_CLOSE_BRACKET 26 #define XML_TOK_LITERAL 27 #define XML_TOK_PARAM_ENTITY_REF 28 #define XML_TOK_INSTANCE_START 29 /* The following occur only in element type declarations */ #define XML_TOK_NAME_QUESTION 30 /* name? */ #define XML_TOK_NAME_ASTERISK 31 /* name* */ #define XML_TOK_NAME_PLUS 32 /* name+ */ #define XML_TOK_COND_SECT_OPEN 33 /* */ #define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ #define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ #define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ #define XML_TOK_COMMA 38 /* The following token is returned only by XmlAttributeValueTok */ #define XML_TOK_ATTRIBUTE_VALUE_S 39 /* The following token is returned only by XmlCdataSectionTok */ #define XML_TOK_CDATA_SECT_CLOSE 40 /* With namespace processing this is returned by XmlPrologTok for a name with a colon. */ #define XML_TOK_PREFIXED_NAME 41 #ifdef XML_DTD #define XML_TOK_IGNORE_SECT 42 #endif /* XML_DTD */ #ifdef XML_DTD #define XML_N_STATES 4 #else /* not XML_DTD */ #define XML_N_STATES 3 #endif /* not XML_DTD */ #define XML_PROLOG_STATE 0 #define XML_CONTENT_STATE 1 #define XML_CDATA_SECTION_STATE 2 #ifdef XML_DTD #define XML_IGNORE_SECTION_STATE 3 #endif /* XML_DTD */ #define XML_N_LITERAL_TYPES 2 #define XML_ATTRIBUTE_VALUE_LITERAL 0 #define XML_ENTITY_VALUE_LITERAL 1 /* The size of the buffer passed to XmlUtf8Encode must be at least this. */ #define XML_UTF8_ENCODE_MAX 4 /* The size of the buffer passed to XmlUtf16Encode must be at least this. */ #define XML_UTF16_ENCODE_MAX 2 typedef struct position { /* first line and first column are 0 not 1 */ unsigned long lineNumber; unsigned long columnNumber; } POSITION; typedef struct { const char *name; const char *valuePtr; const char *valueEnd; char normalized; } ATTRIBUTE; struct encoding; typedef struct encoding ENCODING; typedef int (PTRCALL *SCANNER)(const ENCODING *, const char *, const char *, const char **); struct encoding { SCANNER scanners[XML_N_STATES]; SCANNER literalScanners[XML_N_LITERAL_TYPES]; int (PTRCALL *sameName)(const ENCODING *, const char *, const char *); int (PTRCALL *nameMatchesAscii)(const ENCODING *, const char *, const char *, const char *); int (PTRFASTCALL *nameLength)(const ENCODING *, const char *); const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *); int (PTRCALL *getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts); int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr); int (PTRCALL *predefinedEntityName)(const ENCODING *, const char *, const char *); void (PTRCALL *updatePosition)(const ENCODING *, const char *ptr, const char *end, POSITION *); int (PTRCALL *isPublicId)(const ENCODING *enc, const char *ptr, const char *end, const char **badPtr); void (PTRCALL *utf8Convert)(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim); void (PTRCALL *utf16Convert)(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim); int minBytesPerChar; char isUtf8; char isUtf16; }; /* Scan the string starting at ptr until the end of the next complete token, but do not scan past eptr. Return an integer giving the type of token. Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. Return XML_TOK_PARTIAL when the string does not contain a complete token; nextTokPtr will not be set. Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr will be set to point to the character which made the token invalid. Otherwise the string starts with a valid token; nextTokPtr will be set to point to the character following the end of that token. Each data character counts as a single token, but adjacent data characters may be returned together. Similarly for characters in the prolog outside literals, comments and processing instructions. */ #define XmlTok(enc, state, ptr, end, nextTokPtr) \ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) #define XmlPrologTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) #define XmlContentTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) #define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) #ifdef XML_DTD #define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) #endif /* XML_DTD */ /* This is used for performing a 2nd-level tokenization on the content of a literal that has already been returned by XmlTok. */ #define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) #define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) #define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) #define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) #define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) #define XmlNameLength(enc, ptr) \ (((enc)->nameLength)(enc, ptr)) #define XmlSkipS(enc, ptr) \ (((enc)->skipS)(enc, ptr)) #define XmlGetAttributes(enc, ptr, attsMax, atts) \ (((enc)->getAtts)(enc, ptr, attsMax, atts)) #define XmlCharRefNumber(enc, ptr) \ (((enc)->charRefNumber)(enc, ptr)) #define XmlPredefinedEntityName(enc, ptr, end) \ (((enc)->predefinedEntityName)(enc, ptr, end)) #define XmlUpdatePosition(enc, ptr, end, pos) \ (((enc)->updatePosition)(enc, ptr, end, pos)) #define XmlIsPublicId(enc, ptr, end, badPtr) \ (((enc)->isPublicId)(enc, ptr, end, badPtr)) #define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) #define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) typedef struct { ENCODING initEnc; const ENCODING **encPtr; } INIT_ENCODING; int XmlParseXmlDecl(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingNamePtr, const ENCODING **namedEncodingPtr, int *standalonePtr); int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); const ENCODING *XmlGetUtf8InternalEncoding(void); const ENCODING *XmlGetUtf16InternalEncoding(void); int FASTCALL XmlUtf8Encode(int charNumber, char *buf); int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf); int XmlSizeOfUnknownEncoding(void); typedef int (*CONVERTER)(void *userData, const char *p); ENCODING * XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, void *userData); int XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingNamePtr, const ENCODING **namedEncodingPtr, int *standalonePtr); int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); const ENCODING *XmlGetUtf8InternalEncodingNS(void); const ENCODING *XmlGetUtf16InternalEncodingNS(void); ENCODING * XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, void *userData); #ifdef __cplusplus } #endif #endif /* not XmlTok_INCLUDED */ PyXML-0.8.2/extensions/expat/lib/xmltok_impl.c0100644000076400001440000012666407614471161020527 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ #ifndef IS_INVALID_CHAR #define IS_INVALID_CHAR(enc, ptr, n) (0) #endif #define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_INVALID_CHAR(enc, ptr, n)) { \ *(nextTokPtr) = (ptr); \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; #define INVALID_CASES(ptr, nextTokPtr) \ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ case BT_NONXML: \ case BT_MALFORM: \ case BT_TRAIL: \ *(nextTokPtr) = (ptr); \ return XML_TOK_INVALID; #define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (!IS_NAME_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; #define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ case BT_NONASCII: \ if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ case BT_NMSTRT: \ case BT_HEX: \ case BT_DIGIT: \ case BT_NAME: \ case BT_MINUS: \ ptr += MINBPC(enc); \ break; \ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) #define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; #define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ case BT_NONASCII: \ if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ case BT_NMSTRT: \ case BT_HEX: \ ptr += MINBPC(enc); \ break; \ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) #ifndef PREFIX #define PREFIX(ident) ident #endif /* ptr points to character following " */ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: *nextTokPtr = ptr; return XML_TOK_INVALID; } /* fall through */ case BT_S: case BT_CR: case BT_LF: *nextTokPtr = ptr; return XML_TOK_DECL_OPEN; case BT_NMSTRT: case BT_HEX: ptr += MINBPC(enc); break; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) { int upper = 0; *tokPtr = XML_TOK_PI; if (end - ptr != MINBPC(enc)*3) return 1; switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_x: break; case ASCII_X: upper = 1; break; default: return 1; } ptr += MINBPC(enc); switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_m: break; case ASCII_M: upper = 1; break; default: return 1; } ptr += MINBPC(enc); switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_l: break; case ASCII_L: upper = 1; break; default: return 1; } if (upper) return 0; *tokPtr = XML_TOK_XML_DECL; return 1; } /* ptr points to character following " 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_RSQB: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) break; ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr -= MINBPC(enc); break; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CDATA_SECT_CLOSE; case BT_CR: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; case BT_LF: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; INVALID_CASES(ptr, nextTokPtr) default: ptr += MINBPC(enc); break; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_DATA_CHARS; \ } \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NONXML: case BT_MALFORM: case BT_TRAIL: case BT_CR: case BT_LF: case BT_RSQB: *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } /* ptr points to character following " 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_LT: return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_AMP: return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_CR: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; case BT_LF: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; case BT_RSQB: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_RSQB; if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) break; ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_RSQB; if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr -= MINBPC(enc); break; } *nextTokPtr = ptr; return XML_TOK_INVALID; INVALID_CASES(ptr, nextTokPtr) default: ptr += MINBPC(enc); break; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_DATA_CHARS; \ } \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_RSQB: if (ptr + MINBPC(enc) != end) { if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { ptr += MINBPC(enc); break; } if (ptr + 2*MINBPC(enc) != end) { if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) { ptr += MINBPC(enc); break; } *nextTokPtr = ptr + 2*MINBPC(enc); return XML_TOK_INVALID; } } /* fall through */ case BT_AMP: case BT_LT: case BT_NONXML: case BT_MALFORM: case BT_TRAIL: case BT_CR: case BT_LF: *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } /* ptr points to character following "%" */ static int PTRCALL PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { if (ptr == end) return XML_TOK_PARTIAL; switch (BYTE_TYPE(enc, ptr)) { CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: *nextTokPtr = ptr; return XML_TOK_PERCENT; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_SEMI: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_PARAM_ENTITY_REF; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { if (ptr == end) return XML_TOK_PARTIAL; switch (BYTE_TYPE(enc, ptr)) { CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_CR: case BT_LF: case BT_S: case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: *nextTokPtr = ptr; return XML_TOK_POUND_NAME; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return -XML_TOK_POUND_NAME; } static int PTRCALL PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { while (ptr != end) { int t = BYTE_TYPE(enc, ptr); switch (t) { INVALID_CASES(ptr, nextTokPtr) case BT_QUOT: case BT_APOS: ptr += MINBPC(enc); if (t != open) break; if (ptr == end) return -XML_TOK_LITERAL; *nextTokPtr = ptr; switch (BYTE_TYPE(enc, ptr)) { case BT_S: case BT_CR: case BT_LF: case BT_GT: case BT_PERCNT: case BT_LSQB: return XML_TOK_LITERAL; default: return XML_TOK_INVALID; } default: ptr += MINBPC(enc); break; } } return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { int tok; if (ptr == end) return XML_TOK_NONE; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_QUOT: return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_APOS: return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_LT: { ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; switch (BYTE_TYPE(enc, ptr)) { case BT_EXCL: return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_QUEST: return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_NMSTRT: case BT_HEX: case BT_NONASCII: case BT_LEAD2: case BT_LEAD3: case BT_LEAD4: *nextTokPtr = ptr - MINBPC(enc); return XML_TOK_INSTANCE_START; } *nextTokPtr = ptr; return XML_TOK_INVALID; } case BT_CR: if (ptr + MINBPC(enc) == end) { *nextTokPtr = end; /* indicate that this might be part of a CR/LF pair */ return -XML_TOK_PROLOG_S; } /* fall through */ case BT_S: case BT_LF: for (;;) { ptr += MINBPC(enc); if (ptr == end) break; switch (BYTE_TYPE(enc, ptr)) { case BT_S: case BT_LF: break; case BT_CR: /* don't split CR/LF pair */ if (ptr + MINBPC(enc) != end) break; /* fall through */ default: *nextTokPtr = ptr; return XML_TOK_PROLOG_S; } } *nextTokPtr = ptr; return XML_TOK_PROLOG_S; case BT_PERCNT: return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_COMMA: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_COMMA; case BT_LSQB: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OPEN_BRACKET; case BT_RSQB: ptr += MINBPC(enc); if (ptr == end) return -XML_TOK_CLOSE_BRACKET; if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { if (ptr + MINBPC(enc) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) { *nextTokPtr = ptr + 2*MINBPC(enc); return XML_TOK_COND_SECT_CLOSE; } } *nextTokPtr = ptr; return XML_TOK_CLOSE_BRACKET; case BT_LPAR: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OPEN_PAREN; case BT_RPAR: ptr += MINBPC(enc); if (ptr == end) return -XML_TOK_CLOSE_PAREN; switch (BYTE_TYPE(enc, ptr)) { case BT_AST: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_ASTERISK; case BT_QUEST: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_QUESTION; case BT_PLUS: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_PLUS; case BT_CR: case BT_LF: case BT_S: case BT_GT: case BT_COMMA: case BT_VERBAR: case BT_RPAR: *nextTokPtr = ptr; return XML_TOK_CLOSE_PAREN; } *nextTokPtr = ptr; return XML_TOK_INVALID; case BT_VERBAR: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OR; case BT_GT: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DECL_CLOSE; case BT_NUM: return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ ptr += n; \ tok = XML_TOK_NAME; \ break; \ } \ if (IS_NAME_CHAR(enc, ptr, n)) { \ ptr += n; \ tok = XML_TOK_NMTOKEN; \ break; \ } \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NMSTRT: case BT_HEX: tok = XML_TOK_NAME; ptr += MINBPC(enc); break; case BT_DIGIT: case BT_NAME: case BT_MINUS: #ifdef XML_NS case BT_COLON: #endif tok = XML_TOK_NMTOKEN; ptr += MINBPC(enc); break; case BT_NONASCII: if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { ptr += MINBPC(enc); tok = XML_TOK_NAME; break; } if (IS_NAME_CHAR_MINBPC(enc, ptr)) { ptr += MINBPC(enc); tok = XML_TOK_NMTOKEN; break; } /* fall through */ default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_GT: case BT_RPAR: case BT_COMMA: case BT_VERBAR: case BT_LSQB: case BT_PERCNT: case BT_S: case BT_CR: case BT_LF: *nextTokPtr = ptr; return tok; #ifdef XML_NS case BT_COLON: ptr += MINBPC(enc); switch (tok) { case XML_TOK_NAME: if (ptr == end) return XML_TOK_PARTIAL; tok = XML_TOK_PREFIXED_NAME; switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) default: tok = XML_TOK_NMTOKEN; break; } break; case XML_TOK_PREFIXED_NAME: tok = XML_TOK_NMTOKEN; break; } break; #endif case BT_PLUS: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_PLUS; case BT_AST: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_ASTERISK; case BT_QUEST: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_QUESTION; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return -tok; } static int PTRCALL PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { const char *start; if (ptr == end) return XML_TOK_NONE; start = ptr; while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_AMP: if (ptr == start) return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_LT: /* this is for inside entity references */ *nextTokPtr = ptr; return XML_TOK_INVALID; case BT_LF: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_CR: if (ptr == start) { ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_S: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_ATTRIBUTE_VALUE_S; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } static int PTRCALL PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { const char *start; if (ptr == end) return XML_TOK_NONE; start = ptr; while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_AMP: if (ptr == start) return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_PERCNT: if (ptr == start) { int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_LF: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_CR: if (ptr == start) { ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } #ifdef XML_DTD static int PTRCALL PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { int level = 0; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); end = ptr + n; } } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { INVALID_CASES(ptr, nextTokPtr) case BT_LT: if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) { if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) { ++level; ptr += MINBPC(enc); } } break; case BT_RSQB: if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr += MINBPC(enc); if (level == 0) { *nextTokPtr = ptr; return XML_TOK_IGNORE_SECT; } --level; } } break; default: ptr += MINBPC(enc); break; } } return XML_TOK_PARTIAL; } #endif /* XML_DTD */ static int PTRCALL PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, const char **badPtr) { ptr += MINBPC(enc); end -= MINBPC(enc); for (; ptr != end; ptr += MINBPC(enc)) { switch (BYTE_TYPE(enc, ptr)) { case BT_DIGIT: case BT_HEX: case BT_MINUS: case BT_APOS: case BT_LPAR: case BT_RPAR: case BT_PLUS: case BT_COMMA: case BT_SOL: case BT_EQUALS: case BT_QUEST: case BT_CR: case BT_LF: case BT_SEMI: case BT_EXCL: case BT_AST: case BT_PERCNT: case BT_NUM: #ifdef XML_NS case BT_COLON: #endif break; case BT_S: if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) { *badPtr = ptr; return 0; } break; case BT_NAME: case BT_NMSTRT: if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) break; default: switch (BYTE_TO_ASCII(enc, ptr)) { case 0x24: /* $ */ case 0x40: /* @ */ break; default: *badPtr = ptr; return 0; } break; } } return 1; } /* This must only be called for a well-formed start-tag or empty element tag. Returns the number of attributes. Pointers to the first attsMax attributes are stored in atts. */ static int PTRCALL PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts) { enum { other, inName, inValue } state = inName; int nAtts = 0; int open = 0; /* defined when state == inValue; initialization just to shut up compilers */ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { switch (BYTE_TYPE(enc, ptr)) { #define START_NAME \ if (state == other) { \ if (nAtts < attsMax) { \ atts[nAtts].name = ptr; \ atts[nAtts].normalized = 1; \ } \ state = inName; \ } #define LEAD_CASE(n) \ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NONASCII: case BT_NMSTRT: case BT_HEX: START_NAME break; #undef START_NAME case BT_QUOT: if (state != inValue) { if (nAtts < attsMax) atts[nAtts].valuePtr = ptr + MINBPC(enc); state = inValue; open = BT_QUOT; } else if (open == BT_QUOT) { state = other; if (nAtts < attsMax) atts[nAtts].valueEnd = ptr; nAtts++; } break; case BT_APOS: if (state != inValue) { if (nAtts < attsMax) atts[nAtts].valuePtr = ptr + MINBPC(enc); state = inValue; open = BT_APOS; } else if (open == BT_APOS) { state = other; if (nAtts < attsMax) atts[nAtts].valueEnd = ptr; nAtts++; } break; case BT_AMP: if (nAtts < attsMax) atts[nAtts].normalized = 0; break; case BT_S: if (state == inName) state = other; else if (state == inValue && nAtts < attsMax && atts[nAtts].normalized && (ptr == atts[nAtts].valuePtr || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) atts[nAtts].normalized = 0; break; case BT_CR: case BT_LF: /* This case ensures that the first attribute name is counted Apart from that we could just change state on the quote. */ if (state == inName) state = other; else if (state == inValue && nAtts < attsMax) atts[nAtts].normalized = 0; break; case BT_GT: case BT_SOL: if (state != inValue) return nAtts; break; default: break; } } /* not reached */ } static int PTRFASTCALL PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) { int result = 0; /* skip &# */ ptr += 2*MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_x)) { for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { int c = BYTE_TO_ASCII(enc, ptr); switch (c) { case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4: case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9: result <<= 4; result |= (c - ASCII_0); break; case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F: result <<= 4; result += 10 + (c - ASCII_A); break; case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f: result <<= 4; result += 10 + (c - ASCII_a); break; } if (result >= 0x110000) return -1; } } else { for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { int c = BYTE_TO_ASCII(enc, ptr); result *= 10; result += (c - ASCII_0); if (result >= 0x110000) return -1; } } return checkCharRefNumber(result); } static int PTRCALL PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) { switch ((end - ptr)/MINBPC(enc)) { case 2: if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) { switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_l: return ASCII_LT; case ASCII_g: return ASCII_GT; } } break; case 3: if (CHAR_MATCHES(enc, ptr, ASCII_a)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_m)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_p)) return ASCII_AMP; } } break; case 4: switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_q: ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_u)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_o)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_t)) return ASCII_QUOT; } } break; case ASCII_a: ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_p)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_o)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_s)) return ASCII_APOS; } } break; } } return 0; } static int PTRCALL PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) { for (;;) { switch (BYTE_TYPE(enc, ptr1)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (*ptr1++ != *ptr2++) \ return 0; LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) #undef LEAD_CASE /* fall through */ if (*ptr1++ != *ptr2++) return 0; break; case BT_NONASCII: case BT_NMSTRT: #ifdef XML_NS case BT_COLON: #endif case BT_HEX: case BT_DIGIT: case BT_NAME: case BT_MINUS: if (*ptr2++ != *ptr1++) return 0; if (MINBPC(enc) > 1) { if (*ptr2++ != *ptr1++) return 0; if (MINBPC(enc) > 2) { if (*ptr2++ != *ptr1++) return 0; if (MINBPC(enc) > 3) { if (*ptr2++ != *ptr1++) return 0; } } } break; default: if (MINBPC(enc) == 1 && *ptr1 == *ptr2) return 1; switch (BYTE_TYPE(enc, ptr2)) { case BT_LEAD2: case BT_LEAD3: case BT_LEAD4: case BT_NONASCII: case BT_NMSTRT: #ifdef XML_NS case BT_COLON: #endif case BT_HEX: case BT_DIGIT: case BT_NAME: case BT_MINUS: return 0; default: return 1; } } } /* not reached */ } static int PTRCALL PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *end1, const char *ptr2) { for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { if (ptr1 == end1) return 0; if (!CHAR_MATCHES(enc, ptr1, *ptr2)) return 0; } return ptr1 == end1; } static int PTRFASTCALL PREFIX(nameLength)(const ENCODING *enc, const char *ptr) { const char *start = ptr; for (;;) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NONASCII: case BT_NMSTRT: #ifdef XML_NS case BT_COLON: #endif case BT_HEX: case BT_DIGIT: case BT_NAME: case BT_MINUS: ptr += MINBPC(enc); break; default: return ptr - start; } } } static const char * PTRFASTCALL PREFIX(skipS)(const ENCODING *enc, const char *ptr) { for (;;) { switch (BYTE_TYPE(enc, ptr)) { case BT_LF: case BT_CR: case BT_S: ptr += MINBPC(enc); break; default: return ptr; } } } static void PTRCALL PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end, POSITION *pos) { while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_LF: pos->columnNumber = (unsigned)-1; pos->lineNumber++; ptr += MINBPC(enc); break; case BT_CR: pos->lineNumber++; ptr += MINBPC(enc); if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); pos->columnNumber = (unsigned)-1; break; default: ptr += MINBPC(enc); break; } pos->columnNumber++; } } #undef DO_LEAD_CASE #undef MULTIBYTE_CASES #undef INVALID_CASES #undef CHECK_NAME_CASE #undef CHECK_NAME_CASES #undef CHECK_NMSTRT_CASE #undef CHECK_NMSTRT_CASES PyXML-0.8.2/extensions/expat/lib/xmltok_impl.h0100644000076400001440000000122507335151700020507 0ustar martinusers/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ enum { BT_NONXML, BT_MALFORM, BT_LT, BT_AMP, BT_RSQB, BT_LEAD2, BT_LEAD3, BT_LEAD4, BT_TRAIL, BT_CR, BT_LF, BT_GT, BT_QUOT, BT_APOS, BT_EQUALS, BT_QUEST, BT_EXCL, BT_SOL, BT_SEMI, BT_NUM, BT_LSQB, BT_S, BT_NMSTRT, BT_COLON, BT_HEX, BT_DIGIT, BT_NAME, BT_MINUS, BT_OTHER, /* known not to be a name or name start character */ BT_NONASCII, /* might be a name or name start character */ BT_PERCNT, BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, BT_COMMA, BT_VERBAR }; #include PyXML-0.8.2/extensions/expat/lib/xmltok_ns.c0100644000076400001440000000557707614471161020205 0ustar martinusersconst ENCODING * NS(XmlGetUtf8InternalEncoding)(void) { return &ns(internal_utf8_encoding).enc; } const ENCODING * NS(XmlGetUtf16InternalEncoding)(void) { #if BYTEORDER == 1234 return &ns(internal_little2_encoding).enc; #elif BYTEORDER == 4321 return &ns(internal_big2_encoding).enc; #else const short n = 1; return (*(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc); #endif } static const ENCODING *NS(encodings)[] = { &ns(latin1_encoding).enc, &ns(ascii_encoding).enc, &ns(utf8_encoding).enc, &ns(big2_encoding).enc, &ns(big2_encoding).enc, &ns(little2_encoding).enc, &ns(utf8_encoding).enc /* NO_ENC */ }; static int PTRCALL NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); } static int PTRCALL NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); } int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) { int i = getEncodingIndex(name); if (i == UNKNOWN_ENC) return 0; SET_INIT_ENC_INDEX(p, i); p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); p->initEnc.updatePosition = initUpdatePosition; p->encPtr = encPtr; *encPtr = &(p->initEnc); return 1; } static const ENCODING * NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) { #define ENCODING_MAX 128 char buf[ENCODING_MAX]; char *p = buf; int i; XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); if (ptr != end) return 0; *p = 0; if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) return enc; i = getEncodingIndex(buf); if (i == UNKNOWN_ENC) return 0; return NS(encodings)[i]; } int NS(XmlParseXmlDecl)(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingName, const ENCODING **encoding, int *standalone) { return doParseXmlDecl(NS(findEncoding), isGeneralTextEntity, enc, ptr, end, badPtr, versionPtr, versionEndPtr, encodingName, encoding, standalone); } PyXML-0.8.2/extensions/boolean.c0100644000076400001440000002044607537736433015721 0ustar martinusers/* Boolean extension, by Uche Ogbuji Copyright (c) 2001 Fourthought, Inc. USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information */ #include "Python.h" #include #include #include #if defined(_WIN32) || defined(__WIN32__) #include #define NaN_Check(x) _isnan(x) #define Inf_Check(x) (_finite(x) && !_isnan(x)) #else #include #define NaN_Check(x) isnan(x) #define Inf_Check(x) isinf(x) #endif #define Boolean_Check(v) ((v)->ob_type == &PyBoolean_Type) #define Boolean_Value(v) (((PyBooleanObject *)(v))->value) typedef struct { PyObject_HEAD int value; } PyBooleanObject; static PyBooleanObject *g_true; static PyBooleanObject *g_false; static PyObject *g_true_string; static PyObject *g_false_string; static PyTypeObject PyBoolean_Type; static PyObject * BooleanValue(PyObject *self, PyObject *args) { PyObject *obj; PyObject *str_func; PyBooleanObject *result = NULL; if (!PyArg_ParseTuple(args, "O|O:BooleanValue", &obj, &str_func)) return NULL; if (Boolean_Check(obj)){ result = (PyBooleanObject *)obj; } else if (PyFloat_Check(obj)) { if (NaN_Check(PyFloat_AS_DOUBLE(obj))) { result = g_false; } else { result = PyObject_IsTrue(obj) ? g_true : g_false; } } else if (PyNumber_Check(obj) || PySequence_Check(obj)){ result = PyObject_IsTrue(obj) ? g_true : g_false; } else if (str_func) { obj = PyObject_CallFunction(str_func, "(O)", obj); if (!obj) return NULL; result = PyObject_IsTrue(obj) ? g_true : g_false; Py_DECREF(obj); } else { result = g_false; } Py_INCREF(result); return (PyObject *)result; } static int pyobj_as_boolean_int(PyObject *obj) { if (Boolean_Check(obj)) return Boolean_Value((PyBooleanObject *)obj); else if (PyNumber_Check(obj) || PySequence_Check(obj)) return PyObject_IsTrue(obj) ? 1 : 0; else return 0; } static PyObject * IsBooleanType(PyObject *self, PyObject *args) { PyObject *obj; PyObject *result = NULL; if (!PyArg_ParseTuple(args, "O:IsBooleanType", &obj)) return NULL; if (Boolean_Check(obj)) result = Py_True; else result = Py_False; Py_INCREF(result); return result; } static PyBooleanObject * boolean_NEW(int initval) { PyBooleanObject *object = PyObject_NEW(PyBooleanObject, &PyBoolean_Type); object->value = initval; return object; } static void boolean_dealloc(PyObject *self) { PyMem_DEL(self); } static int boolean_cmp(PyObject *o1, PyObject *o2){ int result = -1; PyBooleanObject *b1; PyBooleanObject *b2; if (Boolean_Check(o1) && Boolean_Check(o2)) { b1 = (PyBooleanObject *)o1; b2 = (PyBooleanObject *)o2; result = !(Boolean_Value(o1) == Boolean_Value(o2)); } else if (Boolean_Check(o1)) { b1 = (PyBooleanObject *)o1; result = !(Boolean_Value(o1) == pyobj_as_boolean_int(o2)); } else if (Boolean_Check(o2)) { b2 = (PyBooleanObject *)o2; result = !(Boolean_Value(o2) == pyobj_as_boolean_int(o1)); } return result; } static PyObject * boolean_repr(PyObject *self) { PyObject *result; if (Boolean_Value((PyBooleanObject *)self)) result = g_true_string; else result = g_false_string; Py_INCREF(result); return result; } static int boolean_coerce(PyObject **v, PyObject **w) { PyObject *newv, *neww; if ((*v)->ob_type == (*w)->ob_type){ Py_INCREF(*v); Py_INCREF(*w); return 0; } newv = PyNumber_Int(*v); neww = PyNumber_Int(*w); if (newv && neww){ *v = newv; *w = neww; return 0; } Py_XDECREF(newv); Py_XDECREF(neww); return -1; /* couldn't do it */ } static PyObject * boolean_and(PyObject *o1, PyObject *o2) { /* FIXME: Check whether we need to conver the 1st arg. The Python/C docs don't help */ int lhs = pyobj_as_boolean_int(o1), rhs = pyobj_as_boolean_int(o2); PyObject *result = NULL; result = PyInt_FromLong((long)(lhs && rhs)); Py_INCREF(result); return result; } static PyObject * boolean_or(PyObject *o1, PyObject *o2) { /* FIXME: Check whether we need to conver the 1st arg. The Python/C docs don't help */ int lhs = pyobj_as_boolean_int(o1), rhs = pyobj_as_boolean_int(o2); return PyInt_FromLong((long)(lhs || rhs)); } static PyObject * boolean_xor(PyObject *o1, PyObject *o2) { /* FIXME: Check whether we need to conver the 1st arg. The Python/C docs don't help */ int lhs = pyobj_as_boolean_int(o1), rhs = pyobj_as_boolean_int(o2); return PyInt_FromLong((long)(lhs ^ rhs)); } static int boolean_nonzero(PyObject *o) { return Boolean_Value((PyBooleanObject *)o); } static PyObject * boolean_int(PyObject *o) { PyBooleanObject *obj = (PyBooleanObject *)o; return PyInt_FromLong((long)Boolean_Value(obj)); } static PyObject * boolean_long(PyObject *o) { PyBooleanObject *obj = (PyBooleanObject *)o; return PyLong_FromLong((long)Boolean_Value(obj)); } static PyObject * boolean_float(PyObject *o) { PyBooleanObject *obj = (PyBooleanObject *)o; return PyFloat_FromDouble((double)Boolean_Value(obj)); } static PyNumberMethods boolean_as_number = { 0, /* binaryfunc nb_add; __add__ */ 0, /* binaryfunc nb_subtract; __sub__ */ 0, /* binaryfunc nb_multiply; __mul__ */ 0, /* binaryfunc nb_divide; __div__ */ 0, /* binaryfunc nb_remainder; __mod__ */ 0, /* binaryfunc nb_divmod; __divmod__ */ 0, /* ternaryfunc nb_power; __pow__ */ 0, /* unaryfunc nb_negative; __neg__ */ 0, /* unaryfunc nb_positive; __pos__ */ 0, /* unaryfunc nb_absolute; __abs__ */ boolean_nonzero, /* inquiry nb_nonzero; __nonzero__ */ 0, /* unaryfunc nb_invert; __invert__ */ 0, /* binaryfunc nb_lshift; __lshift__ */ 0, /* binaryfunc nb_rshift; __rshift__ */ boolean_and, /* binaryfunc nb_and; __and__ */ boolean_xor, /* binaryfunc nb_xor; __xor__ */ boolean_or, /* binaryfunc nb_or; __or__ */ boolean_coerce, /* coercion nb_coerce; __coerce__ */ boolean_int, /* unaryfunc nb_int; __int__ */ boolean_long, /* unaryfunc nb_long; __long__ */ boolean_float, /* unaryfunc nb_float; __float__ */ 0, /* unaryfunc nb_oct; __oct__ */ 0, /* unaryfunc nb_hex; __hex__ */ }; static PyTypeObject PyBoolean_Type = { PyObject_HEAD_INIT(0) 0, "boolean", sizeof(PyBooleanObject), 0, boolean_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ (cmpfunc)boolean_cmp, /* tp_compare */ boolean_repr, /* tp_repr */ &boolean_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ }; static PyMethodDef booleanMethods[] = { { "BooleanValue", BooleanValue, METH_VARARGS }, { "IsBooleanType", IsBooleanType, METH_VARARGS }, { NULL, NULL } }; DL_EXPORT(void) initboolean(void) { PyObject *m; m = Py_InitModule("boolean", booleanMethods); PyBoolean_Type.ob_type = &PyType_Type; Py_INCREF(&PyBoolean_Type); PyModule_AddObject(m, "BooleanType", (PyObject *)&PyBoolean_Type); if (g_true_string == NULL) g_true_string = PyString_FromString("true"); if (g_false_string == NULL) g_false_string = PyString_FromString("false"); if (g_true == NULL) g_true = boolean_NEW(1); if (g_false == NULL) g_false = boolean_NEW(0); Py_INCREF(g_true); PyModule_AddObject(m, "true", (PyObject *)g_true); Py_INCREF(g_false); PyModule_AddObject(m, "false", (PyObject *)g_false); return; } PyXML-0.8.2/extensions/pyexpat.c0100644000076400001440000016365607614471161015775 0ustar martinusers/* Based on Python's pyexpat.c, see the revision number in * get_version_string(). After integrating a new version from Python, * the version string in get_version_string() must be corrected. */ #include "Python.h" #include #include "compile.h" #include "frameobject.h" #include "expat.h" #define XML_COMBINED_VERSION (10000*XML_MAJOR_VERSION+100*XML_MINOR_VERSION+XML_MICRO_VERSION) #ifndef PyDoc_STRVAR /* * fdrake says: * Don't change the PyDoc_STR macro definition to (str), because * '''the parentheses cause compile failures * ("non-constant static initializer" or something like that) * on some platforms (Irix?)''' */ #define PyDoc_STR(str) str #define PyDoc_VAR(name) static char name[] #define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) #endif #if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2) /* In Python 2.0 and 2.1, disabling Unicode was not possible. */ #define Py_USING_UNICODE #define NOFIX_TRACE #endif enum HandlerTypes { StartElement, EndElement, ProcessingInstruction, CharacterData, UnparsedEntityDecl, NotationDecl, StartNamespaceDecl, EndNamespaceDecl, Comment, StartCdataSection, EndCdataSection, Default, DefaultHandlerExpand, NotStandalone, ExternalEntityRef, StartDoctypeDecl, EndDoctypeDecl, EntityDecl, XmlDecl, ElementDecl, AttlistDecl, #if XML_COMBINED_VERSION >= 19504 SkippedEntity, #endif _DummyDecl }; static PyObject *ErrorObject; /* ----------------------------------------------------- */ /* Declarations for objects of type xmlparser */ typedef struct { PyObject_HEAD XML_Parser itself; int returns_unicode; /* True if Unicode strings are returned; if false, UTF-8 strings are returned */ int ordered_attributes; /* Return attributes as a list. */ int specified_attributes; /* Report only specified attributes. */ int in_callback; /* Is a callback active? */ int ns_prefixes; /* Namespace-triplets mode? */ XML_Char *buffer; /* Buffer used when accumulating characters */ /* NULL if not enabled */ int buffer_size; /* Size of buffer, in XML_Char units */ int buffer_used; /* Buffer units in use */ PyObject *intern; /* Dictionary to intern strings */ PyObject **handlers; } xmlparseobject; #define CHARACTER_DATA_BUFFER_SIZE 8192 static PyTypeObject Xmlparsetype; typedef void (*xmlhandlersetter)(XML_Parser self, void *meth); typedef void* xmlhandler; struct HandlerInfo { const char *name; xmlhandlersetter setter; xmlhandler handler; PyCodeObject *tb_code; PyObject *nameobj; }; static struct HandlerInfo handler_info[64]; /* Set an integer attribute on the error object; return true on success, * false on an exception. */ static int set_error_attr(PyObject *err, char *name, int value) { PyObject *v = PyInt_FromLong(value); if (v != NULL && PyObject_SetAttrString(err, name, v) == -1) { Py_DECREF(v); return 0; } return 1; } /* Build and set an Expat exception, including positioning * information. Always returns NULL. */ static PyObject * set_error(xmlparseobject *self, enum XML_Error code) { PyObject *err; char buffer[256]; XML_Parser parser = self->itself; int lineno = XML_GetErrorLineNumber(parser); int column = XML_GetErrorColumnNumber(parser); /* There is no risk of overflowing this buffer, since even for 64-bit integers, there is sufficient space. */ sprintf(buffer, "%.200s: line %i, column %i", XML_ErrorString(code), lineno, column); err = PyObject_CallFunction(ErrorObject, "s", buffer); if ( err != NULL && set_error_attr(err, "code", code) && set_error_attr(err, "offset", column) && set_error_attr(err, "lineno", lineno)) { PyErr_SetObject(ErrorObject, err); } return NULL; } static int have_handler(xmlparseobject *self, int type) { PyObject *handler = self->handlers[type]; return handler != NULL; } static PyObject * get_handler_name(struct HandlerInfo *hinfo) { PyObject *name = hinfo->nameobj; if (name == NULL) { name = PyString_FromString(hinfo->name); hinfo->nameobj = name; } Py_XINCREF(name); return name; } #ifdef Py_USING_UNICODE /* Convert a string of XML_Chars into a Unicode string. Returns None if str is a null pointer. */ static PyObject * conv_string_to_unicode(const XML_Char *str) { /* XXX currently this code assumes that XML_Char is 8-bit, and hence in UTF-8. */ /* UTF-8 from Expat, Unicode desired */ if (str == NULL) { Py_INCREF(Py_None); return Py_None; } return PyUnicode_DecodeUTF8(str, strlen(str), "strict"); } static PyObject * conv_string_len_to_unicode(const XML_Char *str, int len) { /* XXX currently this code assumes that XML_Char is 8-bit, and hence in UTF-8. */ /* UTF-8 from Expat, Unicode desired */ if (str == NULL) { Py_INCREF(Py_None); return Py_None; } return PyUnicode_DecodeUTF8((const char *)str, len, "strict"); } #endif /* Convert a string of XML_Chars into an 8-bit Python string. Returns None if str is a null pointer. */ static PyObject * conv_string_to_utf8(const XML_Char *str) { /* XXX currently this code assumes that XML_Char is 8-bit, and hence in UTF-8. */ /* UTF-8 from Expat, UTF-8 desired */ if (str == NULL) { Py_INCREF(Py_None); return Py_None; } return PyString_FromString(str); } static PyObject * conv_string_len_to_utf8(const XML_Char *str, int len) { /* XXX currently this code assumes that XML_Char is 8-bit, and hence in UTF-8. */ /* UTF-8 from Expat, UTF-8 desired */ if (str == NULL) { Py_INCREF(Py_None); return Py_None; } return PyString_FromStringAndSize((const char *)str, len); } /* Callback routines */ static void clear_handlers(xmlparseobject *self, int initial); /* This handler is used when an error has been detected, in the hope that actual parsing can be terminated early. This will only help if an external entity reference is encountered. */ static int error_external_entity_ref_handler(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { return 0; } static void flag_error(xmlparseobject *self) { clear_handlers(self, 0); XML_SetExternalEntityRefHandler(self->itself, error_external_entity_ref_handler); } static PyCodeObject* getcode(enum HandlerTypes slot, char* func_name, int lineno) { PyObject *code = NULL; PyObject *name = NULL; PyObject *nulltuple = NULL; PyObject *filename = NULL; if (handler_info[slot].tb_code == NULL) { code = PyString_FromString(""); if (code == NULL) goto failed; name = PyString_FromString(func_name); if (name == NULL) goto failed; nulltuple = PyTuple_New(0); if (nulltuple == NULL) goto failed; filename = PyString_FromString(__FILE__); handler_info[slot].tb_code = PyCode_New(0, /* argcount */ 0, /* nlocals */ 0, /* stacksize */ 0, /* flags */ code, /* code */ nulltuple, /* consts */ nulltuple, /* names */ nulltuple, /* varnames */ #if PYTHON_API_VERSION >= 1010 nulltuple, /* freevars */ nulltuple, /* cellvars */ #endif filename, /* filename */ name, /* name */ lineno, /* firstlineno */ code /* lnotab */ ); if (handler_info[slot].tb_code == NULL) goto failed; Py_DECREF(code); Py_DECREF(nulltuple); Py_DECREF(filename); Py_DECREF(name); } return handler_info[slot].tb_code; failed: Py_XDECREF(code); Py_XDECREF(name); return NULL; } #ifndef NOFIX_TRACE static int trace_frame(PyThreadState *tstate, PyFrameObject *f, int code, PyObject *val) { int result = 0; if (!tstate->use_tracing || tstate->tracing) return 0; if (tstate->c_profilefunc != NULL) { tstate->tracing++; result = tstate->c_profilefunc(tstate->c_profileobj, f, code , val); tstate->use_tracing = ((tstate->c_tracefunc != NULL) || (tstate->c_profilefunc != NULL)); tstate->tracing--; if (result) return result; } if (tstate->c_tracefunc != NULL) { tstate->tracing++; result = tstate->c_tracefunc(tstate->c_traceobj, f, code , val); tstate->use_tracing = ((tstate->c_tracefunc != NULL) || (tstate->c_profilefunc != NULL)); tstate->tracing--; } return result; } #endif static PyObject* call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args) { PyThreadState *tstate = PyThreadState_GET(); PyFrameObject *f; PyObject *res; if (c == NULL) return NULL; f = PyFrame_New( tstate, /*back*/ c, /*code*/ PyEval_GetGlobals(), /*globals*/ NULL /*locals*/ ); if (f == NULL) return NULL; tstate->frame = f; #ifndef NOFIX_TRACE if (trace_frame(tstate, f, PyTrace_CALL, Py_None)) { Py_DECREF(f); return NULL; } #endif res = PyEval_CallObject(func, args); if (res == NULL && tstate->curexc_traceback == NULL) PyTraceBack_Here(f); #ifndef NOFIX_TRACE else { if (trace_frame(tstate, f, PyTrace_RETURN, res)) { Py_XDECREF(res); res = NULL; } } #endif tstate->frame = f->f_back; Py_DECREF(f); return res; } #ifndef Py_USING_UNICODE #define STRING_CONV_FUNC conv_string_to_utf8 #else /* Python 2.0 and later versions, when built with Unicode support */ #define STRING_CONV_FUNC (self->returns_unicode \ ? conv_string_to_unicode : conv_string_to_utf8) #endif static PyObject* string_intern(xmlparseobject *self, const char* str) { PyObject *result = STRING_CONV_FUNC(str); PyObject *value; if (!self->intern) return result; value = PyDict_GetItem(self->intern, result); if (!value) { if (PyDict_SetItem(self->intern, result, result) == 0) return result; else return NULL; } Py_INCREF(value); Py_DECREF(result); return value; } /* Return 0 on success, -1 on exception. * flag_error() will be called before return if needed. */ static int call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len) { PyObject *args; PyObject *temp; args = PyTuple_New(1); if (args == NULL) return -1; #ifdef Py_USING_UNICODE temp = (self->returns_unicode ? conv_string_len_to_unicode(buffer, len) : conv_string_len_to_utf8(buffer, len)); #else temp = conv_string_len_to_utf8(buffer, len); #endif if (temp == NULL) { Py_DECREF(args); flag_error(self); return -1; } PyTuple_SET_ITEM(args, 0, temp); /* temp is now a borrowed reference; consider it unused. */ self->in_callback = 1; temp = call_with_frame(getcode(CharacterData, "CharacterData", __LINE__), self->handlers[CharacterData], args); /* temp is an owned reference again, or NULL */ self->in_callback = 0; Py_DECREF(args); if (temp == NULL) { flag_error(self); return -1; } Py_DECREF(temp); return 0; } static int flush_character_buffer(xmlparseobject *self) { int rc; if (self->buffer == NULL || self->buffer_used == 0) return 0; rc = call_character_handler(self, self->buffer, self->buffer_used); self->buffer_used = 0; return rc; } static void my_CharacterDataHandler(void *userData, const XML_Char *data, int len) { xmlparseobject *self = (xmlparseobject *) userData; if (self->buffer == NULL) call_character_handler(self, data, len); else { if ((self->buffer_used + len) > self->buffer_size) { if (flush_character_buffer(self) < 0) return; /* handler might have changed; drop the rest on the floor * if there isn't a handler anymore */ if (!have_handler(self, CharacterData)) return; } if (len > self->buffer_size) { call_character_handler(self, data, len); self->buffer_used = 0; } else { memcpy(self->buffer + self->buffer_used, data, len * sizeof(XML_Char)); self->buffer_used += len; } } } static void my_StartElementHandler(void *userData, const XML_Char *name, const XML_Char *atts[]) { xmlparseobject *self = (xmlparseobject *)userData; if (have_handler(self, StartElement)) { PyObject *container, *rv, *args; int i, max; if (flush_character_buffer(self) < 0) return; /* Set max to the number of slots filled in atts[]; max/2 is * the number of attributes we need to process. */ if (self->specified_attributes) { max = XML_GetSpecifiedAttributeCount(self->itself); } else { max = 0; while (atts[max] != NULL) max += 2; } /* Build the container. */ if (self->ordered_attributes) container = PyList_New(max); else container = PyDict_New(); if (container == NULL) { flag_error(self); return; } for (i = 0; i < max; i += 2) { PyObject *n = string_intern(self, (XML_Char *) atts[i]); PyObject *v; if (n == NULL) { flag_error(self); Py_DECREF(container); return; } v = STRING_CONV_FUNC((XML_Char *) atts[i+1]); if (v == NULL) { flag_error(self); Py_DECREF(container); Py_DECREF(n); return; } if (self->ordered_attributes) { PyList_SET_ITEM(container, i, n); PyList_SET_ITEM(container, i+1, v); } else if (PyDict_SetItem(container, n, v)) { flag_error(self); Py_DECREF(n); Py_DECREF(v); return; } else { Py_DECREF(n); Py_DECREF(v); } } args = Py_BuildValue("(NN)", string_intern(self, name), container); if (args == NULL) { Py_DECREF(container); return; } /* Container is now a borrowed reference; ignore it. */ self->in_callback = 1; rv = call_with_frame(getcode(StartElement, "StartElement", __LINE__), self->handlers[StartElement], args); self->in_callback = 0; Py_DECREF(args); if (rv == NULL) { flag_error(self); return; } Py_DECREF(rv); } } #define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \ RETURN, GETUSERDATA) \ static RC \ my_##NAME##Handler PARAMS {\ xmlparseobject *self = GETUSERDATA ; \ PyObject *args = NULL; \ PyObject *rv = NULL; \ INIT \ \ if (have_handler(self, NAME)) { \ if (flush_character_buffer(self) < 0) \ return RETURN; \ args = Py_BuildValue PARAM_FORMAT ;\ if (!args) { flag_error(self); return RETURN;} \ self->in_callback = 1; \ rv = call_with_frame(getcode(NAME,#NAME,__LINE__), \ self->handlers[NAME], args); \ self->in_callback = 0; \ Py_DECREF(args); \ if (rv == NULL) { \ flag_error(self); \ return RETURN; \ } \ CONVERSION \ Py_DECREF(rv); \ } \ return RETURN; \ } #define VOID_HANDLER(NAME, PARAMS, PARAM_FORMAT) \ RC_HANDLER(void, NAME, PARAMS, ;, PARAM_FORMAT, ;, ;,\ (xmlparseobject *)userData) #define INT_HANDLER(NAME, PARAMS, PARAM_FORMAT)\ RC_HANDLER(int, NAME, PARAMS, int rc=0;, PARAM_FORMAT, \ rc = PyInt_AsLong(rv);, rc, \ (xmlparseobject *)userData) VOID_HANDLER(EndElement, (void *userData, const XML_Char *name), ("(N)", string_intern(self, name))) VOID_HANDLER(ProcessingInstruction, (void *userData, const XML_Char *target, const XML_Char *data), ("(NO&)", string_intern(self, target), STRING_CONV_FUNC,data)) VOID_HANDLER(UnparsedEntityDecl, (void *userData, const XML_Char *entityName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName), ("(NNNNN)", string_intern(self, entityName), string_intern(self, base), string_intern(self, systemId), string_intern(self, publicId), string_intern(self, notationName))) #ifndef Py_USING_UNICODE VOID_HANDLER(EntityDecl, (void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName), ("NiNNNNN", string_intern(self, entityName), is_parameter_entity, conv_string_len_to_utf8(value, value_length), string_intern(self, base), string_intern(self, systemId), string_intern(self, publicId), string_intern(self, notationName))) #else VOID_HANDLER(EntityDecl, (void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName), ("NiNNNNN", string_intern(self, entityName), is_parameter_entity, (self->returns_unicode ? conv_string_len_to_unicode(value, value_length) : conv_string_len_to_utf8(value, value_length)), string_intern(self, base), string_intern(self, systemId), string_intern(self, publicId), string_intern(self, notationName))) #endif VOID_HANDLER(XmlDecl, (void *userData, const XML_Char *version, const XML_Char *encoding, int standalone), ("(O&O&i)", STRING_CONV_FUNC,version, STRING_CONV_FUNC,encoding, standalone)) static PyObject * conv_content_model(XML_Content * const model, PyObject *(*conv_string)(const XML_Char *)) { PyObject *result = NULL; PyObject *children = PyTuple_New(model->numchildren); int i; if (children != NULL) { assert(model->numchildren < INT_MAX); for (i = 0; i < (int)model->numchildren; ++i) { PyObject *child = conv_content_model(&model->children[i], conv_string); if (child == NULL) { Py_XDECREF(children); return NULL; } PyTuple_SET_ITEM(children, i, child); } result = Py_BuildValue("(iiO&N)", model->type, model->quant, conv_string,model->name, children); } return result; } static PyObject * conv_content_model_utf8(XML_Content * const model) { return conv_content_model(model, conv_string_to_utf8); } #ifdef Py_USING_UNICODE static PyObject * conv_content_model_unicode(XML_Content * const model) { return conv_content_model(model, conv_string_to_unicode); } VOID_HANDLER(ElementDecl, (void *userData, const XML_Char *name, XML_Content *model), ("NO&", string_intern(self, name), (self->returns_unicode ? conv_content_model_unicode : conv_content_model_utf8),model)) #else VOID_HANDLER(ElementDecl, (void *userData, const XML_Char *name, XML_Content *model), ("NO&", string_intern(self, name), conv_content_model_utf8,model)) #endif VOID_HANDLER(AttlistDecl, (void *userData, const XML_Char *elname, const XML_Char *attname, const XML_Char *att_type, const XML_Char *dflt, int isrequired), ("(NNO&O&i)", string_intern(self, elname), string_intern(self, attname), STRING_CONV_FUNC,att_type, STRING_CONV_FUNC,dflt, isrequired)) #if XML_COMBINED_VERSION >= 19504 VOID_HANDLER(SkippedEntity, (void *userData, const XML_Char *entityName, int is_parameter_entity), ("Ni", string_intern(self, entityName), is_parameter_entity)) #endif VOID_HANDLER(NotationDecl, (void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId), ("(NNNN)", string_intern(self, notationName), string_intern(self, base), string_intern(self, systemId), string_intern(self, publicId))) VOID_HANDLER(StartNamespaceDecl, (void *userData, const XML_Char *prefix, const XML_Char *uri), ("(NN)", string_intern(self, prefix), string_intern(self, uri))) VOID_HANDLER(EndNamespaceDecl, (void *userData, const XML_Char *prefix), ("(N)", string_intern(self, prefix))) VOID_HANDLER(Comment, (void *userData, const XML_Char *data), ("(O&)", STRING_CONV_FUNC,data)) VOID_HANDLER(StartCdataSection, (void *userData), ("()")) VOID_HANDLER(EndCdataSection, (void *userData), ("()")) #ifndef Py_USING_UNICODE VOID_HANDLER(Default, (void *userData, const XML_Char *s, int len), ("(N)", conv_string_len_to_utf8(s,len))) VOID_HANDLER(DefaultHandlerExpand, (void *userData, const XML_Char *s, int len), ("(N)", conv_string_len_to_utf8(s,len))) #else VOID_HANDLER(Default, (void *userData, const XML_Char *s, int len), ("(N)", (self->returns_unicode ? conv_string_len_to_unicode(s,len) : conv_string_len_to_utf8(s,len)))) VOID_HANDLER(DefaultHandlerExpand, (void *userData, const XML_Char *s, int len), ("(N)", (self->returns_unicode ? conv_string_len_to_unicode(s,len) : conv_string_len_to_utf8(s,len)))) #endif INT_HANDLER(NotStandalone, (void *userData), ("()")) RC_HANDLER(int, ExternalEntityRef, (XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId), int rc=0;, ("(O&NNN)", STRING_CONV_FUNC,context, string_intern(self, base), string_intern(self, systemId), string_intern(self, publicId)), rc = PyInt_AsLong(rv);, rc, XML_GetUserData(parser)) /* XXX UnknownEncodingHandler */ VOID_HANDLER(StartDoctypeDecl, (void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset), ("(NNNi)", string_intern(self, doctypeName), string_intern(self, sysid), string_intern(self, pubid), has_internal_subset)) VOID_HANDLER(EndDoctypeDecl, (void *userData), ("()")) /* ---------------------------------------------------------------- */ static PyObject * get_parse_result(xmlparseobject *self, int rv) { if (PyErr_Occurred()) { return NULL; } if (rv == 0) { return set_error(self, XML_GetErrorCode(self->itself)); } if (flush_character_buffer(self) < 0) { return NULL; } return PyInt_FromLong(rv); } PyDoc_STRVAR(xmlparse_Parse__doc__, "Parse(data[, isfinal])\n\ Parse XML data. `isfinal' should be true at end of input."); static PyObject * xmlparse_Parse(xmlparseobject *self, PyObject *args) { char *s; int slen; int isFinal = 0; if (!PyArg_ParseTuple(args, "s#|i:Parse", &s, &slen, &isFinal)) return NULL; return get_parse_result(self, XML_Parse(self->itself, s, slen, isFinal)); } /* File reading copied from cPickle */ #define BUF_SIZE 2048 static int readinst(char *buf, int buf_size, PyObject *meth) { PyObject *arg = NULL; PyObject *bytes = NULL; PyObject *str = NULL; int len = -1; if ((bytes = PyInt_FromLong(buf_size)) == NULL) goto finally; if ((arg = PyTuple_New(1)) == NULL) goto finally; PyTuple_SET_ITEM(arg, 0, bytes); #if PY_VERSION_HEX < 0x02020000 str = PyObject_CallObject(meth, arg); #else str = PyObject_Call(meth, arg, NULL); #endif if (str == NULL) goto finally; /* XXX what to do if it returns a Unicode string? */ if (!PyString_Check(str)) { PyErr_Format(PyExc_TypeError, "read() did not return a string object (type=%.400s)", str->ob_type->tp_name); goto finally; } len = PyString_GET_SIZE(str); if (len > buf_size) { PyErr_Format(PyExc_ValueError, "read() returned too much data: " "%i bytes requested, %i returned", buf_size, len); Py_DECREF(str); goto finally; } memcpy(buf, PyString_AsString(str), len); finally: Py_XDECREF(arg); Py_XDECREF(str); return len; } PyDoc_STRVAR(xmlparse_ParseFile__doc__, "ParseFile(file)\n\ Parse XML data from file-like object."); static PyObject * xmlparse_ParseFile(xmlparseobject *self, PyObject *args) { int rv = 1; PyObject *f; FILE *fp; PyObject *readmethod = NULL; if (!PyArg_ParseTuple(args, "O:ParseFile", &f)) return NULL; if (PyFile_Check(f)) { fp = PyFile_AsFile(f); } else{ fp = NULL; readmethod = PyObject_GetAttrString(f, "read"); if (readmethod == NULL) { PyErr_Clear(); PyErr_SetString(PyExc_TypeError, "argument must have 'read' attribute"); return NULL; } } for (;;) { int bytes_read; void *buf = XML_GetBuffer(self->itself, BUF_SIZE); if (buf == NULL) return PyErr_NoMemory(); if (fp) { bytes_read = fread(buf, sizeof(char), BUF_SIZE, fp); if (bytes_read < 0) { PyErr_SetFromErrno(PyExc_IOError); return NULL; } } else { bytes_read = readinst(buf, BUF_SIZE, readmethod); if (bytes_read < 0) return NULL; } rv = XML_ParseBuffer(self->itself, bytes_read, bytes_read == 0); if (PyErr_Occurred()) return NULL; if (!rv || bytes_read == 0) break; } return get_parse_result(self, rv); } PyDoc_STRVAR(xmlparse_SetBase__doc__, "SetBase(base_url)\n\ Set the base URL for the parser."); static PyObject * xmlparse_SetBase(xmlparseobject *self, PyObject *args) { char *base; if (!PyArg_ParseTuple(args, "s:SetBase", &base)) return NULL; if (!XML_SetBase(self->itself, base)) { return PyErr_NoMemory(); } Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(xmlparse_GetBase__doc__, "GetBase() -> url\n\ Return base URL string for the parser."); static PyObject * xmlparse_GetBase(xmlparseobject *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":GetBase")) return NULL; return Py_BuildValue("z", XML_GetBase(self->itself)); } PyDoc_STRVAR(xmlparse_GetInputContext__doc__, "GetInputContext() -> string\n\ Return the untranslated text of the input that caused the current event.\n\ If the event was generated by a large amount of text (such as a start tag\n\ for an element with many attributes), not all of the text may be available."); static PyObject * xmlparse_GetInputContext(xmlparseobject *self, PyObject *args) { PyObject *result = NULL; if (PyArg_ParseTuple(args, ":GetInputContext")) { if (self->in_callback) { int offset, size; const char *buffer = XML_GetInputContext(self->itself, &offset, &size); if (buffer != NULL) result = PyString_FromStringAndSize(buffer + offset, size); else { result = Py_None; Py_INCREF(result); } } else { result = Py_None; Py_INCREF(result); } } return result; } PyDoc_STRVAR(xmlparse_ExternalEntityParserCreate__doc__, "ExternalEntityParserCreate(context[, encoding])\n\ Create a parser for parsing an external entity based on the\n\ information passed to the ExternalEntityRefHandler."); static PyObject * xmlparse_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args) { char *context; char *encoding = NULL; xmlparseobject *new_parser; int i; if (!PyArg_ParseTuple(args, "z|s:ExternalEntityParserCreate", &context, &encoding)) { return NULL; } #ifndef Py_TPFLAGS_HAVE_GC /* Python versions 2.0 and 2.1 */ new_parser = PyObject_New(xmlparseobject, &Xmlparsetype); #else /* Python versions 2.2 and later */ new_parser = PyObject_GC_New(xmlparseobject, &Xmlparsetype); #endif if (new_parser == NULL) return NULL; new_parser->buffer_size = self->buffer_size; new_parser->buffer_used = 0; if (self->buffer != NULL) { new_parser->buffer = malloc(new_parser->buffer_size); if (new_parser->buffer == NULL) { #ifndef Py_TPFLAGS_HAVE_GC /* Code for versions 2.0 and 2.1 */ PyObject_Del(new_parser); #else /* Code for versions 2.2 and later. */ PyObject_GC_Del(new_parser); #endif return PyErr_NoMemory(); } } else new_parser->buffer = NULL; new_parser->returns_unicode = self->returns_unicode; new_parser->ordered_attributes = self->ordered_attributes; new_parser->specified_attributes = self->specified_attributes; new_parser->in_callback = 0; new_parser->ns_prefixes = self->ns_prefixes; new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context, encoding); new_parser->handlers = 0; new_parser->intern = self->intern; Py_XINCREF(new_parser->intern); #ifdef Py_TPFLAGS_HAVE_GC PyObject_GC_Track(new_parser); #else PyObject_GC_Init(new_parser); #endif if (!new_parser->itself) { Py_DECREF(new_parser); return PyErr_NoMemory(); } XML_SetUserData(new_parser->itself, (void *)new_parser); /* allocate and clear handlers first */ for (i = 0; handler_info[i].name != NULL; i++) /* do nothing */; new_parser->handlers = malloc(sizeof(PyObject *) * i); if (!new_parser->handlers) { Py_DECREF(new_parser); return PyErr_NoMemory(); } clear_handlers(new_parser, 1); /* then copy handlers from self */ for (i = 0; handler_info[i].name != NULL; i++) { PyObject *handler = self->handlers[i]; if (handler != NULL) { Py_INCREF(handler); new_parser->handlers[i] = handler; handler_info[i].setter(new_parser->itself, handler_info[i].handler); } } return (PyObject *)new_parser; } PyDoc_STRVAR(xmlparse_SetParamEntityParsing__doc__, "SetParamEntityParsing(flag) -> success\n\ Controls parsing of parameter entities (including the external DTD\n\ subset). Possible flag values are XML_PARAM_ENTITY_PARSING_NEVER,\n\ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE and\n\ XML_PARAM_ENTITY_PARSING_ALWAYS. Returns true if setting the flag\n\ was successful."); static PyObject* xmlparse_SetParamEntityParsing(xmlparseobject *p, PyObject* args) { int flag; if (!PyArg_ParseTuple(args, "i", &flag)) return NULL; flag = XML_SetParamEntityParsing(p->itself, flag); return PyInt_FromLong(flag); } #if XML_COMBINED_VERSION >= 19505 PyDoc_STRVAR(xmlparse_UseForeignDTD__doc__, "UseForeignDTD([flag])\n\ Allows the application to provide an artificial external subset if one is\n\ not specified as part of the document instance. This readily allows the\n\ use of a 'default' document type controlled by the application, while still\n\ getting the advantage of providing document type information to the parser.\n\ 'flag' defaults to True if not provided."); static PyObject * xmlparse_UseForeignDTD(xmlparseobject *self, PyObject *args) { PyObject *flagobj = NULL; XML_Bool flag = XML_TRUE; enum XML_Error rc; if (!PyArg_ParseTuple(args, "|O:UseForeignDTD", &flagobj)) return NULL; if (flagobj != NULL) flag = PyObject_IsTrue(flagobj) ? XML_TRUE : XML_FALSE; rc = XML_UseForeignDTD(self->itself, flag); if (rc != XML_ERROR_NONE) { return set_error(self, rc); } Py_INCREF(Py_None); return Py_None; } #endif static struct PyMethodDef xmlparse_methods[] = { {"Parse", (PyCFunction)xmlparse_Parse, METH_VARARGS, xmlparse_Parse__doc__}, {"ParseFile", (PyCFunction)xmlparse_ParseFile, METH_VARARGS, xmlparse_ParseFile__doc__}, {"SetBase", (PyCFunction)xmlparse_SetBase, METH_VARARGS, xmlparse_SetBase__doc__}, {"GetBase", (PyCFunction)xmlparse_GetBase, METH_VARARGS, xmlparse_GetBase__doc__}, {"ExternalEntityParserCreate", (PyCFunction)xmlparse_ExternalEntityParserCreate, METH_VARARGS, xmlparse_ExternalEntityParserCreate__doc__}, {"SetParamEntityParsing", (PyCFunction)xmlparse_SetParamEntityParsing, METH_VARARGS, xmlparse_SetParamEntityParsing__doc__}, {"GetInputContext", (PyCFunction)xmlparse_GetInputContext, METH_VARARGS, xmlparse_GetInputContext__doc__}, #if XML_COMBINED_VERSION >= 19505 {"UseForeignDTD", (PyCFunction)xmlparse_UseForeignDTD, METH_VARARGS, xmlparse_UseForeignDTD__doc__}, #endif {NULL, NULL} /* sentinel */ }; /* ---------- */ #ifdef Py_USING_UNICODE /* pyexpat international encoding support. Make it as simple as possible. */ static char template_buffer[257]; PyObject *template_string = NULL; static void init_template_buffer(void) { int i; for (i = 0; i < 256; i++) { template_buffer[i] = i; } template_buffer[256] = 0; } static int PyUnknownEncodingHandler(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info) { PyUnicodeObject *_u_string = NULL; int result = 0; int i; /* Yes, supports only 8bit encodings */ _u_string = (PyUnicodeObject *) PyUnicode_Decode(template_buffer, 256, name, "replace"); if (_u_string == NULL) return result; for (i = 0; i < 256; i++) { /* Stupid to access directly, but fast */ Py_UNICODE c = _u_string->str[i]; if (c == Py_UNICODE_REPLACEMENT_CHARACTER) info->map[i] = -1; else info->map[i] = c; } info->data = NULL; info->convert = NULL; info->release = NULL; result = 1; Py_DECREF(_u_string); return result; } #endif static PyObject * newxmlparseobject(char *encoding, char *namespace_separator, PyObject *intern) { int i; xmlparseobject *self; #ifdef Py_TPFLAGS_HAVE_GC /* Code for versions 2.2 and later */ self = PyObject_GC_New(xmlparseobject, &Xmlparsetype); #else self = PyObject_New(xmlparseobject, &Xmlparsetype); #endif if (self == NULL) return NULL; #ifdef Py_USING_UNICODE self->returns_unicode = 1; #else self->returns_unicode = 0; #endif self->buffer = NULL; self->buffer_size = CHARACTER_DATA_BUFFER_SIZE; self->buffer_used = 0; self->ordered_attributes = 0; self->specified_attributes = 0; self->in_callback = 0; self->ns_prefixes = 0; self->handlers = NULL; if (namespace_separator != NULL) { self->itself = XML_ParserCreateNS(encoding, *namespace_separator); } else { self->itself = XML_ParserCreate(encoding); } self->intern = intern; Py_XINCREF(self->intern); #ifdef Py_TPFLAGS_HAVE_GC PyObject_GC_Track(self); #else PyObject_GC_Init(self); #endif if (self->itself == NULL) { PyErr_SetString(PyExc_RuntimeError, "XML_ParserCreate failed"); Py_DECREF(self); return NULL; } XML_SetUserData(self->itself, (void *)self); #ifdef Py_USING_UNICODE XML_SetUnknownEncodingHandler(self->itself, (XML_UnknownEncodingHandler) PyUnknownEncodingHandler, NULL); #endif for (i = 0; handler_info[i].name != NULL; i++) /* do nothing */; self->handlers = malloc(sizeof(PyObject *) * i); if (!self->handlers) { Py_DECREF(self); return PyErr_NoMemory(); } clear_handlers(self, 1); return (PyObject*)self; } static void xmlparse_dealloc(xmlparseobject *self) { int i; #ifdef Py_TPFLAGS_HAVE_GC PyObject_GC_UnTrack(self); #else PyObject_GC_Fini(self); #endif if (self->itself != NULL) XML_ParserFree(self->itself); self->itself = NULL; if (self->handlers != NULL) { PyObject *temp; for (i = 0; handler_info[i].name != NULL; i++) { temp = self->handlers[i]; self->handlers[i] = NULL; Py_XDECREF(temp); } free(self->handlers); self->handlers = NULL; } if (self->buffer != NULL) { free(self->buffer); self->buffer = NULL; } Py_XDECREF(self->intern); #ifndef Py_TPFLAGS_HAVE_GC /* Code for versions 2.0 and 2.1 */ PyObject_Del(self); #else /* Code for versions 2.2 and later. */ PyObject_GC_Del(self); #endif } static int handlername2int(const char *name) { int i; for (i = 0; handler_info[i].name != NULL; i++) { if (strcmp(name, handler_info[i].name) == 0) { return i; } } return -1; } static PyObject * get_pybool(int istrue) { PyObject *result = istrue ? Py_True : Py_False; Py_INCREF(result); return result; } static PyObject * xmlparse_getattr(xmlparseobject *self, char *name) { int handlernum = handlername2int(name); if (handlernum != -1) { PyObject *result = self->handlers[handlernum]; if (result == NULL) result = Py_None; Py_INCREF(result); return result; } if (name[0] == 'E') { if (strcmp(name, "ErrorCode") == 0) return PyInt_FromLong((long) XML_GetErrorCode(self->itself)); if (strcmp(name, "ErrorLineNumber") == 0) return PyInt_FromLong((long) XML_GetErrorLineNumber(self->itself)); if (strcmp(name, "ErrorColumnNumber") == 0) return PyInt_FromLong((long) XML_GetErrorColumnNumber(self->itself)); if (strcmp(name, "ErrorByteIndex") == 0) return PyInt_FromLong((long) XML_GetErrorByteIndex(self->itself)); } if (name[0] == 'b') { if (strcmp(name, "buffer_size") == 0) return PyInt_FromLong((long) self->buffer_size); if (strcmp(name, "buffer_text") == 0) return get_pybool(self->buffer != NULL); if (strcmp(name, "buffer_used") == 0) return PyInt_FromLong((long) self->buffer_used); } if (strcmp(name, "namespace_prefixes") == 0) return get_pybool(self->ns_prefixes); if (strcmp(name, "ordered_attributes") == 0) return get_pybool(self->ordered_attributes); if (strcmp(name, "returns_unicode") == 0) return get_pybool((long) self->returns_unicode); if (strcmp(name, "specified_attributes") == 0) return get_pybool((long) self->specified_attributes); if (strcmp(name, "intern") == 0) { if (self->intern == NULL) { Py_INCREF(Py_None); return Py_None; } else { Py_INCREF(self->intern); return self->intern; } } #define APPEND(list, str) \ do { \ PyObject *o = PyString_FromString(str); \ if (o != NULL) \ PyList_Append(list, o); \ Py_XDECREF(o); \ } while (0) if (strcmp(name, "__members__") == 0) { int i; PyObject *rc = PyList_New(0); for (i = 0; handler_info[i].name != NULL; i++) { PyObject *o = get_handler_name(&handler_info[i]); if (o != NULL) PyList_Append(rc, o); Py_XDECREF(o); } APPEND(rc, "ErrorCode"); APPEND(rc, "ErrorLineNumber"); APPEND(rc, "ErrorColumnNumber"); APPEND(rc, "ErrorByteIndex"); APPEND(rc, "buffer_size"); APPEND(rc, "buffer_text"); APPEND(rc, "buffer_used"); APPEND(rc, "namespace_prefixes"); APPEND(rc, "ordered_attributes"); APPEND(rc, "returns_unicode"); APPEND(rc, "specified_attributes"); APPEND(rc, "intern"); #undef APPEND return rc; } return Py_FindMethod(xmlparse_methods, (PyObject *)self, name); } static int sethandler(xmlparseobject *self, const char *name, PyObject* v) { int handlernum = handlername2int(name); if (handlernum >= 0) { xmlhandler c_handler = NULL; PyObject *temp = self->handlers[handlernum]; if (v == Py_None) v = NULL; else if (v != NULL) { Py_INCREF(v); c_handler = handler_info[handlernum].handler; } self->handlers[handlernum] = v; Py_XDECREF(temp); handler_info[handlernum].setter(self->itself, c_handler); return 1; } return 0; } static int xmlparse_setattr(xmlparseobject *self, char *name, PyObject *v) { /* Set attribute 'name' to value 'v'. v==NULL means delete */ if (v == NULL) { PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); return -1; } if (strcmp(name, "buffer_text") == 0) { if (PyObject_IsTrue(v)) { if (self->buffer == NULL) { self->buffer = malloc(self->buffer_size); if (self->buffer == NULL) { PyErr_NoMemory(); return -1; } self->buffer_used = 0; } } else if (self->buffer != NULL) { if (flush_character_buffer(self) < 0) return -1; free(self->buffer); self->buffer = NULL; } return 0; } if (strcmp(name, "namespace_prefixes") == 0) { if (PyObject_IsTrue(v)) self->ns_prefixes = 1; else self->ns_prefixes = 0; XML_SetReturnNSTriplet(self->itself, self->ns_prefixes); return 0; } if (strcmp(name, "ordered_attributes") == 0) { if (PyObject_IsTrue(v)) self->ordered_attributes = 1; else self->ordered_attributes = 0; return 0; } if (strcmp(name, "returns_unicode") == 0) { if (PyObject_IsTrue(v)) { #ifndef Py_USING_UNICODE PyErr_SetString(PyExc_ValueError, "Unicode support not available"); return -1; #else self->returns_unicode = 1; #endif } else self->returns_unicode = 0; return 0; } if (strcmp(name, "specified_attributes") == 0) { if (PyObject_IsTrue(v)) self->specified_attributes = 1; else self->specified_attributes = 0; return 0; } if (strcmp(name, "CharacterDataHandler") == 0) { /* If we're changing the character data handler, flush all * cached data with the old handler. Not sure there's a * "right" thing to do, though, but this probably won't * happen. */ if (flush_character_buffer(self) < 0) return -1; } if (sethandler(self, name, v)) { return 0; } PyErr_SetString(PyExc_AttributeError, name); return -1; } #ifdef WITH_CYCLE_GC static int xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) { int i, err; for (i = 0; handler_info[i].name != NULL; i++) { if (!op->handlers[i]) continue; err = visit(op->handlers[i], arg); if (err) return err; } return 0; } static int xmlparse_clear(xmlparseobject *op) { clear_handlers(op, 0); Py_XDECREF(op->intern); op->intern = 0; return 0; } #endif PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser"); static PyTypeObject Xmlparsetype = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pyexpat.xmlparser", /*tp_name*/ sizeof(xmlparseobject) + PyGC_HEAD_SIZE,/*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)xmlparse_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)xmlparse_getattr, /*tp_getattr*/ (setattrfunc)xmlparse_setattr, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ #ifdef Py_TPFLAGS_HAVE_GC Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/ #endif Xmlparsetype__doc__, /* tp_doc - Documentation string */ #ifdef WITH_CYCLE_GC (traverseproc)xmlparse_traverse, /* tp_traverse */ (inquiry)xmlparse_clear /* tp_clear */ #else 0, 0 #endif }; /* End of code for xmlparser objects */ /* -------------------------------------------------------- */ PyDoc_STRVAR(pyexpat_ParserCreate__doc__, "ParserCreate([encoding[, namespace_separator]]) -> parser\n\ Return a new XML parser object."); static PyObject * pyexpat_ParserCreate(PyObject *notused, PyObject *args, PyObject *kw) { char *encoding = NULL; char *namespace_separator = NULL; PyObject *intern = NULL; PyObject *result; int intern_decref = 0; static char *kwlist[] = {"encoding", "namespace_separator", "intern", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kw, "|zzO:ParserCreate", kwlist, &encoding, &namespace_separator, &intern)) return NULL; if (namespace_separator != NULL && strlen(namespace_separator) > 1) { PyErr_SetString(PyExc_ValueError, "namespace_separator must be at most one" " character, omitted, or None"); return NULL; } /* Explicitly passing None means no interning is desired. Not passing anything means that a new dictionary is used. */ if (intern == Py_None) intern = NULL; else if (intern == NULL) { intern = PyDict_New(); if (!intern) return NULL; intern_decref = 1; } else if (!PyDict_Check(intern)) { PyErr_SetString(PyExc_TypeError, "intern must be a dictionary"); return NULL; } result = newxmlparseobject(encoding, namespace_separator, intern); if (intern_decref) { Py_DECREF(intern); } return result; } PyDoc_STRVAR(pyexpat_ErrorString__doc__, "ErrorString(errno) -> string\n\ Returns string error for given number."); static PyObject * pyexpat_ErrorString(PyObject *self, PyObject *args) { long code = 0; if (!PyArg_ParseTuple(args, "l:ErrorString", &code)) return NULL; return Py_BuildValue("z", XML_ErrorString((int)code)); } /* List of methods defined in the module */ static struct PyMethodDef pyexpat_methods[] = { {"ParserCreate", (PyCFunction)pyexpat_ParserCreate, METH_VARARGS|METH_KEYWORDS, pyexpat_ParserCreate__doc__}, {"ErrorString", (PyCFunction)pyexpat_ErrorString, METH_VARARGS, pyexpat_ErrorString__doc__}, {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ }; /* Module docstring */ PyDoc_STRVAR(pyexpat_module_documentation, "Python wrapper for Expat parser."); /* Return a Python string that represents the version number without the * extra cruft added by revision control, even if the right options were * given to the "cvs export" command to make it not include the extra * cruft. */ static PyObject * get_version_string(void) { static char *rcsid = "#Revision: 2.78 $"; char *rev = rcsid; int i = 0; while (!isdigit((int)*rev)) ++rev; while (rev[i] != ' ' && rev[i] != '\0') ++i; return PyString_FromStringAndSize(rev, i); } /* Initialization function for the module */ #ifndef MODULE_NAME #define MODULE_NAME "pyexpat" #endif #ifndef MODULE_INITFUNC #define MODULE_INITFUNC initpyexpat #endif #ifndef PyMODINIT_FUNC # ifdef MS_WINDOWS # define PyMODINIT_FUNC __declspec(dllexport) void # else # define PyMODINIT_FUNC void # endif #endif PyMODINIT_FUNC MODULE_INITFUNC(void); /* avoid compiler warnings */ PyMODINIT_FUNC MODULE_INITFUNC(void) { PyObject *m, *d; PyObject *errmod_name = PyString_FromString(MODULE_NAME ".errors"); PyObject *errors_module; PyObject *modelmod_name; PyObject *model_module; PyObject *sys_modules; if (errmod_name == NULL) return; modelmod_name = PyString_FromString(MODULE_NAME ".model"); if (modelmod_name == NULL) return; Xmlparsetype.ob_type = &PyType_Type; /* Create the module and add the functions */ m = Py_InitModule3(MODULE_NAME, pyexpat_methods, pyexpat_module_documentation); /* Add some symbolic constants to the module */ if (ErrorObject == NULL) { ErrorObject = PyErr_NewException("xml.parsers.expat.ExpatError", NULL, NULL); if (ErrorObject == NULL) return; } Py_INCREF(ErrorObject); PyModule_AddObject(m, "error", ErrorObject); Py_INCREF(ErrorObject); PyModule_AddObject(m, "ExpatError", ErrorObject); Py_INCREF(&Xmlparsetype); PyModule_AddObject(m, "XMLParserType", (PyObject *) &Xmlparsetype); PyModule_AddObject(m, "__version__", get_version_string()); PyModule_AddStringConstant(m, "EXPAT_VERSION", (char *) XML_ExpatVersion()); { XML_Expat_Version info = XML_ExpatVersionInfo(); PyModule_AddObject(m, "version_info", Py_BuildValue("(iii)", info.major, info.minor, info.micro)); } #ifdef Py_USING_UNICODE init_template_buffer(); #endif /* XXX When Expat supports some way of figuring out how it was compiled, this should check and set native_encoding appropriately. */ PyModule_AddStringConstant(m, "native_encoding", "UTF-8"); /* THIS IS FOR USE IN PyXML ONLY. */ PyModule_AddStringConstant(m, "pyxml_expat_version", "$Revision: 1.74 $"); sys_modules = PySys_GetObject("modules"); d = PyModule_GetDict(m); errors_module = PyDict_GetItem(d, errmod_name); if (errors_module == NULL) { errors_module = PyModule_New(MODULE_NAME ".errors"); if (errors_module != NULL) { PyDict_SetItem(sys_modules, errmod_name, errors_module); /* gives away the reference to errors_module */ PyModule_AddObject(m, "errors", errors_module); } } Py_DECREF(errmod_name); model_module = PyDict_GetItem(d, modelmod_name); if (model_module == NULL) { model_module = PyModule_New(MODULE_NAME ".model"); if (model_module != NULL) { PyDict_SetItem(sys_modules, modelmod_name, model_module); /* gives away the reference to model_module */ PyModule_AddObject(m, "model", model_module); } } Py_DECREF(modelmod_name); if (errors_module == NULL || model_module == NULL) /* Don't core dump later! */ return; #if XML_COMBINED_VERSION > 19505 { const XML_Feature *features = XML_GetFeatureList(); PyObject *list = PyList_New(0); if (list == NULL) /* just ignore it */ PyErr_Clear(); else { int i = 0; for (; features[i].feature != XML_FEATURE_END; ++i) { int ok; PyObject *item = Py_BuildValue("si", features[i].name, features[i].value); if (item == NULL) { Py_DECREF(list); list = NULL; break; } ok = PyList_Append(list, item); Py_DECREF(item); if (ok < 0) { PyErr_Clear(); break; } } if (list != NULL) PyModule_AddObject(m, "features", list); } } #endif #define MYCONST(name) \ PyModule_AddStringConstant(errors_module, #name, \ (char*)XML_ErrorString(name)) MYCONST(XML_ERROR_NO_MEMORY); MYCONST(XML_ERROR_SYNTAX); MYCONST(XML_ERROR_NO_ELEMENTS); MYCONST(XML_ERROR_INVALID_TOKEN); MYCONST(XML_ERROR_UNCLOSED_TOKEN); MYCONST(XML_ERROR_PARTIAL_CHAR); MYCONST(XML_ERROR_TAG_MISMATCH); MYCONST(XML_ERROR_DUPLICATE_ATTRIBUTE); MYCONST(XML_ERROR_JUNK_AFTER_DOC_ELEMENT); MYCONST(XML_ERROR_PARAM_ENTITY_REF); MYCONST(XML_ERROR_UNDEFINED_ENTITY); MYCONST(XML_ERROR_RECURSIVE_ENTITY_REF); MYCONST(XML_ERROR_ASYNC_ENTITY); MYCONST(XML_ERROR_BAD_CHAR_REF); MYCONST(XML_ERROR_BINARY_ENTITY_REF); MYCONST(XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF); MYCONST(XML_ERROR_MISPLACED_XML_PI); MYCONST(XML_ERROR_UNKNOWN_ENCODING); MYCONST(XML_ERROR_INCORRECT_ENCODING); MYCONST(XML_ERROR_UNCLOSED_CDATA_SECTION); MYCONST(XML_ERROR_EXTERNAL_ENTITY_HANDLING); MYCONST(XML_ERROR_NOT_STANDALONE); PyModule_AddStringConstant(errors_module, "__doc__", "Constants used to describe error conditions."); #undef MYCONST #define MYCONST(c) PyModule_AddIntConstant(m, #c, c) MYCONST(XML_PARAM_ENTITY_PARSING_NEVER); MYCONST(XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS); #undef MYCONST #define MYCONST(c) PyModule_AddIntConstant(model_module, #c, c) PyModule_AddStringConstant(model_module, "__doc__", "Constants used to interpret content model information."); MYCONST(XML_CTYPE_EMPTY); MYCONST(XML_CTYPE_ANY); MYCONST(XML_CTYPE_MIXED); MYCONST(XML_CTYPE_NAME); MYCONST(XML_CTYPE_CHOICE); MYCONST(XML_CTYPE_SEQ); MYCONST(XML_CQUANT_NONE); MYCONST(XML_CQUANT_OPT); MYCONST(XML_CQUANT_REP); MYCONST(XML_CQUANT_PLUS); #undef MYCONST } static void clear_handlers(xmlparseobject *self, int initial) { int i = 0; PyObject *temp; for (; handler_info[i].name != NULL; i++) { if (initial) self->handlers[i] = NULL; else { temp = self->handlers[i]; self->handlers[i] = NULL; Py_XDECREF(temp); handler_info[i].setter(self->itself, NULL); } } } static struct HandlerInfo handler_info[] = { {"StartElementHandler", (xmlhandlersetter)XML_SetStartElementHandler, (xmlhandler)my_StartElementHandler}, {"EndElementHandler", (xmlhandlersetter)XML_SetEndElementHandler, (xmlhandler)my_EndElementHandler}, {"ProcessingInstructionHandler", (xmlhandlersetter)XML_SetProcessingInstructionHandler, (xmlhandler)my_ProcessingInstructionHandler}, {"CharacterDataHandler", (xmlhandlersetter)XML_SetCharacterDataHandler, (xmlhandler)my_CharacterDataHandler}, {"UnparsedEntityDeclHandler", (xmlhandlersetter)XML_SetUnparsedEntityDeclHandler, (xmlhandler)my_UnparsedEntityDeclHandler}, {"NotationDeclHandler", (xmlhandlersetter)XML_SetNotationDeclHandler, (xmlhandler)my_NotationDeclHandler}, {"StartNamespaceDeclHandler", (xmlhandlersetter)XML_SetStartNamespaceDeclHandler, (xmlhandler)my_StartNamespaceDeclHandler}, {"EndNamespaceDeclHandler", (xmlhandlersetter)XML_SetEndNamespaceDeclHandler, (xmlhandler)my_EndNamespaceDeclHandler}, {"CommentHandler", (xmlhandlersetter)XML_SetCommentHandler, (xmlhandler)my_CommentHandler}, {"StartCdataSectionHandler", (xmlhandlersetter)XML_SetStartCdataSectionHandler, (xmlhandler)my_StartCdataSectionHandler}, {"EndCdataSectionHandler", (xmlhandlersetter)XML_SetEndCdataSectionHandler, (xmlhandler)my_EndCdataSectionHandler}, {"DefaultHandler", (xmlhandlersetter)XML_SetDefaultHandler, (xmlhandler)my_DefaultHandler}, {"DefaultHandlerExpand", (xmlhandlersetter)XML_SetDefaultHandlerExpand, (xmlhandler)my_DefaultHandlerExpandHandler}, {"NotStandaloneHandler", (xmlhandlersetter)XML_SetNotStandaloneHandler, (xmlhandler)my_NotStandaloneHandler}, {"ExternalEntityRefHandler", (xmlhandlersetter)XML_SetExternalEntityRefHandler, (xmlhandler)my_ExternalEntityRefHandler}, {"StartDoctypeDeclHandler", (xmlhandlersetter)XML_SetStartDoctypeDeclHandler, (xmlhandler)my_StartDoctypeDeclHandler}, {"EndDoctypeDeclHandler", (xmlhandlersetter)XML_SetEndDoctypeDeclHandler, (xmlhandler)my_EndDoctypeDeclHandler}, {"EntityDeclHandler", (xmlhandlersetter)XML_SetEntityDeclHandler, (xmlhandler)my_EntityDeclHandler}, {"XmlDeclHandler", (xmlhandlersetter)XML_SetXmlDeclHandler, (xmlhandler)my_XmlDeclHandler}, {"ElementDeclHandler", (xmlhandlersetter)XML_SetElementDeclHandler, (xmlhandler)my_ElementDeclHandler}, {"AttlistDeclHandler", (xmlhandlersetter)XML_SetAttlistDeclHandler, (xmlhandler)my_AttlistDeclHandler}, #if XML_COMBINED_VERSION >= 19504 {"SkippedEntityHandler", (xmlhandlersetter)XML_SetSkippedEntityHandler, (xmlhandler)my_SkippedEntityHandler}, #endif {NULL, NULL, NULL} /* sentinel */ }; PyXML-0.8.2/extensions/sgmlop.c0100644000076400001440000012560307521676757015611 0ustar martinusers/* * SGMLOP * $Id: sgmlop.c,v 1.14 2025/07/31 06:04:31 loewis Exp $ * * The sgmlop accelerator module * * This module provides a FastSGMLParser type, which is designed to * speed up the standard sgmllib and xmllib modules. The parser can * be configured to support either basic SGML (enough of it to process * HTML documents, at least) or XML. This module also provides an * Element type, useful for fast but simple DOM implementations. * * History: * 2025-04-04 fl Created (for coreXML) * 2025-04-05 fl Added close method * 2025-04-06 fl Added parse method, revised callback interface * 2025-04-14 fl Fixed parsing of PI tags * 2025-05-14 fl Cleaned up for first public release * 2025-05-19 fl Fixed xmllib compatibility: handle_proc, handle_special * 2025-05-22 fl Added attribute parser * 2025-06-20 fl Added Element data type, various bug fixes. * 2025-05-28 fl Fixed data truncation error (@SGMLOP1) * 2025-05-28 fl Added temporary workaround for unicode problem (@SGMLOP2) * 2025-05-28 fl Removed optional close argument (@SGMLOP3) * 2025-05-28 fl Raise exception on recursive feed (@SGMLOP4) * 2025-07-05 fl Fixed attribute handling in empty tags (@SGMLOP6) * 2024-12-28 wd Add XMLUnicodeParser * 2024-12-31 mvl Properly process large character references * * Copyright (c) 1998-2000 by Secret Labs AB * Copyright (c) 1998-2000 by Fredrik Lundh * * fredrik@pythonware.com * http://www.pythonware.com * * By obtaining, using, and/or copying this software and/or its * associated documentation, you agree that you have read, understood, * and will comply with the following terms and conditions: * * Permission to use, copy, modify, and distribute this software and its * associated documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appears in all * copies, and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of Secret Labs * AB or the author not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. * * SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "Python.h" #include #if (PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION > 5) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2) /* In Python 1.6, 2.0 and 2.1, disabling Unicode was not possible. */ #define Py_USING_UNICODE #define PyUnicode_GetMax() (0xffff) #endif #ifdef SGMLOP_UNICODE_SUPPORT /* wide character set (experimental) */ /* FIXME: under Python 1.6, the current version converts Unicode strings to UTF-8, and parses the result as if it was an ASCII string. */ #define CHAR_T Py_UNICODE #define ISALNUM Py_UNICODE_ISALNUM #define ISSPACE Py_UNICODE_ISSPACE #define TOLOWER Py_UNICODE_TOLOWER #else /* 8-bit character set */ #define CHAR_T char #define ISALNUM isalnum #define ISSPACE isspace #define TOLOWER tolower #endif #if 0 static int memory = 0; #define ALLOC(size, comment)\ do { memory += size; printf("%8d - %s\n", memory, comment); } while (0) #define RELEASE(size, comment)\ do { memory -= size; printf("%8d - %s\n", memory, comment); } while (0) #else #define ALLOC(size, comment) #define RELEASE(size, comment) #endif /* ==================================================================== */ /* parser data type */ /* state flags */ #define MAYBE 1 #define SURE 2 /* parser type definition */ typedef struct { PyObject_HEAD /* mode flags */ int xml; /* 0=sgml/html 1=xml */ int unicode; /* 0=8bit strings 1=unicode objects */ char *encoding; /* state attributes */ int feed; int shorttag; /* 0=normal 2=parsing shorttag */ int doctype; /* 0=normal 1=dtd pending 2=parsing dtd */ /* buffer (holds incomplete tags) */ char* buffer; int bufferlen; /* current amount of data */ int buffertotal; /* actually allocated */ /* callbacks */ PyObject* finish_starttag; PyObject* finish_endtag; PyObject* handle_proc; PyObject* handle_special; PyObject* handle_charref; PyObject* handle_entityref; PyObject* handle_data; PyObject* handle_cdata; PyObject* handle_comment; } FastSGMLParserObject; staticforward PyTypeObject FastSGMLParser_Type; /* forward declarations */ static int fastfeed(FastSGMLParserObject* self); static PyObject* attrparse(FastSGMLParserObject* self, const CHAR_T* p, int len); static int fetchEncoding(FastSGMLParserObject* self, const CHAR_T* data, int len); static PyObject* stringFromData(FastSGMLParserObject* self, const CHAR_T* data, int len); static int callWithString(FastSGMLParserObject* self, PyObject* callback, const CHAR_T* data, int len); static int callWith2Strings(FastSGMLParserObject* self, PyObject* callback, const CHAR_T* data1, int len1, const CHAR_T* data2, int len2); static int callWithStringAndObj(FastSGMLParserObject* self, PyObject* callback, const CHAR_T* data, int len, PyObject* obj); #define callHandleData(self, data, len) callWithString((self), (self)->handle_data, (data), (len)) #define callHandleCData(self, data, len) callWithString((self), (self)->handle_cdata, (data), (len)) #define callHandleComment(self, data, len) callWithString((self), (self)->handle_comment, (data), (len)) #define callHandleEntityRef(self, data, len) callWithString((self), (self)->handle_entityref, (data), (len)) #define callHandleCharRef(self, data, len) callWithString((self), (self)->handle_charref, (data), (len)) #define callHandleSpecial(self, data, len) callWithString((self), (self)->handle_special, (data), (len)) #define callHandleProc(self, data1, len1, data2, len2) callWith2Strings((self), (self)->handle_proc, (data1), (len1), (data2), (len2)) #define callFinishStartTag(self, data, len, obj) callWithStringAndObj((self), (self)->finish_starttag, (data), (len), (obj)) #define callFinishEndTag(self, data, len) callWithString((self), (self)->finish_endtag, (data), (len)) /* -------------------------------------------------------------------- */ /* create parser */ static PyObject* _sgmlop_new(int xml, int unicode) { FastSGMLParserObject* self; self = PyObject_NEW(FastSGMLParserObject, &FastSGMLParser_Type); if (self == NULL) return NULL; self->xml = xml; self->unicode = unicode; self->encoding = NULL; self->feed = 0; self->shorttag = 0; self->doctype = 0; self->buffer = NULL; self->bufferlen = 0; self->buffertotal = 0; self->finish_starttag = NULL; self->finish_endtag = NULL; self->handle_proc = NULL; self->handle_special = NULL; self->handle_charref = NULL; self->handle_entityref = NULL; self->handle_data = NULL; self->handle_cdata = NULL; self->handle_comment = NULL; return (PyObject*) self; } static PyObject* _sgmlop_sgmlparser(PyObject* self, PyObject* args) { if (!PyArg_NoArgs(args)) return NULL; return _sgmlop_new(0, 0); } static PyObject* _sgmlop_xmlparser(PyObject* self, PyObject* args) { if (!PyArg_NoArgs(args)) return NULL; return _sgmlop_new(1, 0); } static PyObject* _sgmlop_xmlunicodeparser(PyObject* self, PyObject* args) { if (!PyArg_NoArgs(args)) return NULL; return _sgmlop_new(1, 1); } static void _sgmlop_dealloc(FastSGMLParserObject* self) { if (self->buffer) free(self->buffer); if (self->encoding) free(self->encoding); Py_XDECREF(self->finish_starttag); Py_XDECREF(self->finish_endtag); Py_XDECREF(self->handle_proc); Py_XDECREF(self->handle_special); Py_XDECREF(self->handle_charref); Py_XDECREF(self->handle_entityref); Py_XDECREF(self->handle_data); Py_XDECREF(self->handle_cdata); Py_XDECREF(self->handle_comment); PyMem_DEL(self); } #define GETCB(member, name)\ Py_XDECREF(self->member);\ self->member = PyObject_GetAttrString(item, name); static PyObject* _sgmlop_register(FastSGMLParserObject* self, PyObject* args) { /* register a callback object */ PyObject* item; if (!PyArg_ParseTuple(args, "O", &item)) return NULL; GETCB(finish_starttag, "finish_starttag"); GETCB(finish_endtag, "finish_endtag"); GETCB(handle_proc, "handle_proc"); GETCB(handle_special, "handle_special"); GETCB(handle_charref, "handle_charref"); GETCB(handle_entityref, "handle_entityref"); GETCB(handle_data, "handle_data"); GETCB(handle_cdata, "handle_cdata"); GETCB(handle_comment, "handle_comment"); PyErr_Clear(); Py_INCREF(Py_None); return Py_None; } /* -------------------------------------------------------------------- */ /* feed data to parser. the parser processes as much of the data as possible, and keeps the rest in a local buffer. */ static PyObject* feed(FastSGMLParserObject* self, char* string, int stringlen, int last) { /* common subroutine for SGMLParser.feed and SGMLParser.close */ int length; if (self->feed) { /* dealing with recursive feeds isn's exactly trivial, so let's just bail out before the parser messes things up */ PyErr_SetString(PyExc_AssertionError, "recursive feed"); return NULL; } /* append new text block to local buffer */ if (!self->buffer) { length = stringlen; self->buffer = malloc(length); self->buffertotal = stringlen; } else { length = self->bufferlen + stringlen; if (length > self->buffertotal) { self->buffer = realloc(self->buffer, length); self->buffertotal = length; } } if (!self->buffer) { PyErr_NoMemory(); return NULL; } memcpy(self->buffer + self->bufferlen, string, stringlen); self->bufferlen = length; self->feed = 1; length = fastfeed(self); self->feed = 0; if (length < 0) return NULL; if (length > self->bufferlen) { /* ran beyond the end of the buffer (internal error)*/ PyErr_SetString(PyExc_AssertionError, "buffer overrun"); return NULL; } if (length > 0 && length < self->bufferlen) /* adjust buffer */ memmove(self->buffer, self->buffer + length, self->bufferlen - length); self->bufferlen = self->bufferlen - length; /* FIXME: if data remains in the buffer even through this is the last call, do an extra handle_data to get rid of it */ /* FIXME: if this is the last call, shut the parser down and release the internal buffers */ return Py_BuildValue("i", self->bufferlen); } static PyObject* _sgmlop_feed(FastSGMLParserObject* self, PyObject* args) { /* feed a chunk of data to the parser */ char* string; int stringlen; if (!PyArg_ParseTuple(args, "t#", &string, &stringlen)) return NULL; return feed(self, string, stringlen, 0); } static PyObject* _sgmlop_close(FastSGMLParserObject* self, PyObject* args) { /* flush parser buffers */ if (!PyArg_NoArgs(args)) return NULL; return feed(self, "", 0, 1); } static PyObject* _sgmlop_parse(FastSGMLParserObject* self, PyObject* args) { /* feed a single chunk of data to the parser */ char* string; int stringlen; if (!PyArg_ParseTuple(args, "t#", &string, &stringlen)) return NULL; return feed(self, string, stringlen, 1); } /* -------------------------------------------------------------------- */ /* type interface */ static PyMethodDef _sgmlop_methods[] = { /* register callbacks */ {"register", (PyCFunction) _sgmlop_register, 1}, /* incremental parsing */ {"feed", (PyCFunction) _sgmlop_feed, 1}, {"close", (PyCFunction) _sgmlop_close, 0}, /* one-shot parsing */ {"parse", (PyCFunction) _sgmlop_parse, 1}, {NULL, NULL} }; static PyObject* _sgmlop_getattr(FastSGMLParserObject* self, char* name) { return Py_FindMethod(_sgmlop_methods, (PyObject*) self, name); } statichere PyTypeObject FastSGMLParser_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "FastSGMLParser", /* tp_name */ sizeof(FastSGMLParserObject), /* tp_size */ 0, /* tp_itemsize */ /* methods */ (destructor)_sgmlop_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc)_sgmlop_getattr, /* tp_getattr */ 0 /* tp_setattr */ }; /* ==================================================================== */ /* element data type */ typedef struct { PyObject_HEAD /* an element has the following attributes: */ PyObject* parent; /* back link (None for the root node) */ PyObject* tag; /* element tag (a string) */ PyObject* attrib; /* attributes (a dictionary object) */ PyObject* text; /* text before first child */ PyObject* suffix; /* text after this element, in parent */ /* in addition, it can hold any number of child nodes: */ int child_count; /* actual items */ int child_total; /* allocated items */ PyObject* *children; /* Note: the suffix attribute holds textual data that belongs to the parent. on other words, each element represents the following XML snippet: " text children suffix" */ } ElementObject; staticforward PyTypeObject Element_Type; /* -------------------------------------------------------------------- */ /* element constructor and destructor */ static PyObject* element_new(PyObject* _self, PyObject* args) { ElementObject* self; PyObject* parent; PyObject* tag; PyObject* attrib = Py_None; PyObject* text = Py_None; PyObject* suffix = Py_None; if (!PyArg_ParseTuple(args, "OO|OOO", &parent, &tag, &attrib, &text, &suffix)) return NULL; if (parent != Py_None && parent->ob_type != &Element_Type) { PyErr_SetString(PyExc_TypeError, "parent must be Element or None"); return NULL; } self = PyObject_NEW(ElementObject, &Element_Type); if (self == NULL) return NULL; Py_INCREF(parent); self->parent = parent; Py_INCREF(tag); self->tag = tag; Py_INCREF(attrib); self->attrib = attrib; Py_INCREF(text); self->text = text; Py_INCREF(suffix); self->suffix = suffix; self->child_count = 0; self->child_total = 0; self->children = NULL; ALLOC(sizeof(ElementObject), "create element"); return (PyObject*) self; } static void element_dealloc(ElementObject* self) { int i; /* FIXME: the parent attribute means that a tree will contain circular references. this will be fixed ("how?" is the big question...) */ if (self->children) { for (i = 0; i < self->child_count; i++) Py_DECREF(self->children[i]); free(self->children); } /* break the backlink */ Py_DECREF(self->parent); /* discard attributes */ Py_DECREF(self->tag); Py_XDECREF(self->attrib); Py_XDECREF(self->text); Py_XDECREF(self->suffix); RELEASE(sizeof(ElementObject), "destroy element"); PyMem_DEL(self); } /* -------------------------------------------------------------------- */ /* methods (in alphabetical order) */ static PyObject* element_append(ElementObject* self, PyObject* args) { int total; PyObject* element; if (!PyArg_ParseTuple(args, "O!", &Element_Type, &element)) return NULL; if (!self->children) { total = 10; self->children = malloc(total * sizeof(PyObject*)); self->child_total = total; } else if (self->child_count >= self->child_total) { total = self->child_total + 10; self->children = realloc(self->children, total * sizeof(PyObject*)); self->child_total = total; } if (!self->children) { PyErr_NoMemory(); return NULL; } Py_INCREF(element); self->children[self->child_count++] = element; Py_INCREF(Py_None); return Py_None; } static PyObject* element_destroy(ElementObject* self, PyObject* args) { int i; PyObject* res; if (!PyArg_NoArgs(args)) return NULL; /* break the backlink */ if (self->parent != Py_None) { Py_DECREF(self->parent); self->parent = Py_None; Py_INCREF(self->parent); } /* destroy element children */ if (self->children) { for (i = 0; i < self->child_count; i++) { res = element_destroy((ElementObject*) self->children[i], args); Py_DECREF(res); Py_DECREF(self->children[i]); } self->child_count = 0; } /* leave the rest to the garbage collector... */ Py_INCREF(Py_None); return Py_None; } static PyObject * element_get(ElementObject* self, PyObject* args) { PyObject* value; PyObject* key; PyObject* default_value = Py_None; if (!PyArg_ParseTuple(args, "O|O", &key, &default_value)) return NULL; value = PyDict_GetItem(self->attrib, key); if (!value) { value = default_value; PyErr_Clear(); } Py_INCREF(value); return value; } static PyObject* element_getitem(ElementObject* self, int index) { if (index < 0 || index >= self->child_count) { PyErr_SetString(PyExc_IndexError, "child index out of range"); return NULL; } Py_INCREF(self->children[index]); return self->children[index]; } static int element_length(ElementObject* self) { return self->child_count; } static PyObject* element_repr(ElementObject* self) { char buf[300]; if (PyString_Check(self->tag)) sprintf( buf, "", PyString_AsString(self->tag), (long) self ); else sprintf( buf, "", (long) self ); return PyString_FromString(buf); } /* -------------------------------------------------------------------- */ /* type descriptor */ static PyMethodDef element_methods[] = { {"get", (PyCFunction) element_get, 1}, {"append", (PyCFunction) element_append, 1}, {"destroy", (PyCFunction) element_destroy, 0}, {NULL, NULL} }; static PyObject* element_getattr(ElementObject* self, char* name) { PyObject* res; res = Py_FindMethod(element_methods, (PyObject*) self, name); if (res) return res; PyErr_Clear(); if (strcmp(name, "tag") == 0) res = self->tag; else if (strcmp(name, "text") == 0) res = self->text; else if (strcmp(name, "suffix") == 0) res = self->suffix; else if (strcmp(name, "attrib") == 0) res = self->attrib; else if (strcmp(name, "parent") == 0) res = self->parent; else { PyErr_SetString(PyExc_AttributeError, name); return NULL; } Py_INCREF(res); return res; } static int element_setattr(ElementObject *self, const char* name, PyObject* value) { if (value == NULL) { PyErr_SetString(PyExc_AttributeError, "can't delete element attributes"); return -1; } if (strcmp(name, "text") == 0) { Py_DECREF(self->text); self->text = value; Py_INCREF(self->text); } else if (strcmp(name, "suffix") == 0) { Py_DECREF(self->suffix); self->suffix = value; Py_INCREF(self->suffix); } else if (strcmp(name, "attrib") == 0) { Py_DECREF(self->attrib); self->attrib = value; Py_INCREF(self->attrib); } else { PyErr_SetString(PyExc_AttributeError, name); return -1; } return 0; } static PySequenceMethods element_as_sequence = { (inquiry) element_length, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ (intargfunc) element_getitem, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ }; statichere PyTypeObject Element_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "Element", /* tp_name */ sizeof(ElementObject), /*tp_size*/ 0, /* tp_itemsize */ /* methods */ (destructor)element_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc)element_getattr, /* tp_getattr */ (setattrfunc)element_setattr, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)element_repr, /* tp_repr */ 0, /* tp_as_number */ &element_as_sequence, /* tp_as_sequence */ 0 /* tp_as_mapping */ }; /* ==================================================================== */ /* tree builder (not yet implemented) */ typedef struct { PyObject_HEAD PyObject* root; /* root node (first created node) */ PyObject* this; /* current node */ PyObject* last; /* most recently created node */ PyObject* data; /* data collector */ } TreeBuilderObject; staticforward PyTypeObject TreeBuilder_Type; /* -------------------------------------------------------------------- */ /* constructor and destructor */ static PyObject* treebuilder_new(PyObject* _self, PyObject* args) { TreeBuilderObject* self; /* no arguments */ if (!PyArg_NoArgs(args)) return NULL; self = PyObject_NEW(TreeBuilderObject, &TreeBuilder_Type); if (self == NULL) return NULL; Py_INCREF(Py_None); self->root = Py_None; self->this = NULL; self->last = NULL; self->data = NULL; return (PyObject*) self; } static void treebuilder_dealloc(TreeBuilderObject* self) { Py_XDECREF(self->data); Py_XDECREF(self->last); Py_XDECREF(self->this); Py_DECREF(self->root); PyMem_DEL(self); } /* -------------------------------------------------------------------- */ /* methods (in alphabetical order) */ static PyObject* treebuilder_start(TreeBuilderObject* self, PyObject* args) { PyObject* tag; PyObject* attrib = Py_None; if (!PyArg_ParseTuple(args, "O|O", &tag, &attrib)) return NULL; /* create a new node */ Py_INCREF(Py_None); return Py_None; } static PyObject* treebuilder_end(TreeBuilderObject* self, PyObject* args) { PyObject* tag; if (!PyArg_ParseTuple(args, "O", &tag)) return NULL; /* end current node */ Py_INCREF(Py_None); return Py_None; } static PyObject * treebuilder_data(TreeBuilderObject* self, PyObject* args) { PyObject* data; if (!PyArg_ParseTuple(args, "O", &data)) return NULL; /* add data to collector */ Py_INCREF(Py_None); return Py_None; } /* -------------------------------------------------------------------- */ /* type descriptor */ static PyMethodDef treebuilder_methods[] = { {"data", (PyCFunction) treebuilder_data, 1}, {"start", (PyCFunction) treebuilder_start, 1}, {"end", (PyCFunction) treebuilder_end, 1}, {NULL, NULL} }; static PyObject* treebuilder_getattr(ElementObject* self, char* name) { return Py_FindMethod(treebuilder_methods, (PyObject*) self, name); } statichere PyTypeObject TreeBuilder_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "TreeBuilder", /* tp_name */ sizeof(TreeBuilderObject), /*tp_size*/ 0, /* tp_itemsize */ /* methods */ (destructor)treebuilder_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc)treebuilder_getattr, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0 /* tp_as_mapping */ }; /* ==================================================================== */ /* python module interface */ static PyMethodDef _functions[] = { {"SGMLParser", _sgmlop_sgmlparser, 0}, {"XMLParser", _sgmlop_xmlparser, 0}, {"XMLUnicodeParser", _sgmlop_xmlunicodeparser, 0}, {"Element", element_new, 1}, {"TreeBuilder", treebuilder_new, 0}, {NULL, NULL} }; DL_EXPORT(void) initsgmlop(void) { /* Patch object type */ FastSGMLParser_Type.ob_type = Element_Type.ob_type = TreeBuilder_Type.ob_type = &PyType_Type; Py_InitModule("sgmlop", _functions); } /* -------------------------------------------------------------------- */ /* the parser does it all in a single loop, keeping the necessary state in a few flag variables and the data buffer. if you have a good optimizer, this can be incredibly fast. */ #define TAG 0x100 #define TAG_START 0x101 #define TAG_END 0x102 #define TAG_EMPTY 0x103 #define DIRECTIVE 0x104 #define DOCTYPE 0x105 #define PI 0x106 #define DTD_START 0x107 #define DTD_END 0x108 #define DTD_ENTITY 0x109 #define CDATA 0x200 #define ENTITYREF 0x400 #define CHARREF 0x401 #define COMMENT 0x800 static int fastfeed(FastSGMLParserObject* self) { CHAR_T *end; /* tail */ CHAR_T *p, *q, *s; /* scanning pointers */ CHAR_T *b, *t, *e; /* token start/end */ int token; s = q = p = (CHAR_T*) self->buffer; end = (CHAR_T*) (self->buffer + self->bufferlen); while (p < end) { q = p; /* start of token */ if (*p == '<') { int has_attr; /* */ token = TAG_START; if (++p >= end) goto eol; if (*p == '!') { /* = end) goto eol; token = DIRECTIVE; b = t = p; if (*p == '-') { /* */ token = COMMENT; b = p + 2; for (;;) { if (p+3 >= end) goto eol; if (p[1] != '-') p += 2; /* boyer moore, sort of ;-) */ else if (p[0] != '-' || p[2] != '>') p++; else break; } e = p; p += 3; goto eot; } else if (self->xml) { /* FIXME: recognize ? */ /* FIXME: recognize ? */ /* FIXME: recognize ? */ /* FIXME: recognize ? */ if (*p == 'D' ) { /* FIXME: make sure this really is a !DOCTYPE tag */ /* or */ token = DOCTYPE; self->doctype = MAYBE; } else if (*p == '[') { /* FIXME: make sure this really is a ![CDATA[ tag */ /* FIXME: recognize */ token = CDATA; b = t = p + 7; for (;;) { if (p+3 >= end) goto eol; if (p[1] != ']') p += 2; else if (p[0] != ']' || p[2] != '>') p++; else break; } e = p; p += 3; goto eot; } } } else if (*p == '?') { token = PI; if (++p >= end) goto eol; } else if (*p == '/') { /* */ token = TAG_END; if (++p >= end) goto eol; } /* process tag name */ b = p; if (!self->xml) while (ISALNUM(*p) || *p == '-' || *p == '.' || *p == ':' || *p == '?') { *p = (CHAR_T) TOLOWER(*p); if (++p >= end) goto eol; } else while (ISALNUM(*p) || *p == '-' || *p == '.' || *p == '_' || *p == ':' || *p == '?') { if (++p >= end) goto eol; } t = p; has_attr = 0; if (*p == '/' && !self->xml) { /* */ token = TAG_START; e = p; if (++p >= end) goto eol; if (*p == '>') { /* */ token = TAG_EMPTY; if (++p >= end) goto eol; } else /* shorttag = SURE; /* we'll generate an end tag when we stumble upon the end slash */ } else { /* skip attributes */ int quote = 0; int last = 0; if (token==PI && self->xml) { int found = 0; while ((*p!='>') || (!found)) { found = (*p=='?'); if (++p >= end) goto eol; } last = '?'; } else { while (*p != '>' || quote) { if (!ISSPACE(*p)) { has_attr = 1; /* FIXME: note: end tags cannot have attributes! */ } if (quote) { if (*p == quote) quote = 0; } else { if (*p == '"' || *p == '\'') quote = *p; } if (*p == '[' && !quote && self->doctype) { self->doctype = SURE; token = DTD_START; e = p++; goto eot; } last = *p; if (++p >= end) goto eol; } } e = p++; if (last == '/') { /* */ e--; token = TAG_EMPTY; } else if (token == PI && last == '?') e--; if (self->doctype == MAYBE) self->doctype = 0; /* there was no dtd */ if (has_attr) ; /* FIXME: process attributes */ } } else if (*p == '/' && self->shorttag) { /* end of shorttag. this generates an empty end tag */ token = TAG_END; self->shorttag = 0; b = t = e = p; if (++p >= end) goto eol; } else if (*p == ']' && self->doctype) { /* end of dtd. this generates an empty end tag */ token = DTD_END; /* FIXME: who handles the ending > !? */ b = t = e = p; if (++p >= end) goto eol; self->doctype = 0; } else if (*p == '%' && self->doctype) { /* doctype entities */ token = DTD_ENTITY; if (++p >= end) goto eol; b = t = p; while (ISALNUM(*p) || *p == '.') if (++p >= end) goto eol; e = p; if (*p == ';') p++; } else if (*p == '&') { /* entities */ token = ENTITYREF; if (++p >= end) goto eol; if (*p == '#') { token = CHARREF; if (++p >= end) goto eol; } b = t = p; if (self->xml) { while (ISALNUM(*p) || *p == '.' || *p == '-' || *p == '_' || *p == ':') if (++p >= end) goto eol; } else { while (ISALNUM(*p) || *p == '.') if (++p >= end) goto eol; } e = p; if (*p == ';') p++; else continue; } else { /* raw data */ if (++p >= end) { q = p; goto eol; } continue; } eot: /* end of token */ if (q != s && self->handle_data) { /* flush any raw data before this tag */ if (callHandleData(self, s, q-s)) return -1; } /* invoke callbacks */ if (token & TAG) { if (token == TAG_END) { if (self->finish_endtag) { if (callFinishEndTag(self, b, t-b)) return -1; } } else if (token == DIRECTIVE || token == DOCTYPE) { if (self->handle_special) { if (callHandleSpecial(self, b, e-b)) return -1; } } else if (token == PI) { if (self->handle_proc) { int len = t-b; while (ISSPACE(*t)) t++; if ((len==3) && (b[0]=='x') && (b[1]=='m') && (b[2]=='l')) fetchEncoding(self, t, e-t); if (callHandleProc(self, b, len, t, e-t)) return -1; } } else if (self->finish_starttag) { PyObject* attr; int len = t-b; while (ISSPACE(*t)) t++; attr = attrparse(self, t, e-t); if (!attr) return -1; if (callFinishStartTag(self, b, len, attr)) { Py_DECREF(attr); return -1; } Py_DECREF(attr); if (token == TAG_EMPTY && self->finish_endtag) { if (callFinishEndTag(self, b, len)) return -1; } } } else if (token == ENTITYREF && self->handle_entityref) { if (callHandleEntityRef(self, b, e-b)) return -1; } else if (token == CHARREF && (self->handle_charref || self->handle_data)) { if (self->handle_charref) { if (callHandleCharRef(self, b, e-b)) return -1; } else { /* fallback: handle charref's as data */ int ch = 0; CHAR_T *p; if (*b == 'x') { for (p = b+1; p < e; p++) ch = ch*16 + *p - (*p > 'F' ? 'a'-10 :(*p > '9' ? 'A'-10 : '0')); } else { for (p = b; p < e; p++) ch = ch*10 + *p - '0'; } #ifdef Py_USING_UNICODE if (self->unicode) { PyObject *res; Py_UNICODE uch = ch; int maxunicode = PyUnicode_GetMax(); if (ch > maxunicode) { PyErr_Format(PyExc_ValueError, "character reference &#x%x; exceeds sys.maxunicode (0x%x)", ch, maxunicode); return -1; } res = PyObject_CallFunction(self->handle_data, "u#", &uch, 1); if (!res) return -1; Py_DECREF(res); } else #endif { char nch; if (ch >= 128) { /* XXX: should utf-8 encode here for XML; can't do anything for SGML. */ PyErr_Format(PyExc_ValueError, "character reference &#x%x; exceeds ASCII range", ch); return -1; } nch = ch; if (callHandleData(self, &nch, 1)) return -1; } } } else if (token == CDATA && (self->handle_cdata || self->handle_data)) { if (self->handle_cdata) { if (callHandleCData(self, b, e-b)) return -1; } else { /* fallback: handle cdata as plain data */ if (callHandleData(self, b, e-b)) return -1; } } else if (token == COMMENT && self->handle_comment) { if (callHandleComment(self, b, e-b)) return -1; } q = p; /* start of token */ s = p; /* start of span */ } eol: /* end of line */ if (q != s && self->handle_data) { if (callHandleData(self, s, q-s)) return -1; } /* returns the number of bytes consumed in this pass */ return ((char*) q) - self->buffer; } static PyObject* attrparse(FastSGMLParserObject* self, const CHAR_T* p, int len) { PyObject* attrs; PyObject* key = NULL; PyObject* value = NULL; const CHAR_T* end = p + len; const CHAR_T* q; if (self->xml) attrs = PyDict_New(); else attrs = PyList_New(0); while (p < end) { /* skip leading space */ while (p < end && ISSPACE(*p)) p++; if (p >= end) break; /* get attribute name (key) */ q = p; while (p < end && *p != '=' && !ISSPACE(*p)) p++; key = stringFromData(self, q, p-q); if (key == NULL) goto err; if (self->xml) value = Py_None; else value = key; /* in SGML mode, default is same as key */ Py_INCREF(value); while (p < end && ISSPACE(*p)) p++; if (p < end && *p == '=') { /* attribute value found */ Py_DECREF(value); if (p < end) p++; while (p < end && ISSPACE(*p)) p++; q = p; if (p < end && (*p == '"' || *p == '\'')) { p++; while (p < end && *p != *q) p++; value = stringFromData(self, q+1, p-q-1); if (p < end && *p == *q) p++; } else { while (p < end && !ISSPACE(*p)) p++; value = stringFromData(self, q, p-q); } if (value == NULL) goto err; } if (self->xml) { /* add to dictionary */ /* PyString_InternInPlace(&key); */ if (PyDict_SetItem(attrs, key, value) < 0) goto err; Py_DECREF(key); Py_DECREF(value); } else { /* add to list */ PyObject* res; res = PyTuple_New(2); if (!res) goto err; PyTuple_SET_ITEM(res, 0, key); PyTuple_SET_ITEM(res, 1, value); if (PyList_Append(attrs, res) < 0) { Py_DECREF(res); goto err; } Py_DECREF(res); } key = NULL; value = NULL; } return attrs; err: Py_XDECREF(key); Py_XDECREF(value); Py_DECREF(attrs); return NULL; } /* this function gets passed the data part of the xml header * and reads and updates the encoding attribute * (this function does not free the original encoding string, * so it can only be called once) * * returns true on error, false on success */ static int fetchEncoding(FastSGMLParserObject* self, const CHAR_T* data, int len) { const char *found = NULL; char quote; for (;len>8;++data, --len) { if (!strncmp(data, "encoding", 8)) { found = data; break; } } if (!found) return 0; data += 8; /* skip "encoding" */ len -= 8; if ((len==0) || (*data!= '=')) return 0; ++data; /* skip '=' */ --len; if ((len==0) || ((*data!= '\'') && (*data!= '"'))) return 0; quote = *data++; /* skip quote char */ --len; found = data; /* encoding name starts here */ while ((len>0) && (*data != quote)) { ++data; --len; } if ((len==0) || (*data != quote)) return 0; /* now we can be sure that we found it */ self->encoding = malloc(data-found+1); if (!self->encoding) { PyErr_NoMemory(); return -1; } strncpy(self->encoding, found, data-found); self->encoding[data-found] = '\0'; /*printf("'%s'\n", self->encoding);*/ return 0; } static char *defaultEncoding = "utf-8"; /* this function constructs a string or Unicode object * from the passed in character data according to * the unicode parameter of the parser */ static PyObject* stringFromData(FastSGMLParserObject* self, const CHAR_T* data, int len) { #ifdef Py_USING_UNICODE if (self->unicode) return PyUnicode_Decode(data, len, self->encoding ? self->encoding : defaultEncoding, "strict"); else #endif return PyString_FromStringAndSize(data, len); } /* this function constructs a Unicode object from the * characters passed in (if the parser has unicode==1) * or uses the string directly (if the parser * has unicode==0) and calls the callback with it * * returns true on error, false on success */ static int callWithString(FastSGMLParserObject* self, PyObject* callback, const CHAR_T* data, int len) { PyObject* str = stringFromData(self, data, len); PyObject* res; if (!str) return -1; res = PyObject_CallFunction(callback, "O", str); Py_DECREF(str); if (res) { Py_DECREF(res); return 0; } else return -1; } /* this function constructs 2 Unicode objects from the * characters passed in (if the parser has unicode==1) * or uses the strings directly (if the parser * has unicode==0) and calls the callback with it * * returns true on error, false on success */ static int callWith2Strings(FastSGMLParserObject* self, PyObject* callback, const CHAR_T* data1, int len1, const CHAR_T* data2, int len2) { PyObject* res; PyObject* str1; PyObject* str2; str1 = stringFromData(self, data1, len1); if (!str1) return -1; str2 = stringFromData(self, data2, len2); if (!str2) { Py_DECREF(str1); return -1; } res = PyObject_CallFunction(callback, "OO", str1, str2); Py_DECREF(str1); Py_DECREF(str2); if (res) { Py_DECREF(res); return 0; } else return -1; } /* this function constructs a Unicode object from the * characters passed in (if the parser has unicode==1) * or uses the string directly (if the parser * has unicode==0) and calls the callback with it and * the second object * * returns true on error, false on success */ static int callWithStringAndObj(FastSGMLParserObject* self, PyObject* callback, const CHAR_T* data, int len, PyObject *obj) { PyObject* res; PyObject* str = stringFromData(self, data, len); if (!str) return -1; res = PyObject_CallFunction(callback, "OO", str, obj); Py_DECREF(str); if (res) { Py_XDECREF(res); return 0; } else return -1; } PyXML-0.8.2/mac/0040755000076400001440000000000007614726123012463 5ustar martinusersPyXML-0.8.2/mac/pyexpat.prj0100644000076400001440000015360706613227657014711 0ustar martinuserscool( xeCodeWarrior Project??? monaco( ( Wze~ZIP  $  $R`R-./lr Wai IJKLMNO??? monaco( ( X7exx.CFM68K:Project Miscxx.CFM68K:Editorxx.CFM68K:Fontxx.CFM68K:Project Extrasxx.CFM68K:Custom Keywordsxx.CFM68K:Access Pathsxx.CFM68K:Build Extrasxx.CFM68K:68K CodeGenxx.CFM68K:68K Disassemblerxx.CFM68K:68K Linkerxx.CFM68K:68K Projectxx.CFM68K:C/C++ Compilerxx.CFM68K:C/C++ Warningsxx.CFM68K:CFM68Kxx.CFM68K:Pascal Compilerxx.CFM68K:Pascal Warningsxx.CFM68K:PPC CodeGenxx.CFM68K:PPC Disassemblerxx.CFM68K:PPC Linkerxx.CFM68K:PPC PEFxx.CFM68K:PPC Projectxx.CFM68K:PPCAsm Panelxx.CFM68K:Rez Compilerxx.CFM68K:Target Settingsxx.CFM68K:File Mappingsxx.ppc:Project Miscxx.ppc:Editorxx.ppc:Fontxx.ppc:Project Extrasxx.ppc:Custom Keywordsxx.ppc:Access Pathsxx.ppc:Build Extrasxx.ppc:68K CodeGenxx.ppc:68K Disassemblerxx.ppc:68K Linkerxx.ppc:68K Projectxx.ppc:C/C++ Compilerxx.ppc:C/C++ Warningsxx.ppc:CFM68Kxx.ppc:Pascal Compilerxx.ppc:Pascal Warningsxx.ppc:PPC CodeGenxx.ppc:PPC Disassemblerxx.ppc:PPC Linkerxx.ppc:PPC PEFxx.ppc:PPC Projectxx.ppc:PPCAsm Panelxx.ppc:Rez Compilerxx.ppc:Target Settingsxx.ppc:File MappingsProject File Listxx.CFM68K:IR Optimizerxx.CFM68K:MacOS Merge Panelxx.ppc:IR Optimizerxx.ppc:MacOS Merge Panelxmltok.CFM68K:Custom Keywordsxmltok.CFM68K:Access Pathsxmltok.CFM68K:Target Settingsxmltok.CFM68K:File Mappingsxmltok.CFM68K:Build Extrasxmltok.CFM68K:68K CodeGenxmltok.CFM68K:68K Disassemblerxmltok.CFM68K:68K Linkerxmltok.CFM68K:68K Projectxmltok.CFM68K:C/C++ Compilerxmltok.CFM68K:C/C++ Warningsxmltok.CFM68K:CFM68Kxmltok.CFM68K:IR Optimizerxmltok.CFM68K:MacOS Merge Panelxmltok.CFM68K:Pascal Compilerxmltok.CFM68K:Pascal Warningsxmltok.CFM68K:PPC CodeGenxmltok.CFM68K:PPC Disassemblerxmltok.CFM68K:PPC Linkerxmltok.CFM68K:PPC PEFxmltok.CFM68K:PPC Projectxmltok.CFM68K:PPCAsm Panelxmltok.CFM68K:Rez Compilerxmltok.ppc:Custom Keywordsxmltok.ppc:Access Pathsxmltok.ppc:Target Settingsxmltok.ppc:File Mappingsxmltok.ppc:Build Extrasxmltok.ppc:68K CodeGenxmltok.ppc:68K Disassemblerxmltok.ppc:68K Linkerxmltok.ppc:68K Projectxmltok.ppc:C/C++ Compilerxmltok.ppc:C/C++ Warningsxmltok.ppc:CFM68Kxmltok.ppc:IR Optimizerxmltok.ppc:MacOS Merge Panelxmltok.ppc:Pascal Compilerxmltok.ppc:Pascal Warningsxmltok.ppc:PPC CodeGenxmltok.ppc:PPC Disassemblerxmltok.ppc:PPC Linkerxmltok.ppc:PPC PEFxmltok.ppc:PPC Projectxmltok.ppc:PPCAsm Panelxmltok.ppc:Rez Compilerxmltok.CFM68K:Debugger Targetxmltok.CFM68K:FTP Panelxmltok.CFM68K:Java Languagexmltok.CFM68K:Java Outputxmltok.CFM68K:Java Projectxmltok.CFM68K:JavaDoc Projectxmltok.CFM68K:WinRC Compilerxmltok.CFM68K:x86 CodeGenxmltok.CFM68K:x86 Exceptions Panelxmltok.CFM68K:x86 Linkerxmltok.CFM68K:x86 Projectxmltok.ppc:Debugger Targetxmltok.ppc:FTP Panelxmltok.ppc:Java Languagexmltok.ppc:Java Outputxmltok.ppc:Java Projectxmltok.ppc:JavaDoc Projectxmltok.ppc:WinRC Compilerxmltok.ppc:x86 CodeGenxmltok.ppc:x86 Exceptions Panelxmltok.ppc:x86 Linkerxmltok.ppc:x86 Projectpyexpat.CFM68K:Custom Keywordspyexpat.CFM68K:Access Pathspyexpat.CFM68K:Target Settingspyexpat.CFM68K:File Mappingspyexpat.CFM68K:Build Extraspyexpat.CFM68K:Debugger Targetpyexpat.CFM68K:68K CodeGenpyexpat.CFM68K:68K Disassemblerpyexpat.CFM68K:68K Linkerpyexpat.CFM68K:68K Projectpyexpat.CFM68K:C/C++ Compilerpyexpat.CFM68K:C/C++ Warningspyexpat.CFM68K:CFM68Kpyexpat.CFM68K:FTP Panelpyexpat.CFM68K:IR Optimizerpyexpat.CFM68K:Java Languagepyexpat.CFM68K:Java Outputpyexpat.CFM68K:Java Projectpyexpat.CFM68K:JavaDoc Projectpyexpat.CFM68K:MacOS Merge Panelpyexpat.CFM68K:Pascal Compilerpyexpat.CFM68K:Pascal Warningspyexpat.CFM68K:PPC CodeGenpyexpat.CFM68K:PPC Disassemblerpyexpat.CFM68K:PPC Linkerpyexpat.CFM68K:PPC PEFpyexpat.CFM68K:PPC Projectpyexpat.CFM68K:PPCAsm Panelpyexpat.CFM68K:Rez Compilerpyexpat.CFM68K:WinRC Compilerpyexpat.CFM68K:x86 CodeGenpyexpat.CFM68K:x86 Exceptions Panelpyexpat.CFM68K:x86 Linkerpyexpat.CFM68K:x86 Projectpyexpat.ppc:Custom Keywordspyexpat.ppc:Access Pathspyexpat.ppc:Target Settingspyexpat.ppc:File Mappingspyexpat.ppc:Build Extraspyexpat.ppc:Debugger Targetpyexpat.ppc:68K CodeGenpyexpat.ppc:68K Disassemblerpyexpat.ppc:68K Linkerpyexpat.ppc:68K Projectpyexpat.ppc:C/C++ Compilerpyexpat.ppc:C/C++ Warningspyexpat.ppc:CFM68Kpyexpat.ppc:FTP Panelpyexpat.ppc:IR Optimizerpyexpat.ppc:Java Languagepyexpat.ppc:Java Outputpyexpat.ppc:Java Projectpyexpat.ppc:JavaDoc Projectpyexpat.ppc:MacOS Merge Panelpyexpat.ppc:Pascal Compilerpyexpat.ppc:Pascal Warningspyexpat.ppc:PPC CodeGenpyexpat.ppc:PPC Disassemblerpyexpat.ppc:PPC Linkerpyexpat.ppc:PPC PEFpyexpat.ppc:PPC Projectpyexpat.ppc:PPCAsm Panelpyexpat.ppc:Rez Compilerpyexpat.ppc:WinRC Compilerpyexpat.ppc:x86 CodeGenpyexpat.ppc:x86 Exceptions Panelpyexpat.ppc:x86 Linkerpyexpat.ppc:x86 Project2|{~}<=>?8;@AB7e:fCghijDEFGHIJKLM9klmnoSTUVORWXYNpQqZrstu[\]^_`abcdPvwxyz  34 !"#$%&156'()*+,-./00123IKMBD!# +N.456*/-Q7 EFHJLG$%() 89;<=>?@OACP :,& "'JavaClasses.jarZIP MWZP l=ROOTGRUPSourcesFILE FILEGRUPexpat librariesFILE FILE FILEGRUP LibrariesFILEFILEFILEEEE pyexpat.cfm68k.slbPythshlb????U { mwerks_plugin_config.h '7Rcj w  -;BSbmx !"#$%&' (/)@*Q+a,n-~./0123456789:/;<<H=Y>d?l@xABCDEFGHIJ*K:LQM^NwO{PQR IJKLMN O __initialize_start__terminate a.out????APPLX????U { mwerks_plugin_config.h UPI.prefixJavaClasses.jarZIP MWZP Merge Out????APPLDLGXckidProjWSPC UPI.prefixxx.CFM68KSourcesLibrariesxxmodule.cxx.CFM68K..expMSL ShLibRuntimeCFM68K.LibPythonCoreCFM68Kxx.ppcxx.ppc..expMSL ShLibRuntime.LibPythonCorePPC:xx.CFM68K.slbLib Import 68KMPW Import 68KBalloon HelpMW C/C++ 68KMW Pascal 68KMW RezPEF Import 68k:xx.ppc.slbLib Import PPCMW C/C++ PPCMW Pascal PPCPPCAsmXCOFF Import PPCPEF Import PPCxx.prj.expPythonCore:Modules:xxmodule.c:xx.prj.exp:PythonCore:a.outxmltok.CFM68K:xmltok.cfm68k.slbxmltok.ppc:xmltok.ppc.slblibxmltok (cfm68k).Liblibxmltok (ppc GUSI).Libxmltok.cxmltok.prj.expMacOS 68K LinkerMacOS PPC LinkerCustom KeywordsAccess PathsTarget SettingsFile MappingsBuild ExtrasDebugger Target68K CodeGen68K Disassembler68K Linker68K ProjectC/C++ CompilerC/C++ WarningsCFM68KIR OptimizerPascal CompilerPascal WarningsRez CompilerPPC CodeGenPPC DisassemblerPPC LinkerPPC PEFPPC ProjectPPCAsm Panelpyexpat.CFM68K:pyexpat.cfm68k.slbpyexpat.ppc:pyexpat.ppc.slblibexpat (4i8d GUSI).Liblibexpat (ppc GUSI).Liblibexpat.prjlibexpat 68k:libexpat (4i8d GUSI).Liblibexpat cfm68k:libexpat (cfm68k).Liblibexpat ppc:libexpat (ppc GUSI).Liballpyexpat.cpyexpat.prj.expFTP PanelBCosDEo::::::::CWGUSI::Metrowerks Standard Library:MSL C:@:MacOS Support:@ Merge Out????APPLDLGXckidProjWSPCinitxinitxx(n H PQL QQMacOS 68K Linkerpyexpat.CFM68K:DFLTMetrowerks JavaInternet ExplorerDFLTMSIEhttp://java.sun.com/products/jdk/1.1/docs/api/222stdwin xxmodule.slbPYTHshlb????P'CODE' 'DATA' 'PICT' NONAME.EXE@U { NONAME.EXE@U {(7Pj  &7Qk!9M[g} !"#$ %"&8'F(])t*+,-./012'394P5l6789:; <'=A>`?y@ABCDEF;GYHsIJKLMNO,PDQ_RxSTUVWX Y$Z6[N\k]^_`abc d ,e Df bg zh i j k l m n Co \p vq r s t u v w #x :y Zz p{ | } ~   9 T t  0 M h =Wn8So (?Wr6Tp6Qi::::::::CWGUSI:clude::Metrowerks Standard Library:MSL C:@:MacOS Support:@__initialize__ter__terminate+,-./01234 5 67R89:;<=>?@AMacOS PPC Linkerpyexpat.ppc:MacOS PPC LinkerAPPL`Appl`MMLBLib Import PPCMPLFLib Import PPCMWCD`RSRC`TEXT.bhcʫP0~ʫPeBalloon HelpʫeTEXT.cMW C/C++ PPCTEXT.c++MW C/C++ PPCTEXT.ccMW C/C++ PPCTEXT.cpMW C/C++ PPCTEXT.cppMW C/C++ PPCTEXT.expTEXT.hMW C/C++ PPCTEXT.pMW Pascal PPCTEXT.pasMW Pascal PPCTEXT.pchMW C/C++ PPCTEXT.pch++MW C/C++ PPCTEXT.rMW RezTEXT.shcʫP0~ʫPePPCAsmn HelʫeXCOFXCOFF Import PPCdocu`rsrc`shlbPEF Import PPCstubPEF Import PPC.docPMacOS 68K LinkerAPPL`Appl`MMLBLib Import 68KMPLFLib Import 68KMWCD`OBJ MPW Import 68KRSRC`TEXT.bhcʫP0~ʫPeBalloon HelpʫeTEXT.cMW C/C++ 68KTEXT.c++MW C/C++ 68KTEXT.ccMW C/C++ 68KTEXT.cpMW C/C++ 68KTEXT.cppMW C/C++ 68KTEXT.expʫP0~ʫPe*t xʮDTʫe<TEXT.hMW C/C++ 68KTEXT.pMW Pascal 68KTEXT.pasMW Pascal 68KTEXT.pchMW C/C++ 68KTEXT.pch++MW C/C++ 68KTEXT.rMW RezTEXT.segʫP0~ʫPe*t xʮDTʫe<docu`rsrc`shlbPEF Import 68kstubPEF Import 68k.docPWin32 x86 Linker TEXT.cMW C/C++ x86TEXT.c++MW C/C++ x86TEXT.cpMW C/C++ x86TEXT.cppMW C/C++ x86TEXT.pchMW C/C++ x86TEXT.pch++MW C/C++ x86TEXT.rcMW WinRC.libLib Import x86.objObj Import x86MC LinkerMMCHTEXT.cMC C/C++TEXT.clsMC Class CompilerTEXT.defTEXT.docTEXT.hTEXT.pchMC C/C++TEXT.tsNoneMMPr@MacOS MergeAPPL`Appl`RSRC`TEXT.bhBalloon HelpTEXT.rRezrsrc`shlb__startDFLTMetrowerks JavaInternet ExplorerDFLTMSIEhttp://java.sun.com/products/jdk/1.1/docs/api/:::pyexpat.ppc.slbPythshlb????P'CODE' 'DATA' 'PICT' NONAME.EXE@U { n G H PQQQBCoDEoU {)*+,-./01234 5 6789:;<=>?@AMacOS PPC LinkerAPPL`Appl`MMLBLib Import PPCMPLFLib Import PPCMWCD`RSRC`TEXT.bhcn0yneBalloon Help%neVTEXT.cMW C/C++ PPCTEXT.c++MW C/C++ PPCTEXT.ccMW C/C++ PPCTEXT.cpMW C/C++ PPCTEXT.cppMW C/C++ PPCTEXT.expn0yneRez(nq%neaTEXT.hMW C/C++ PPCTEXT.pMW Pascal PPCTEXT.pasMW Pascal PPCTEXT.pchMW C/C++ PPCTEXT.pch++MW C/C++ PPCTEXT.rMW RezTEXT.shcn0ynePPCAsmn Hel%neVXCOFXCOFF Import PPCdocu`rsrc`shlbPEF Import PPCstubPEF Import PPC.docPMacOS 68K LinkerAPPL`Appl`MMLBLib Import 68KMPLFLib Import 68KMWCD`OBJ MPW Import 68KRSRC`TEXT.bhc@ Cj9ToCBalloon Helpj9TnCj9hLrTEXT.cMW C/C++ 68KTEXT.c++MW C/C++ 68KTEXT.ccMW C/C++ 68KTEXT.cpMW C/C++ 68KTEXT.cppMW C/C++ 68KTEXT.exp@ 9WCcCc ::.8P"Cc9WTEXT.hMW C/C++ 68KTEXT.pMW Pascal 68KTEXT.pasMW Pascal 68KTEXT.pchMW C/C++ 68KTEXT.pch++MW C/C++ 68KTEXT.rMW RezTEXT.seg@ 9WCcCc ::.8P"Cc9Wdocu`rsrc`shlbPEF Import 68kstubPEF Import 68k.docPWin32 x86 Linker TEXT.cMW C/C++ x86TEXT.c++MW C/C++ x86TEXT.cpMW C/C++ x86TEXT.cppMW C/C++ x86TEXT.pchMW C/C++ x86TEXT.pch++MW C/C++ x86TEXT.rcMW WinRC.libLib Import x86.objObj Import x86MC LinkerMMCHTEXT.cMC C/C++TEXT.clsMC Class CompilerTEXT.defTEXT.docTEXT.hTEXT.pchMC C/C++TEXT.tsNoneMMPr@MacOS MergeAPPL`Appl`RSRC`TEXT.bhBalloon HelpTEXT.rRezrsrc`shlbmstrf7 mstlmstn(msti-mstr$mstlmstn' pref10prefaJpref/prefMFa@mtslFmtplmtlomtpi( pref+20prefbJpref! pref$ mtslmtpl mtlo mtpi54mtgl,mpsi!HPLst|3:(msti"mtps"mtps mall|cmaplprefz|:- `pref"e}LA pref~xprefprefRMprefdpref0 prefy<pref9#(prefw$. # modified 2000/12/18, Martin v. Löwis ########################################################################### # import some modules we need import os,sys,string from types import StringType,TupleType,ListType from distutils.util import change_root from distutils.filelist import FileList from distutils.command.install_data import install_data ########################################################################### # a container class for our more sophisticated install mechanism class Data_Files: """ container for list of data files. supports alternate base_dirs e.g. 'install_lib','install_header',... supports a directory where to copy files supports templates as in MANIFEST.in supports preserving of paths in filenames eg. foo/xyz is copied to base_dir/foo/xyz supports stripping of leading dirs of source paths eg. foo/bar1/xyz, foo/bar2/abc can be copied to bar1/xyz, bar2/abc """ def __init__(self,base_dir=None,files=None,copy_to=None,template=None,preserve_path=0,strip_dirs=0): self.base_dir = base_dir self.files = files self.copy_to = copy_to if template is not None: t = [] for item in template: item = string.strip(item) if not item:continue t.append(item) template = t self.template = template self.preserve_path = preserve_path self.strip_dirs = strip_dirs self.finalized = 0 def warn (self, msg): sys.stderr.write ("warning: %s: %s\n" % ("install_data", msg)) def debug_print (self, msg): """Print 'msg' to stdout if the global DEBUG (taken from the DISTUTILS_DEBUG environment variable) flag is true. """ from distutils.core import DEBUG if DEBUG: print msg def finalize(self): """ complete the files list by processing the given template """ if self.finalized: return if self.files == None: self.files = [] if self.template != None: if type(self.template) == StringType: self.template = string.split(self.template,";") filelist = FileList(self.warn,self.debug_print) for line in self.template: filelist.process_template_line(string.strip(line)) filelist.sort() filelist.remove_duplicates() self.files.extend(filelist.files) self.finalized = 1 # end class Data_Files ########################################################################### # a more sophisticated install routine than distutils install_data class install_Data_Files (install_data): def check_data(self,d): """ check if data are in new format, if not create a suitable object. returns finalized data object """ if not isinstance(d, Data_Files): self.warn(("old-style data files list found " "-- please convert to Data_Files instance")) if type(d) is TupleType: if len(d) != 2 or not (type(d[1]) is ListType): raise DistutilsSetupError, \ ("each element of 'data_files' option must be an " "Data File instance, a string or 2-tuple (string,[strings])") d = Data_Files(copy_to=d[0],files=d[1]) else: if not (type(d) is StringType): raise DistutilsSetupError, \ ("each element of 'data_files' option must be an " "Data File instance, a string or 2-tuple (string,[strings])") d = Data_Files(files=[d]) d.finalize() return d def run(self): self.outfiles = [] install_cmd = self.get_finalized_command('install') for d in self.data_files: d = self.check_data(d) install_dir = self.install_dir # alternative base dir given => overwrite install_dir if d.base_dir != None: install_dir = getattr(install_cmd,d.base_dir) # copy to an other directory if d.copy_to != None: if not os.path.isabs(d.copy_to): # relatiev path to install_dir dir = os.path.join(install_dir, d.copy_to) elif install_cmd.root: # absolute path and alternative root set dir = change_root(self.root,d.copy_to) else: # absolute path dir = d.copy_to else: # simply copy to install_dir dir = install_dir # warn if necceassary self.warn("setup script did not provide a directory to copy files to " " -- installing right in '%s'" % install_dir) dir=os.path.normpath(dir) # create path self.mkpath(dir) # copy all files for src in d.files: if d.strip_dirs > 0: dst = string.join(string.split(os.path.normcase(src),os.sep)[d.strip_dirs:],os.sep) else: dst = src if d.preserve_path: # preserve path in filename self.mkpath(os.path.dirname(os.path.join(dir,dst))) out = self.copy_file(src, os.path.join(dir,dst)) else: out = self.copy_file(src, dir) if type(out) is TupleType: out = out[0] self.outfiles.append(out) return self.outfiles def get_inputs (self): inputs = [] for d in self.data_files: d = self.check_data(d) inputs.append(d.files) return inputs def get_outputs (self): return self.outfiles ########################################################################### PyXML-0.8.2/test/0040755000076400001440000000000007614726123012702 5ustar martinusersPyXML-0.8.2/test/dom/0040755000076400001440000000000007614726123013461 5ustar martinusersPyXML-0.8.2/test/dom/borrowed/0040755000076400001440000000000007614726123015304 5ustar martinusersPyXML-0.8.2/test/dom/borrowed/TestSuite.py0100644000076400001440000001066007413603006017576 0ustar martinusersimport sys, traceback, os OK = 0 PASSED = 1 FAILED = -1 class TestItem: def __init__(self, suite, title): self.suite = suite self.title = title self.messages = [] self.hasErrors = 0 self.hasWarnings = 0 if suite.useColor: #self.moveTo = '\033[%dG' % (suite.columns - 9) self.colorSuccess = '\033[1;32m' self.colorFailure = '\033[1;31m' self.colorWarning = '\033[1;33m' self.colorNormal = '\033[0;39m' else: self.colorSuccess = '' self.colorFailure = '' self.colorWarning = '' self.colorNormal = '' def finish(self): if self.hasErrors: msg = self._failure() retVal = FAILED elif self.hasWarnings: msg = self._passed() retVal = PASSED else: msg = self._success() retVal = OK spaces = self.suite.columns - 9 spaces = spaces - len(self.title) title = self.title + ' '*spaces + msg for msg in self.messages: print msg[0] return retVal def debug(self, msg): self.messages.append(msg) def message(self, msg): self.messages.append(msg) def warning(self, msg): self.messages.append(msg) self.hasWarnings = 1 def error(self, msg, saveTrace=0): if self.suite.stopOnError: raise msg if saveTrace: tb = sys.exc_info()[-1] ftb = traceback.format_list(traceback.extract_tb(tb)) if ftb: msg = msg + '\n' for t in ftb: msg = msg + t self.messages.append(msg) self.hasErrors = 1 ### Internal Methods ### def _success(self): return '[%s OK %s]' %(self.colorSuccess, self.colorNormal) def _passed(self): return '[%sPASSED%s]' %(self.colorWarning, self.colorNormal) def _failure(self): return '[%sFAILED%s]' %(self.colorFailure, self.colorNormal) class TestGroup: def __init__(self, suite, title=None): self.suite = suite self.title = title self.tests = [] self.retVal = OK if title: msg = '********** ' + title + ' **********' print msg ### Methods ### def finish(self): for test in self.tests: self.retVal = self.retVal or test.finish() return self.retVal def startTest(self, title): test = TestItem(self.suite, title) self.tests.append(test) def testDone(self): if self.tests: self.retVal = self.retVal | self.tests[-1].finish() del self.tests[-1] return self.retVal class TestSuite: def __init__(self, stopOnError=1, useColor=0, cols=80): if os.name == 'posix': self.useColor = 1 else: self.useColor = useColor self.stopOnError = stopOnError self.useColor = useColor self.columns = cols self.groups = [] self.retVal = OK def __del__(self): retVal = OK while len(self.groups): retVal = retVal or group[-1].finish() return retVal ### Methods ### def startGroup(self, title): group = TestGroup(self, title) self.groups.append(group) def groupDone(self): retVal = OK if self.groups: retVal = self.groups[-1].finish() del self.groups[-1] return retVal def startTest(self, title): if not self.groups: self.startGroup(self) print 'Added (null) group' self.groups[-1].startTest(title) def testDone(self): if self.groups: self.groups[-1].testDone() def testResults(self,expected,actual, done = 1): if expected != actual: self.error("Expected %s, got %s" % (expected,actual)) return 0 elif done: self.testDone() return 1 def message(self, msg): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].message(msg) def warning(self, msg): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].warning(msg) def error(self, msg, saveTrace=0): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].error(msg, saveTrace) PyXML-0.8.2/test/dom/borrowed/af_20000919.py0100644000076400001440000001510507413603006017216 0ustar martinusersimport cStringIO from xml.dom import DOMException from xml.dom import NAMESPACE_ERR from xml.dom.ext import Print, PrettyPrint from xml.dom.ext.reader import Sax2 def GetExceptionName(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name source_1 = """ Pieter Aaron
    404 Error Way
    404-555-1234 404-555-4321 404-555-5555 pieter.aaron@inter.net
    Emeka Ndubuisi
    42 Spam Blvd
    767-555-7676 767-555-7642 800-SKY-PAGEx767676 endubuisi@spamtron.com
    Vasia Zhugenev
    2000 Disaster Plaza
    000-987-6543 000-000-0000 vxz@magog.ru
    """ expected_1 = """""" expected_2 = """ """ expected_3 = """ Pieter Aaron
    404 Error Way
    404-555-1234 404-555-4321 404-555-5555 pieter.aaron@inter.net
    Emeka Ndubuisi
    42 Spam Blvd
    767-555-7676 767-555-7642 800-SKY-PAGEx767676 endubuisi@spamtron.com
    Vasia Zhugenev
    2000 Disaster Plaza
    000-987-6543 000-000-0000 vxz@magog.ru
    """ expected_4 = """ Pieter Aaron
    404 Error Way
    404-555-1234 404-555-4321 404-555-5555 pieter.aaron@inter.net
    Emeka Ndubuisi
    42 Spam Blvd
    767-555-7676 767-555-7642 800-SKY-PAGEx767676 endubuisi@spamtron.com
    Vasia Zhugenev
    2000 Disaster Plaza
    000-987-6543 000-000-0000 vxz@magog.ru
    """ def Test(tester): tester.startGroup("Alexander Fayolle's Problems and variations") tester.startTest('Bad setAttNS test') d=Sax2.FromXml('') e = d.createElementNS('', 'elt') d.documentElement.appendChild(e) try: e.setAttributeNS('http://logilab', 'att', 'value1') except DOMException, x: if x.code != NAMESPACE_ERR: name = getExceptionName(x.code) tester.error("Wrong exception '%s', expected NAMESPACE_ERR" % name) else: tester.error('setAttributeNS with no prefix and non-null URI doesn\'t raise exception.') e.setAttributeNS('http://logilab', 'spam:att', 'value1') stream = cStringIO.StringIO() Print(d, stream=stream) result = stream.getvalue() if result != expected_1: tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_1), repr(result))) stream = cStringIO.StringIO() PrettyPrint(d, stream=stream) result = stream.getvalue() if result != expected_2: tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_2), repr(result))) tester.testDone() tester.startTest('Document Fragment Printing') d = Sax2.FromXml(source_1) df = d.createDocumentFragment() for n in d.documentElement.childNodes: df.appendChild(n.cloneNode(1)) if len(df.childNodes) != len(d.documentElement.childNodes): tester.error('Docfrag append error') if df.childNodes.length != d.documentElement.childNodes.length: tester.error('Docfrag append error') stream = cStringIO.StringIO() PrettyPrint(df, stream=stream) result = stream.getvalue() if result != expected_3: raise Exception('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_3), repr(result))) tester.testDone() tester.startTest('Document Type Printing') d = Sax2.FromXml(source_1) d.doctype.__dict__['__systemId'] = "addr_book.dtd" stream = cStringIO.StringIO() PrettyPrint(d, stream=stream) result = stream.getvalue() if result != expected_4: raise Exception('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_4), repr(result))) tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = Test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/borrowed/af_20000922.py0100644000076400001440000000322707413603006017212 0ustar martinusersimport cStringIO from xml.dom import DOMException from xml.dom import NAMESPACE_ERR from xml.dom.ext import Print, PrettyPrint from xml.dom.ext.reader import Sax2 def GetExceptionName(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name source_1 = """ """ expected_1 = """\ \303\240\303\251\303\250\303\252\303\253\303\257\303\256\303\266\303\264\303\271\303\274""" expected_2 = """\ """ def Test(tester): tester.startGroup("Alexander Fayolle's encoding problems and variations") tester.startTest('XML output UTF-8 encoding') d=Sax2.FromXml(source_1) stream = cStringIO.StringIO() Print(d, stream=stream) result = stream.getvalue() if result != expected_1: tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_1), repr(result))) tester.testDone() tester.startTest('XML output ISO-8859-1 encoding') d=Sax2.FromXml(source_1) stream = cStringIO.StringIO() Print(d, stream=stream, encoding='ISO-8859-1') result = stream.getvalue() if result != expected_2: tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_2), repr(result))) tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = Test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/borrowed/nc_20000921.py0100644000076400001440000000223607413603006017222 0ustar martinusersimport cStringIO from xml.dom import DOMException from xml.dom import NAMESPACE_ERR from xml.dom.ext import Print, PrettyPrint from xml.dom.ext.reader import Sax2 def GetExceptionName(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name source_1 = """""" expected_1 = """\ """ def Test(tester): tester.startGroup("Nicolas Chauvat 's Printer Bug Report") tester.startTest('Attribute quote print') d=Sax2.FromXml(source_1) stream = cStringIO.StringIO() Print(d, stream=stream) result = stream.getvalue() if result != expected_1: tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_1), repr(result))) return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = Test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/borrowed/uo_20010713.py0100644000076400001440000000420207323624056017250 0ustar martinusersimport cStringIO from xml.dom import DOMException from xml.dom.ext.reader import HtmlLib from xml.dom.ext import XHtmlPrint def GetExceptionName(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name source_1 = """\ XML The future of EDI?
    Resources and Related Links
       
    """ expected_1 = """\ XML The future of EDI?
    Resources and Related Links
    """ def Test(tester): tester.startGroup("Uche Ogbuji's problems with   and  ") tester.startTest('Tidy HTML with nbsps and 160s') reader = HtmlLib.Reader() doc = reader.fromString(source_1, charset="iso-8859-1") stream = cStringIO.StringIO() XHtmlPrint(doc, stream=stream) result = stream.getvalue() if result != expected_1: tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_1), repr(result))) tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = Test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/ext/0040755000076400001440000000000007614726123014261 5ustar martinusersPyXML-0.8.2/test/dom/ext/TestSuite.py0100644000076400001440000001066007413603007016554 0ustar martinusersimport sys, traceback, os OK = 0 PASSED = 1 FAILED = -1 class TestItem: def __init__(self, suite, title): self.suite = suite self.title = title self.messages = [] self.hasErrors = 0 self.hasWarnings = 0 if suite.useColor: #self.moveTo = '\033[%dG' % (suite.columns - 9) self.colorSuccess = '\033[1;32m' self.colorFailure = '\033[1;31m' self.colorWarning = '\033[1;33m' self.colorNormal = '\033[0;39m' else: self.colorSuccess = '' self.colorFailure = '' self.colorWarning = '' self.colorNormal = '' def finish(self): if self.hasErrors: msg = self._failure() retVal = FAILED elif self.hasWarnings: msg = self._passed() retVal = PASSED else: msg = self._success() retVal = OK spaces = self.suite.columns - 9 spaces = spaces - len(self.title) title = self.title + ' '*spaces + msg for msg in self.messages: print msg[0] return retVal def debug(self, msg): self.messages.append(msg) def message(self, msg): self.messages.append(msg) def warning(self, msg): self.messages.append(msg) self.hasWarnings = 1 def error(self, msg, saveTrace=0): if self.suite.stopOnError: raise msg if saveTrace: tb = sys.exc_info()[-1] ftb = traceback.format_list(traceback.extract_tb(tb)) if ftb: msg = msg + '\n' for t in ftb: msg = msg + t self.messages.append(msg) self.hasErrors = 1 ### Internal Methods ### def _success(self): return '[%s OK %s]' %(self.colorSuccess, self.colorNormal) def _passed(self): return '[%sPASSED%s]' %(self.colorWarning, self.colorNormal) def _failure(self): return '[%sFAILED%s]' %(self.colorFailure, self.colorNormal) class TestGroup: def __init__(self, suite, title=None): self.suite = suite self.title = title self.tests = [] self.retVal = OK if title: msg = '********** ' + title + ' **********' print msg ### Methods ### def finish(self): for test in self.tests: self.retVal = self.retVal or test.finish() return self.retVal def startTest(self, title): test = TestItem(self.suite, title) self.tests.append(test) def testDone(self): if self.tests: self.retVal = self.retVal | self.tests[-1].finish() del self.tests[-1] return self.retVal class TestSuite: def __init__(self, stopOnError=1, useColor=0, cols=80): if os.name == 'posix': self.useColor = 1 else: self.useColor = useColor self.stopOnError = stopOnError self.useColor = useColor self.columns = cols self.groups = [] self.retVal = OK def __del__(self): retVal = OK while len(self.groups): retVal = retVal or group[-1].finish() return retVal ### Methods ### def startGroup(self, title): group = TestGroup(self, title) self.groups.append(group) def groupDone(self): retVal = OK if self.groups: retVal = self.groups[-1].finish() del self.groups[-1] return retVal def startTest(self, title): if not self.groups: self.startGroup(self) print 'Added (null) group' self.groups[-1].startTest(title) def testDone(self): if self.groups: self.groups[-1].testDone() def testResults(self,expected,actual, done = 1): if expected != actual: self.error("Expected %s, got %s" % (expected,actual)) return 0 elif done: self.testDone() return 1 def message(self, msg): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].message(msg) def warning(self, msg): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].warning(msg) def error(self, msg, saveTrace=0): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].error(msg, saveTrace) PyXML-0.8.2/test/dom/ext/bigTest.html0100644000076400001440000000433007166146227016550 0ustar martinusers Sample SAX Program

    2.2a Sample SAX Program

    import sys
    from xml.sax import saxlib, saxexts, drivers

    class PrintWorkNumbers(saxlib.HandlerBase):
        """This is our specialized document handler class"""
        def __init__(self):
            self.curr_name = ''
            self.print_flag = 0

        def startElement(self, name, attribs):
            if name == 'NAME':
                sys.stdout.write('Name: ')
                self.print_flag = 1
            elif name == 'PHONENUM':
                if attribs['DESC'] == 'Work':
                &nb sp;   sys.stdout.write('Work phone number: ')
                &nb sp;   self.print_flag = 1

        def endElement(self, name):
            if self.print_flag:
                self.print_flag = 0
                print    #write new line
            if name == 'NAME':
                self.curr_name = name

        def characters(self, ch, start, length):
            if self.print_flag:
                sys.stdout.write(ch[start:start+length])
     

    p = saxexts.XMLValParserFactory.make_parser()
    p.setDocumentHandler(PrintWorkNumbers())
    xml_file = open(sys.argv[1], 'r')
    p.parseFile(xml_file)
    xml_file.close()
     
      PyXML-0.8.2/test/dom/ext/mulit-single.html0100644000076400001440000000064507166146227017565 0ustar martinusers Single tag Test

    Single tag Test





    Last modified: Tue Aug 31 13:05:11 CDT 1999 PyXML-0.8.2/test/dom/ext/single.html0100644000076400001440000000060707166146227016433 0ustar martinusers Single tag Test

    Single tag Test



    Last modified: Tue Aug 31 13:05:11 CDT 1999 PyXML-0.8.2/test/dom/ext/test_html_builder.py0100644000076400001440000000140307413603007020327 0ustar martinusers######################################################################## # # File Name: TestHtmlBuilder.py # # Docs: http://docs.4suite.com/4Dom/TestHtmlBuilder.py.html # """ Test suite for the Html portion of the builder. WWW: http://4suite.com/4Dom e-mail: support@4suite.com Copyright (c) 2000 Fourthought, Inc., USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ def test(): from xml.dom.ext.reader import HtmlLib from xml.dom import ext d = HtmlLib.FromHtmlFile('single.html') ext.PrettyPrint(d) d = HtmlLib.FromHtmlFile('mulit-single.html') ext.PrettyPrint(d) d = HtmlLib.FromHtmlFile('bigTest.html') ext.PrettyPrint(d) if __name__ == '__main__': test() PyXML-0.8.2/test/dom/ext/test_memory.py0100644000076400001440000000202107413603007017162 0ustar martinusersimport Cyclops,sys from xml.dom.ext.reader import Sax2 from xml.dom import ext def test(): data = sys.stdin.read() doc = Sax2.FromXml(data) b1 = doc.createElementNS("http://foo.com","foo:branch") c1 = doc.createElementNS("http://foo.com","foo:child1") c2 = doc.createElementNS("http://foo.com","foo:child2") b1.setAttributeNS("http://foo.com","foo:a1","value-1") a1 = b1.getAttributeNodeNS("http://foo.com","a1") a1.value = "This shouldn't leak" b1.appendChild(c1) b1.appendChild(c2) doc.documentElement.appendChild(b1) r1 = doc.createElementNS("http://foo.com","foo:replace") doc.documentElement.replaceChild(r1,b1) b1.removeChild(c2) import cStringIO s = cStringIO.StringIO() import xml.dom.ext xml.dom.ext.Print(doc, stream = s) ext.ReleaseNode(doc) ext.ReleaseNode(b1) doc = Sax2.FromXml(data) ext.ReleaseNode(doc) if __name__ == '__main__': cy = Cyclops.CycleFinder() cy.run(test) cy.find_cycles() cy.show_cycles() PyXML-0.8.2/test/dom/ext/test_nss_print.py0100644000076400001440000000242107166146227017710 0ustar martinuserssource_1 = """ XML Blaster Re: Blaster Bitchin

    By Test Super User
    2025-08-19 13:56:42-0600
    """ def test(tester): tester.startGroup('XML With Namespaces') tester.startTest('Namespaces multiply defined at 2nd level') from xml.dom.ext.reader import Sax2 import xml.dom.ext doc = Sax2.FromXml(source_1) xml.dom.ext.Print(doc) tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/ext/test_single_elements.py0100644000076400001440000000066507413603007021043 0ustar martinusersdef test(inFile): from xml.dom.ext.reader import HtmlLib from xml.dom import ext from xml.dom import Node from xml.dom.html import HTMLDocument doc = HTMLDocument.HTMLDocument() HtmlLib.FromHtmlStream(inFile,doc) print doc ext.PrettyPrint(doc) if __name__ == '__main__': import sys inFile = sys.stdin if len(sys.argv) == 2: inFile = open(sys.argv[1],'r') test(inFile) PyXML-0.8.2/test/dom/ext/test_xhtml_printer.py0100644000076400001440000000045107413603007020556 0ustar martinusersdef test(stream): from xml.dom.ext.reader import HtmlLib doc = HtmlLib.FromHtmlStream(stream) from xml.dom import ext #print "Not Pretty" #ext.XHtmlPrint(doc) print "Pretty" ext.XHtmlPrettyPrint(doc) if __name__ == '__main__': import sys test(sys.stdin) PyXML-0.8.2/test/dom/html/0040755000076400001440000000000007614726123014425 5ustar martinusersPyXML-0.8.2/test/dom/html/test.py0100644000076400001440000000317307413603007015747 0ustar martinusersfileList = ['Collection', 'Element', 'HTML', 'HEAD', 'LINK', 'TITLE', 'META', 'BASE', 'ISINDEX', 'STYLE', 'BODY', 'FORM', 'SELECT', 'OPTGROUP', 'OPTION', 'INPUT', 'TEXTAREA', 'BUTTON', 'LABEL', 'FIELDSET', 'LEGEND', 'UL', 'OL', 'DL', 'DIR', 'MENU', 'LI', 'BLOCKQUOTE', 'DIV', 'P', 'H', 'Q', 'PRE', 'BR', 'BASEFONT', 'FONT', 'HR', 'MOD', 'A', 'IMG', 'OBJECT', 'PARAM', 'APPLET', 'MAP', 'AREA', 'SCRIPT', 'CAPTION', 'COL', 'TD', 'TR', 'SECTION', 'TABLE', 'FRAMESET', 'FRAME', 'IFRAME', 'DOCUMENT', 'HTML_DOM_IMPLEMENTATION', ] import string def test(files): print 'Testing HTML Level 1' for file in files: print '**********Testing HTML %s**********' % file exec 'import test_%s;_mod = test_%s' % (string.lower(file),string.lower(file)); _mod.test(); if __name__ == '__main__': import sys if len(sys.argv) <2: test(fileList) else: test(sys.argv[1:]); PyXML-0.8.2/test/dom/html/test_a.py0100644000076400001440000000142607413603007016246 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLAnchorElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') a = doc.createElement('A') print 'testing get/set' testAttribute(a,'accessKey') testAttribute(a,'charset') testAttribute(a,'coords') testAttribute(a,'href') testAttribute(a,'hreflang') testAttribute(a,'rel') testAttribute(a,'rev') testIntAttribute(a,'tabIndex') testAttribute(a,'target') testAttribute(a,'type') a._set_shape('rect') rt = a._get_shape() if rt != 'Rect': error('get/set shape failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_applet.py0100644000076400001440000000140207413603007017305 0ustar martinusersfrom util import error from util import testAttribute def test(): print 'testing source code syntax' from xml.dom.html.HTMLAppletElement import HTMLAppletElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') p = doc.createElement('Applet') print "testing get/set" testAttribute(p,'alt') testAttribute(p,'archive') testAttribute(p,'code') testAttribute(p,'codeBase') testAttribute(p,'height') testAttribute(p,'hspace') testAttribute(p,'object') testAttribute(p,'vspace') testAttribute(p,'width') p._set_align('left') rt = p._get_align() if rt != 'Left': error('get/set align failed') print "get/sets work" if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_area.py0100644000076400001440000000134607413603007016737 0ustar martinusersfrom util import error from util import testAttribute from util import testIntAttribute def test(): print "testing syntax" from xml.dom.html.HTMLAreaElement import HTMLAreaElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') p = doc.createElement('Area') print "testing get/set" testAttribute(p,'accessKey') testAttribute(p,'alt') testAttribute(p,'coords') testAttribute(p,'href') testAttribute(p,'target') testIntAttribute(p,'noHref') testIntAttribute(p,'tabIndex') p._set_shape('circle') rt = p._get_shape() if rt != 'Circle': error('get/set shape failed') print "get/sets work" if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_base.py0100644000076400001440000000070307413603007016735 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLBaseElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') b = doc.createElement('Base') print 'testing get/set attributes' testAttribute(b,'href') testAttribute(b,'target') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_basefont.py0100644000076400001440000000074007413603007017625 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLBaseFontElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') b = doc.createElement('BaseFont') print 'testing get/set' testAttribute(b,'color'); testAttribute(b,'face'); testAttribute(b,'size'); print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_blockquote.py0100644000076400001440000000064607413603007020201 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLQuoteElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') b = doc.createElement('BlockQuote'); print 'testing get/set' testAttribute(b,'cite'); print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_body.py0100644000076400001440000000107407413603007016762 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLBodyElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') b = doc.createElement('Body'); print 'testing get/set ' testAttribute(b,'aLink'); testAttribute(b,'background'); testAttribute(b,'bgColor'); testAttribute(b,'link'); testAttribute(b,'text'); testAttribute(b,'vLink'); print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_br.py0100644000076400001440000000075307413603007016433 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLBRElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') b = doc.createElement('BR'); print 'testing get/set' b._set_clear('left') rt = b._get_clear() if rt != 'Left': error('get/set clear failed') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_button.py0100644000076400001440000000106707413603007017342 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLButtonElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') b = doc.createElement('Button'); print 'testing get/set attributes' testAttribute(b,'accessKey'); testIntAttribute(b,'disabled'); testAttribute(b,'name'); testIntAttribute(b,'tabIndex'); testAttribute(b,'value'); print 'get/sets works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_caption.py0100644000076400001440000000077007413603007017464 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLTableCaptionElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') c = doc.createElement('Caption') print 'testing get/set' c._set_align('left') rt = c._get_align() if rt != 'Left': error('get/set align failed') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_col.py0100644000076400001440000000133007413603007016575 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLTableColElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') c = doc.createElement('COL'); print 'testing get/set' testAttribute(c,'ch'); testAttribute(c,'chOff'); testIntAttribute(c,'span'); testAttribute(c,'width'); c._set_align('left') rt = c._get_align() if rt != 'Left': error('get/set align failed') c._set_vAlign('top') rt = c._get_vAlign() if rt != 'Top': error('get/set vAlign failed') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_collection.py0100644000076400001440000000224307413603007020157 0ustar martinusersdef error(msg): raise 'ERROR: ' + msg def test(): from xml.dom import implementation print 'testing source code syntax' from xml.dom.html.HTMLCollection import HTMLCollection print '### implementation: ' + str(implementation) doc = implementation.createHTMLDocument('Title') hc = doc._get_images() if hc.length != 0: error('Initial Length wrong'); e = doc.createElement('IMG'); doc.documentElement.appendChild(e); hc = doc._get_images() print 'test item' if hc[0].nodeName != e.nodeName: error('item returns the worng value'); if hc.item(1) != None: error('item returns a value when it should be none') print 'item works' e.setAttribute('NAME','TEST') e.setAttribute('ID','1') print 'test namedItem' if hc.namedItem('TEST').nodeName != e.nodeName: error('namedItem did not find a named item') if hc.namedItem('1').nodeName != e.nodeName: error('namedItem did not find an IDed item') if hc.namedItem('TEST1') != None: error('namedItem found an item when one did not exist') print 'namedItem works'; if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_dir.py0100644000076400001440000000065007413603007016602 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLDirectoryElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') d = doc.createElement('Dir') print 'testing get/set' testIntAttribute(d, 'compact') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_div.py0100644000076400001440000000075607413603007016615 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLDivElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') d = doc.createElement('Div') print 'testing get/set' d._set_align('left') rt = d._get_align() if rt != 'Left': error('get/set of align failed') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_dl.py0100644000076400001440000000064607413603007016430 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLDListElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') d = doc.createElement('DL') print 'testing get and set' testIntAttribute(d,'compact') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_document.py0100644000076400001440000000657707413603007017660 0ustar martinusersfrom util import error from util import testAttribute CLONE_TEST_ENABLED = 0 def test(): print 'Testing Syntax' from xml.dom.html.HTMLDocument import HTMLDocument from xml.dom import implementation d = implementation.createHTMLDocument('') print 'testing title' if d._get_title() != '': error('getTitle failed with no title'); #This will test ADC d._set_title('TEST'); if d._get_title() != 'TEST': error('get/set title failed with body') #Print test replace of a child d._set_title('TEST2'); if d._get_title() != 'TEST2': error('replace a title failed') print 'title works' #d.removeChild(h); print 'testing documentElement' if d.documentElement == None: error('documentElement ADC failed'); print 'documentElement works' print 'testing body' if d._get_body() == None: error('body ADC failed'); b = d.createElement('BODY'); d._set_body(b) if d._get_body().nodeName != b.nodeName: error('body failed on replace'); print 'get/set Body works' print 'testing getImages' i = d.createElement('Img'); b.appendChild(i); hc = d._get_images() if hc.length != 1: error('getImages failed'); print 'getImages works' print 'getApplets' a = d.createElement('Applet'); o = d.createElement('Object'); o._set_code('TEST'); hc = d._get_applets() if hc.length != 0: error('getApplets failed with none'); b.appendChild(a); hc = d._get_applets(); if hc.length != 1: error('getApplets failed for applets'); b.appendChild(o) hc = d._get_applets() if hc.length != 2: error('getApplets failed for object'); print 'getApplets works' print 'testing getLinks' a1 = d.createElement('Area'); a1._set_href('TEST') a2 = d.createElement('A'); a2._set_href('TEST') if d._get_links().length != 0: error('getLinks failed with no Links'); b.appendChild(a1); if d._get_links().length != 1: error('getLinks failed with Area'); b.appendChild(a2); if d._get_links().length != 2: error('getLinks failed with Anchor'); print 'getLinks works' print 'testing getForms'; if d._get_forms().length != 0: error('getForms failed with no Forms'); f = d.createElement('FORM'); b.appendChild(f); if d._get_forms().length != 1: error('getForms failed with a form'); print 'getForms works' print 'testing getAnchors' if d._get_anchors().length != 0: error('get Anchors failed with none in there'); a2._set_name('TEST'); if d._get_anchors().length != 1: error('getAnchors failed with an Anchor'); print 'getAnchors works' testAttribute(d,'cookie'); if CLONE_TEST_ENABLED: print 'test cloneNode (deep)' d2 = d.cloneNode(1) if d2._get_referrer() != d._get_referrer(): error('cloneNode did not set referrer'); if d2._get_domain() != d._get_domain(): error('cloneNode did not set Domain'); if d2._get_URL() != d._get_URL(): error('cloneNode did not set URL'); if d2._get_cookie() != d._get_cookie(): error('cloneNode did not set cookie'); else: print "NOTE: DOCUMENT CLONE TEST SKIPPED" print 'cloneNode works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_element.py0100644000076400001440000000206407413603007017456 0ustar martinusersdef error(msg): raise 'ERROR: ' + msg def test(): print 'Testing Syntax' from util import testAttribute from util import testIntAttribute from xml.dom import implementation from xml.dom.html.HTMLElement import HTMLElement #Test with an HTML Element doc = implementation.createHTMLDocument('Title') e = doc.createElement('HTML'); print 'Testing get/set of attributes' e._set_id('1'); if e._get_id() != '1': error('get/set of ID failed'); e._set_title('TEST'); if e._get_title() != 'TEST': error('get/set of Title failed'); e._set_lang('EN'); if e._get_lang() != 'EN': error('get/set of lang failed'); e._set_dir('/src/'); if e._get_dir() != '/src/': error('get/set of dir failed'); e._set_className('class'); if e._get_className() != 'class': error('get/set of className failed'); print 'get/set of attributes works' print 'test cloneNode' e2 = e.cloneNode(0); print 'cloneNode works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_fieldset.py0100644000076400001440000000052307413603007017622 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLFieldSetElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') f = doc.createElement('FieldSet'); if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_font.py0100644000076400001440000000073107413603007016772 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLFontElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') f = doc.createElement('Font'); print 'testing get/set' testAttribute(f,'color'); testAttribute(f,'face'); testAttribute(f,'size'); print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_form.py0100644000076400001440000000157607413603007016777 0ustar martinusersfrom util import testAttribute, error def test(): print 'testing source code syntax' from xml.dom.html import HTMLFormElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') f = doc.createElement('Form') print 'testing get/set' testAttribute(f,'name') testAttribute(f,'acceptCharset') testAttribute(f,'action') testAttribute(f,'encType') testAttribute(f,'target') f._set_method("TEST") rt = f._get_method() if rt != "Test": error('get/set of method failed') print 'get/sets work' print 'test getElements' i = doc.createElement('IsIndex') f.appendChild(i) hc = f._get_elements() if hc.length != 1: error('getElements failed') if f._get_length() != 1: error('getLength failed') print 'getElements works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_frame.py0100644000076400001440000000143307413603007017116 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLFrameElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') f = doc.createElement('Frame') print 'testing get/set' testAttribute(f,'longDesc') testAttribute(f,'marginHeight') testAttribute(f,'marginWidth') testIntAttribute(f,'noResize') testAttribute(f,'src') f._set_frameBorder('left') rt = f._get_frameBorder() if rt != 'Left': error('get/set frameBorder failed') f._set_scrolling('auto') rt = f._get_scrolling() if rt != 'Auto': error('get/set scrolling failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_frameset.py0100644000076400001440000000067707413603007017643 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLFrameSetElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') f = doc.createElement('FrameSet') print 'testing get/set' testAttribute(f,'cols') testAttribute(f,'rows') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_h.py0100644000076400001440000000076207413603007016257 0ustar martinusersfrom util import testAttribute, error from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLHeadingElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') h = doc.createElement('H1') print 'testing get/set' h._set_align('left') rt = h._get_align() if rt != 'Left': error('get/set align failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_head.py0100644000076400001440000000104607413603007016725 0ustar martinusersdef error(msg): raise 'ERROR: ' + msg from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLHeadElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') h = doc.createElement('Head') print 'testing get/set profile' h._set_profile('PROFILE') if h._get_profile() != 'PROFILE': error('get/set profile failed') print 'get/set profile works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_hr.py0100644000076400001440000000110307413603007016427 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLHRElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') h = doc.createElement('HR') print 'testing get/set' h._set_align('left') rt = h._get_align() if rt != 'Left': error('get/set align failed') testIntAttribute(h,'noShade') testAttribute(h,'size') testAttribute(h,'width') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_html.py0100644000076400001440000000106507413603007016771 0ustar martinusersdef error(msg): raise 'ERROR: ' + msg def test(): print 'testing source code syntax' from xml.dom.html import HTMLHtmlElement from xml.dom import implementation from util import testAttribute from util import testIntAttribute doc = implementation.createHTMLDocument('Title') h = doc.createElement('html') print 'testing get/set version' h._set_version('VERSION') if h._get_version() != 'VERSION': error('get/set of version failed') print 'get/set version works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_html_dom_implementation.py0100644000076400001440000000071007413603007022731 0ustar martinusersdef error(msg): raise 'ERROR: ' + msg from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom import implementation doc = implementation.createHTMLDocument('Title') di = doc._get_implementation() doc2 = implementation.createHTMLDocument('The Title') import xml.dom.ext xml.dom.ext.PrettyPrint(doc2) return 1 if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_iframe.py0100644000076400001440000000167107413603007017273 0ustar martinusersfrom util import testAttribute, error from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLIFrameElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') f = doc.createElement('IFrame') print 'testing get/set' testAttribute(f,'height'); testAttribute(f,'longDesc'); testAttribute(f,'marginHeight'); testAttribute(f,'marginWidth'); testAttribute(f,'src'); testAttribute(f,'width'); f._set_align('left') rt = f._get_align() if rt != 'Left': error('get/set of align failed') f._set_frameBorder('left') rt = f._get_frameBorder() if rt != 'Left': error('get/set of frameBorder failed') f._set_scrolling('auto') rt = f._get_scrolling() if rt != 'Auto': error('get/set of scrolling failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_img.py0100644000076400001440000000146307413603007016603 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLImageElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') i = doc.createElement('IMG') print 'testing get/set' testAttribute(i,'lowSrc') testAttribute(i,'alt') testAttribute(i,'border') testAttribute(i,'height') testAttribute(i,'hspace') testIntAttribute(i,'isMap') testAttribute(i,'longDesc') testAttribute(i,'src') testAttribute(i,'useMap') testAttribute(i,'vspace') testAttribute(i,'width') i._set_align('left') rt = i._get_align() if rt != 'Left': error('get/set align failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_input.py0100644000076400001440000000353307413603010017160 0ustar martinusersfrom util import error from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLInputElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') f = doc.createElement('Form') text = doc.createElement('Input') text.setAttribute('TYPE','TEXT') radio = doc.createElement('Input') radio.setAttribute('TYPE','RADIO') image = doc.createElement('Input') image.setAttribute('TYPE','IMAGE') f.appendChild(text) f.appendChild(radio) f.appendChild(image) print 'testing generic get/set functions' testAttribute(text,'defaultValue') testAttribute(text,'accept') testAttribute(text,'accessKey') testAttribute(text,'alt') testAttribute(text,'name') testAttribute(text,'size') testAttribute(image,'src') testAttribute(text,'useMap') testAttribute(text,'value') text._set_align('left') rt = text._get_align() if rt != 'Left': error('get/set of align failed') if image._get_type() != 'Image': error('get of type failed') print 'get/set works' print 'testing int Attributes' testIntAttribute(radio,'defaultChecked'); testIntAttribute(radio,'checked'); testIntAttribute(radio,'disabled'); testIntAttribute(text,'maxLength'); testIntAttribute(text,'readOnly'); testIntAttribute(text,'tabIndex'); print 'Int get/sets work' print "testing cloneNode" i2 = radio.cloneNode(0); if i2._get_defaultChecked() != radio._get_defaultChecked(): error('cloneNode failed to copy defaultChecked') i3 = text.cloneNode(0) if i3._get_defaultValue() != text._get_defaultValue(): error('cloneNode failed to copy defaultValue') print 'cloneNode works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_isindex.py0100644000076400001440000000121307413603010017455 0ustar martinusersfrom util import error from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLIsIndexElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') i = doc.createElement('IsIndex') f = doc.createElement('Form') print 'testing get/set of Prompt' testAttribute(i,'prompt'); print 'get/set Prompt works' print 'testing getForm' f.appendChild(i) if i._get_form().nodeName != f.nodeName: error('getForm failed') print 'getForm works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_label.py0100644000076400001440000000071507413603010017077 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLLabelElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') l = doc.createElement('LABEL') print 'testing get/set attributes' testAttribute(l,'accessKey') testAttribute(l,'htmlFor') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_legend.py0100644000076400001440000000077207413603010017261 0ustar martinusersfrom util import testAttribute, error def test(): print 'testing source code syntax' from xml.dom.html import HTMLLegendElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') l = doc.createElement('LEGEND') print 'testing get/set' testAttribute(l,'accessKey') l._set_align('left') rt = l._get_align() if rt != 'Left': error('get/set of align failed') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_li.py0100644000076400001440000000067107413603010016425 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLLIElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') l = doc.createElement('LI') print 'testing get/set' testAttribute(l,'type') testIntAttribute(l,'value') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_link.py0100644000076400001440000000272007413603010016753 0ustar martinusersdef error(msg): raise 'ERROR: ' + msg def test(): from xml.dom import implementation doc = implementation.createHTMLDocument('Title') print 'Testing source code syntax' from xml.dom.html import HTMLLinkElement l = doc.createElement('LINK') print 'testing get/set of attributes' if l._get_disabled() != 0: error('get disabled failed for false'); l._set_disabled(0) if l._get_disabled() != 0: error('get disabled failed for false'); l._set_disabled(1); if l._get_disabled() != 1: error('get/set disabled failed for true'); l._set_charset('TEST'); if l._get_charset() != 'TEST': error('get/set failed for CharSet'); l._set_href('TEST'); if l._get_href() != 'TEST': error('get/set failed for href'); l._set_hreflang('EN'); if l._get_hreflang() != 'EN': error('get/set failed for hrefLang'); l._set_media('TEST'); if l._get_media() != 'TEST': error('get/set failed for MEDIA'); l._set_rel('TEST'); if l._get_rel() != 'TEST': error('get/set failed for REL'); l._set_rev('TEST'); if l._get_rev() != 'TEST': error('get/set failed for Rev'); l._set_target('TEST'); if l._get_target() != 'TEST': error('get/set failed for TARGET'); l._set_type('TEST'); if l._get_type() != 'TEST': error('get/set failed for TYPE') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_map.py0100644000076400001440000000104707413603010016574 0ustar martinusersfrom util import error from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLMapElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') m = doc.createElement('MAP') a = doc.createElement('AREA') print "testing get/set" m.appendChild(a); print "get Areas" as = m._get_areas() if as[0].nodeName != a.nodeName: error('getAreas failed') if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_menu.py0100644000076400001440000000064107413603010016762 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLMenuElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') m = doc.createElement('MENU') print 'testing get/set' testIntAttribute(m,'compact') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_meta.py0100644000076400001440000000100407413603010016736 0ustar martinusersfrom util import error from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLMetaElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') m = doc.createElement('META') print 'testing get/set of attributes' testAttribute(m,'content') testAttribute(m,'httpEquiv') testAttribute(m,'scheme') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_mod.py0100644000076400001440000000067107413603010016600 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLModElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') m = doc.createElement('ins') print 'testing get/set' testAttribute(m,'cite') testAttribute(m,'dateTime') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_object.py0100644000076400001440000000171007413603010017262 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLObjectElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') o = doc.createElement('OBJECT') print 'testing get/set' testAttribute(o,'code'); testAttribute(o,'archive'); testAttribute(o,'border'); testAttribute(o,'codeBase'); testAttribute(o,'codeType'); testAttribute(o,'data'); testIntAttribute(o,'declare'); testAttribute(o,'height'); testAttribute(o,'hspace'); testAttribute(o,'standby'); testIntAttribute(o,'tabIndex'); testAttribute(o,'type'); testAttribute(o,'useMap'); testAttribute(o,'vspace'); testAttribute(o,'width'); o._set_align('left') rt = o._get_align() if rt != 'Left': error('get/set align failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_ol.py0100644000076400001440000000074207413603010016432 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLOListElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') o = doc.createElement('OL') print 'testing get and set' testIntAttribute(o,'compact') testIntAttribute(o,'start') testAttribute(o,'type') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_optgroup.py0100644000076400001440000000143607413603010017700 0ustar martinusersfrom util import error from util import testAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLOptGroupElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') o = doc.createElement('OPTGROUP') print 'testing get/set disabled' if o._get_disabled() != 0: error('get disabled failed with nothing set') o._set_disabled(1) if o._get_disabled() != 1: error('get disabled failed when set to 1') o._set_disabled(0); if o._get_disabled() != 0: error('get/set disabled failed when set to 0') print 'get/set disabled works' print 'testing get/set label' testAttribute(o, 'label') print 'get/set label works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_option.py0100644000076400001440000000420607413603010017327 0ustar martinusersfrom util import error from util import testAttribute from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLOptionElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') o = doc.createElement('OPTION') f = doc.createElement('FORM') f.appendChild(o); print 'testing getForm' if o._get_form().nodeName != f.nodeName: error('getForm failed'); print 'getForm works' print 'testing get/set default selected' if o._get_defaultSelected() != 0: error('getDefaultSelected failed without setting it'); o._set_defaultSelected(1); if o._get_defaultSelected() != 1: error('get/setDefaultSelected failed when set to 1'); o._set_defaultSelected(0); if o._get_defaultSelected() != 0: error('get/set defaultSelected does not work when set to 0'); print 'get/set default selected works' print 'testing getText' t = doc.createTextNode('TEST') o.appendChild(t) if o._get_text() != 'TEST': error('getText failed') print 'getText works' print 'testing get index' if o._get_index() != -1: error('get/set index failed') s = doc.createElement('Select') s.add(o, None); if o._get_index() != 0: error('get Index failed for 1') print 'testing get/set disabled' if o._get_disabled() != 0: error('getDisabled failed with nothing set') o._set_disabled(1); if o._get_disabled() != 1: error('getDisabled failed when set to 1') o._set_disabled(0); if o._get_disabled() != 0: error('getdisabled failed when set to 0') print 'get/set disabled works' print 'testing get/set for label and value' testAttribute(o,'label') testAttribute(o,'value') print 'get/set works' print 'testing getSelected' #o.setSelected(1); #if o.getSelected() != 1: # error('getSelected failed'); print 'getselected works' print 'testing cloneNode' o2 = o.cloneNode(0) print 'cloneNode works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_p.py0100644000076400001440000000072207413603010016255 0ustar martinusersfrom util import testAttribute, error def test(): print 'testing source code syntax' from xml.dom.html import HTMLParagraphElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') p = doc.createElement('P') print 'testing get/set' p._set_align('left') rt = p._get_align() if rt != 'Left': error('get/set align failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_param.py0100644000076400001440000000105407413603010017115 0ustar martinusersfrom util import error from util import testAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLParamElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') p = doc.createElement('PARAM') print "testing get/set" testAttribute(p,'type') testAttribute(p,'value') p._set_valueType('object') rt = p._get_valueType() if rt != 'Object': error('get/set valueType failed') print "get/sets work" if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_pre.py0100644000076400001440000000057607413603010016613 0ustar martinusersfrom util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLPreElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') p = doc.createElement('PRE') print 'testing get/set' testIntAttribute(p,'width') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_q.py0100644000076400001440000000057007413603010016257 0ustar martinusersfrom util import testAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLQuoteElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') q = doc.createElement('Q') print 'testing get/set' testAttribute(q,'cite') print 'get/set works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_script.py0100644000076400001440000000103007413603010017313 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLScriptElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') s = doc.createElement('SCRIPT') print "testing get/set" testAttribute(s,'text') testAttribute(s,'charset') testAttribute(s,'src') testAttribute(s,'type') testIntAttribute(s,'defer') print "get/sets work" if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_section.py0100644000076400001440000000351307413603010017463 0ustar martinusersfrom util import testAttribute from util import error def test(): print 'testing source code syntax' from xml.dom.html import HTMLTableSectionElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') s = doc.createElement('TFOOT') #Row index and section row index tested in section print 'testing get/set' testAttribute(s,'ch') testAttribute(s,'chOff') s._set_align('left') rt = s._get_align() if rt != 'Left': error('get/set align failed') s._set_vAlign('Top') rt = s._get_vAlign() if rt != 'Top': error('get/set align failed') print 'get/set works' print 'testing insertRow,deleteRow, getRows, and TR.getRowSelectionIndex' try: r1 = s.insertRow(-1) error('insertRow(-1) does not raise exception'); except: pass r1 = s.insertRow(0) if r1 == None: error('insertRow(0) failed'); r2 = s.insertRow(1) if r2 == None: error('insertRow(1) failed'); if r2._get_sectionRowIndex() != 1: error('getSectionRowIndex Failed'); rows = s._get_rows() if rows._get_length() != 2: error('getRows failed') if rows.item(0).nodeName != r1.nodeName: error('getRows failed') if rows.item(1).nodeName != r2.nodeName: error('getRows failed') try: s.deleteRow(-1) error('deleteRow(-1) does not raise exception') except: pass s.deleteRow(1) if r2._get_rowIndex() != -1: error('deleted row still in tree') if s._get_rows()._get_length() != 1: error('deleteRow failed'); s.deleteRow(0) if s._get_rows()._get_length() != 0: error('deleteRow(0) failed') print 'insertRow, deleteRow, getRows, and TR.getSelectionRowIndex works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_select.py0100644000076400001440000000625707413603010017306 0ustar martinusersfrom util import error from util import testAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLSelectElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') s = doc.createElement('SELECT') o = doc.createElement('OPTION') o1 = doc.createElement('OPTION') print 'getType works' print 'testing get/set SelectedIndex' if s._get_selectedIndex() != -1: error('With none selected getSelectedIndex failed'); s.add(o,None) s.add(o1,o) s._set_selectedIndex(1) if s._get_selectedIndex() != 1: error('get/setSelected index fails when one is set'); print 'get/set selected index works' print 'testing getLength' if s._get_length() != 2: error('getLength fails'); print 'getLength works' print 'testing getOptions' os = s._get_options(); if os.item(0).nodeName != o1.nodeName: error('getOptions returns the wrong stuff') if os.item(1).nodeName != o.nodeName: error('getOptions does not return the correct stuff'); print 'getOptions works' print 'testing get/set disabled' if s._get_disabled() != 0: error('getDisabled failed when not set'); s._set_disabled(1) if s._get_disabled() != 1: error('get/set disabled failed when set'); s._set_disabled(0) if s._get_disabled() != 0: error('get/set disabled failed when not set'); print 'get/set disabled works' print 'testing get type' if s._get_type() != 'select-one': error('getType failed'); print 'testing get/set multiple' if s._get_multiple() != 0: error('getMultiple fails with nothing set'); s._set_multiple(1) if s._get_multiple() != 1: error('get/set multiple fails when set to 1'); s._set_multiple(0); if s._get_multiple() != 0: error('get/set multiple fails when set to 0'); print 'get/set multiple works' print 'test get/set name' testAttribute(s,'name'); print 'get/setName works' print 'testing get/set size' s._set_size(3) if s._get_size() != 3: error('get/setSize does not work'); print 'get/setSize works' print 'testing get/setTabIndex' s._set_tabIndex(3) if s._get_tabIndex() != 3: error('get/setTabIndex failed'); print 'get/setTabIndex works' print 'testing add' #This was already called if s.firstChild.nodeName != o1.nodeName: error('add does not work with 2 args'); if s.lastChild.nodeName != o.nodeName: error('add does not work with 1 arg'); print 'add works' print 'testing remove' s.remove(0); if s.firstChild.nodeName != o.nodeName: error('remove failed'); if s.lastChild.nodeName != o.nodeName: error('remove failed'); if s.firstChild._get_index() != 0: print s.firstChild.getIndex() error('reindex did not work on remove'); print 'remove works' print 'testing clone node' s1 = s.cloneNode(1); if s._get_selectedIndex() != s1._get_selectedIndex(): error('cloneNode did not copy Selected') print 'cloneNode Works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_style.py0100644000076400001440000000133007413603010017152 0ustar martinusersfrom util import error from util import testAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLStyleElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') s = doc.createElement('STYLE') print 'testing get/set of attributes' testAttribute(s,'media') testAttribute(s,'type') if s._get_disabled() != 0: error('getDisabled failed on false'); s._set_disabled(1); if s._get_disabled() != 1: error('getDisabled failed on true'); s._set_disabled(0); if s._get_disabled() != 0: error('getDisabled failed on false'); print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_table.py0100644000076400001440000000734407413603010017114 0ustar martinusersfrom util import testAttribute from util import testIntAttribute from util import error def test(): print 'testing source code syntax' from xml.dom.html import HTMLTableElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') t = doc.createElement('TABLE') print 'testing get/set' testAttribute(t,'bgColor'); testAttribute(t,'border'); testAttribute(t,'cellPadding'); testAttribute(t,'cellSpacing'); testAttribute(t,'summary'); testAttribute(t,'width'); t._set_align('left') rt = t._get_align() if rt != 'Left': error('get/set align failed') t._set_frame('border') rt = t._get_frame() if rt != 'Border': error('get/set frame failed') t._set_rules('all') rt = t._get_rules() if rt != 'All': error('get/set rules failed') print 'get/set works' print 'testing create and delete of THead' h = t.createTHead() h2 = t.createTHead() if t.childNodes.length != 1: error('create THead failed'); if h.nodeName != h2.nodeName: error('create a second THead fails'); t.deleteTHead() if t.childNodes.length != 0: error('deleteTHead fails') t.deleteTHead() print 'create and delete thead works' print 'testing create and delete TFoot' f = t.createTFoot() f2 = t.createTFoot() if t.childNodes.length != 1: error('create TFoot failed'); if f.nodeName != f2.nodeName: error('create a second TFoot fails'); t.deleteTFoot(); if t.childNodes.length != 0: error('deleteTFoot fails') t.deleteTFoot() print 'create and delete of tfoot works' print 'testing create and delete of caption' c = t.createCaption() c2 = t.createCaption() if t.childNodes.length != 1: error('create Caption failed'); if c.nodeName != c2.nodeName: error('second Create caption fails'); t.deleteCaption() if t.childNodes.length != 0: error('delete of Caption failed'); t.deleteCaption() print 'create and delete of caption works' print 'testing get Caption' c = t.createCaption() if t._get_caption().nodeName != c.nodeName: error('get caption failed'); print 'getCaption works' print 'testing getTHead' h = t.createTHead(); if t._get_tHead().nodeName != h.nodeName: error('get THead failed'); print 'getTHead works' print 'testing getTFoot' f = t.createTFoot(); if t._get_tFoot().nodeName != f.nodeName: error('get TFoot failed'); print 'getTFoot works' print 'testing getRows,insertRow, and deleteRow' if t._get_rows().length != 0: error('getRows failed'); r1 = t.insertRow(0); if t._get_rows().length != 1: error('getRows failed'); if t._get_rows()[0].nodeName != r1.nodeName: error('insertRow Failed') try: r2 = t.insertRow(10) error('insertRows(10) does not throw exception') except: pass try: r3 = t.insertRow(-1) error('insertRows(-1) does not throw exception') except: pass r2 = t.insertRow(1) if t._get_rows().length != 2: error('insertRows(11) failed'); t.deleteRow(0) if t._get_rows().length != 1: error('deleteRow failed'); if t._get_rows()[0].nodeName != r2.nodeName: error('deleteRow failed'); print 'insertRow, deleteRow, getRows works'; print 'testing getTBodies' if t._get_tBodies().length != 1: error('getTBodies'); print 'getTBodies works' print 'testing TR.getRowIndex' if r2._get_rowIndex() != 0: error('getRowIndex failed'); print 'TR.getRowIndex works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_td.py0100644000076400001440000000212407413603010016423 0ustar martinusersfrom util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLTableCellElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') c = doc.createElement('TD') print 'testing get/set' testAttribute(c,'abbr'); testAttribute(c,'axis'); testAttribute(c,'bgColor'); testAttribute(c,'ch'); testAttribute(c,'chOff'); testIntAttribute(c,'colSpan'); testAttribute(c,'headers'); testAttribute(c,'height'); testIntAttribute(c,'noWrap'); testIntAttribute(c,'rowSpan'); testAttribute(c,'width'); print 'get/set works' c._set_align('left') rt = c._get_align() if rt != 'Left': error('get/set align failed') c._set_vAlign('top') rt = c._get_vAlign() if rt != 'Top': error('get/set align failed') c._set_scope('colgroup') rt = c._get_scope() if rt != 'Colgroup': error('get/set align failed') #getCells is tested in the TR test file if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_textarea.py0100644000076400001440000000160107413603010017630 0ustar martinusersfrom util import error from util import testAttribute from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLTextAreaElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') t = doc.createElement('TEXTAREA') print 'testing get/set of attributes' testAttribute(t,'defaultValue'); testAttribute(t,'accessKey'); testIntAttribute(t,'cols'); testIntAttribute(t,'disabled'); testAttribute(t,'name'); testIntAttribute(t,'readonly'); testIntAttribute(t,'rows'); testIntAttribute(t,'tabIndex'); print 'get/set work' print 'testing clone node' t2 = t.cloneNode(1) if t2._get_defaultValue() != t._get_defaultValue(): error('cloneNode did not set the default value'); print 'cloneNode works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/test_title.py0100644000076400001440000000066707413603010017147 0ustar martinusersfrom util import error def test(): print 'testing source code syntax' from xml.dom.html import HTMLTitleElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') t = doc.createElement('TITLE') print 'test get/set text' t._set_text('TEST'); if t._get_text() != 'TEST': error('get/set text failed'); print 'text works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_tr.py0100644000076400001440000000321407413603010016442 0ustar martinusersfrom util import testAttribute from util import error def test(): print 'testing source code syntax' from xml.dom.html import HTMLTableRowElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') r = doc.createElement('TR') #Row index and section row index tested in section print 'testing get/set' testAttribute(r,'bgColor'); testAttribute(r,'ch'); testAttribute(r,'chOff'); r._set_align('left') rt = r._get_align() if rt != 'Left': error('get/set align failed') r._set_vAlign('top') rt = r._get_vAlign() if rt != 'Top': error('get/set align failed') print 'get/set works' print 'testing insertCell,deleteCell, getCells, and TD.cellIndex' try: c1 = r.insertCell(-1) error('insertCell(-1) does not raise exception') except: pass c1 = r.insertCell(0) if c1 == None: error('insertCell(0) failed'); try: c2 = r.insertCell(10) error('insertCell(10) does not raise exception') except: pass cells = r._get_cells() if cells._get_length() != 1: error('getCells failed'); if cells.item(0).nodeName != c1.nodeName: error('getCells failed'); try: r.deleteCell(-1); error('deleteCell(-1) does not raise exception'); except: pass r.deleteCell(0); if c1._get_cellIndex() != -1: error('deleted cell still in tree'); if r._get_cells().length != 0: error('deleteCell failed'); print 'insertCell, deleteCell, getCells, and TD.getCellIndex works' if __name__ == '__main__': test(); PyXML-0.8.2/test/dom/html/test_ul.py0100644000076400001440000000103207413603010016431 0ustar martinusersfrom util import testAttribute, error from util import testIntAttribute def test(): print 'testing source code syntax' from xml.dom.html import HTMLUListElement from xml.dom import implementation doc = implementation.createHTMLDocument('Title') u = doc.createElement('UL') print 'testing get/set' testIntAttribute(u,'compact') u._set_type('ordered') rt = u._get_type() if rt != 'Ordered': error('get/set of type failed') print 'get/set works' if __name__ == '__main__': test() PyXML-0.8.2/test/dom/html/util.py0100644000076400001440000000067507244341126015754 0ustar martinusersdef error(msg): raise Exception('ERROR: ' + msg) def testAttribute(elem, attr): setattr(elem, attr, 'TEST') if getattr(elem, attr) != 'TEST': error('get/set of %s failed' % attr) def testIntAttribute(elem, attr): setattr(elem, attr, 1) if getattr(elem, attr) != 1: error('get/set of %s failed' % attr) setattr(elem, attr, 0) if getattr(elem, attr) != 0: error('get/set of %s failed' % attr) PyXML-0.8.2/test/dom/TestSuite.py0100644000076400001440000001131707413603006015753 0ustar martinusersimport sys, traceback, os OK = 0 PASSED = 1 FAILED = -1 try: from xml.dom import EMPTY_NAMESPACE except ImportError: # For compatibility with older DOM implementations, it # may be necessary to set this to an empty string EMPTY_NAMESPACE = None class TestItem: def __init__(self, suite, title): self.suite = suite self.title = title self.messages = [] self.hasErrors = 0 self.hasWarnings = 0 if suite.useColor: #self.moveTo = '\033[%dG' % (suite.columns - 9) self.colorSuccess = '\033[1;32m' self.colorFailure = '\033[1;31m' self.colorWarning = '\033[1;33m' self.colorNormal = '\033[0;39m' else: self.colorSuccess = '' self.colorFailure = '' self.colorWarning = '' self.colorNormal = '' def finish(self): if self.hasErrors: msg = self._failure() retVal = FAILED elif self.hasWarnings: msg = self._passed() retVal = PASSED else: msg = self._success() retVal = OK spaces = self.suite.columns - 9 spaces = spaces - len(self.title) title = self.title + ' '*spaces + msg print title for msg in self.messages: print msg[0] return retVal def debug(self, msg): self.messages.append(msg) def message(self, msg): self.messages.append(msg) def warning(self, msg): self.messages.append(msg) self.hasWarnings = 1 def error(self, msg, saveTrace=0): if self.suite.stopOnError: raise msg if saveTrace: tb = sys.exc_info()[-1] ftb = traceback.format_list(traceback.extract_tb(tb)) if ftb: msg = msg + '\n' for t in ftb: msg = msg + t self.messages.append(msg) self.hasErrors = 1 ### Internal Methods ### def _success(self): return '[%s OK %s]' %(self.colorSuccess, self.colorNormal) def _passed(self): return '[%sPASSED%s]' %(self.colorWarning, self.colorNormal) def _failure(self): return '[%sFAILED%s]' %(self.colorFailure, self.colorNormal) class TestGroup: def __init__(self, suite, title=None): self.suite = suite self.title = title self.tests = [] self.retVal = OK if title: msg = '********** ' + title + ' **********' print msg ### Methods ### def finish(self): for test in self.tests: self.retVal = self.retVal or test.finish() return self.retVal def startTest(self, title): test = TestItem(self.suite, title) self.tests.append(test) def testDone(self): if self.tests: retVal = self.tests[-1].finish() del self.tests[-1] self.retVal = self.retVal or retVal return self.retVal class TestSuite: def __init__(self, stopOnError=1, useColor=0, cols=80): if os.name == 'posix': self.useColor = 1 else: self.useColor = useColor self.stopOnError = stopOnError self.columns = cols self.groups = [] self.retVal = OK def __del__(self): retVal = OK while len(self.groups): retVal = retVal or group[-1].finish() return retVal ### Methods ### def startGroup(self, title): group = TestGroup(self, title) self.groups.append(group) def groupDone(self): retVal = OK if self.groups: retVal = self.groups[-1].finish() del self.groups[-1] return retVal def startTest(self, title): if not self.groups: self.startGroup(self) print 'Added (null) group' self.groups[-1].startTest(title) def testDone(self): if self.groups: self.groups[-1].testDone() def testResults(self,expected,actual, done = 1, msg = ""): if expected != actual: if msg: msg = msg+":" self.error("%sExpected %s, got %s" % (msg,expected,actual)) return 0 elif done: self.testDone() return 1 def message(self, msg): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].message(msg) def warning(self, msg): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].warning(msg) def error(self, msg, saveTrace=0): if self.groups: if self.groups[-1].tests: self.groups[-1].tests[-1].error(msg, saveTrace) PyXML-0.8.2/test/dom/newtest_node.py0100644000076400001440000002142207413603006016516 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE from xml.dom import DOMException from xml.dom import HIERARCHY_REQUEST_ERR from xml.dom import WRONG_DOCUMENT_ERR from xml.dom import NOT_FOUND_ERR from Ft.Lib import TestSuite class NodeTestCase(TestSuite.TestCase): def create(self): from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) #We cannot use just plain old nodes, we need to use Elements self.pNode = doc.createElement('PARENT') self.nodes = [] for ctr in range(3): n = doc.createElement('Child %d' % ctr) self.nodes.append(n); def testSyntax(self): from xml.dom import Node from xml.dom.Node import Node def testNodeName(self): if self.pNode.nodeName != 'PARENT': raise TestSuiteError('error getting nodeName') def testNodeValue(self): self.pNode.nodeValue = 'NODE_VALUE' if self.pNode.nodeValue != 'NODE_VALUE': raise TestSuiteError('error with get/set nodeVaLue') def testNodeType(self): if self.pNode.nodeType != Node.ELEMENT_NODE: raise TestSuiteError('error getting nodeType') def test(FIXME): test = group.newTest("Testing attributes") if p.nodeName != 'PARENT': test.error("Error getting NodeName"); p.nodeValue = 'NodeValue'; if p.nodeValue != 'NodeValue': test.error('Error getting/setting NodeValue'); if p.nodeType != Node.ELEMENT_NODE: test.error('Error getting NodeType'); if p.parentNode != None: test.error('Error getting parentNode'); p._4dom_setParentNode(None) if p.firstChild != None: test.error('Error getting FirstChild'); if p.lastChild != None: test.error('Error getting Last Child'); if p.nextSibling != None: test.error('Error getting Next Sibling'); if p.previousSibling != None: test.error('Error getting Previous Sibling'); if p.attributes == None: test.error('Error getting attributes'); if p.ownerDocument.nodeName != doc.nodeName: test.error('Error getting ownerDocument'); if p.namespaceURI != '': test.error('Error namespaceURI') if p.prefix != '': test.error('Error Prefix') if p.localName != p.nodeName: test.error('Error localName') group.newTest("Testing insertBefore()") if p.insertBefore(nodes[0],None).nodeName != nodes[0].nodeName: test.error("Error inserting"); if p.firstChild.nodeName != nodes[0].nodeName: test.error("Error insert failed"); if p.lastChild.nodeName != nodes[0].nodeName: test.error("Error insert failed"); if p.insertBefore(nodes[1],nodes[0]).nodeName != nodes[1].nodeName: test.error("Error inserting"); if p.firstChild.nodeName != nodes[1].nodeName: test.error("Error insert failed"); if p.lastChild.nodeName != nodes[0].nodeName: test.error("Error insert failed"); if nodes[0].nextSibling != None: test.error("Error insert failed"); if nodes[0].previousSibling.nodeName != nodes[1].nodeName: test.error("Error insert failed"); if nodes[1].nextSibling.nodeName != nodes[0].nodeName: test.error("Error insert failed"); if nodes[1].previousSibling != None: test.error("Error insert failed"); if p.removeChild(nodes[1]).nodeName != nodes[1].nodeName: test.error("Error Removing") if p.firstChild.nodeName != nodes[0].nodeName: test.error("Error Remove Failed") if p.lastChild.nodeName != nodes[0].nodeName: test.error("Error RemoveFailed") if nodes[1].nextSibling != None: test.error("Error Remove Failed"); if nodes[1].previousSibling != None: test.error("Error Remove Failed"); if nodes[0].nextSibling != None: test.error("Error Remove Failed"); if nodes[0].previousSibling != None: test.error("Error Remove Failed"); try: p.insertBefore(nodes[2],nodes[1]); except DOMException, e: if e.code != NOT_FOUND_ERR: raise e group.newTest("Testing replaceChild") if p.replaceChild(nodes[1], nodes[0]).nodeName != nodes[0].nodeName: test.error("ReplaceChild Does not work") if p.firstChild.nodeName != nodes[1].nodeName: test.error("ReplaceChild Does not work") if p.lastChild.nodeName != nodes[1].nodeName: test.error("ReplaceChild Does not work") if nodes[1].nextSibling != None: test.error("ReplaceChild Does not work") if nodes[1].previousSibling != None: test.error("ReplaceChild Does not work") if nodes[0].nextSibling != None: test.error("ReplaceChild Does not work") if nodes[0].previousSibling != None: test.error("ReplaceChild Does not work") try: p.replaceChild(nodes[0],nodes[0] ) except DOMException, e: if e.code != NOT_FOUND_ERR: raise e; group.newTest("Testing removeChild") try: p.removeChild(nodes[0]); except DOMException, e: if e.code != NOT_FOUND_ERR: raise e if p.removeChild(nodes[1]).nodeName != nodes[1].nodeName: test.error("Error Remove Failed"); if p.firstChild != None: test.error("Error Remove Failed"); if p.lastChild != None: test.error("Error Remove Failed"); if nodes[1].nextSibling != None: test.error("Error Remove Fialed"); if nodes[1].previousSibling != None: test.error("Error Remove Failed"); group.newTest("Testing appendChild") if p.appendChild(nodes[0]).nodeName != nodes[0].nodeName: test.error("Error Append Failed"); if nodes[0].parentNode.nodeName != p.nodeName: test.error('AppendChild faild to set parent'); if p.firstChild.nodeName != nodes[0].nodeName: test.error("Error Append Failed"); if p.lastChild.nodeName != nodes[0].nodeName: test.error("Error Append Failed"); if nodes[0].nextSibling!= None: test.error("Error Append Failed"); if nodes[0].previousSibling != None: test.error("Error Append Failed") group.newTest("Testing hasChildNodes") if not p.hasChildNodes(): test.error("Error hasChildNodes"); p.removeChild(nodes[0]); if p.hasChildNodes(): test.error("Error hasChildNodes") group.newTest("Testing supports") if nodes[1].supports('XML','') != 1: test.error("Supports failed") group.newTest('Testing normalize()') e = doc.createElement('TEST'); e1 = doc.createElement('TAG3') t1 = doc.createTextNode('String1'); t2 = doc.createTextNode(' String2'); t3 = doc.createTextNode(' String 3'); t4 = doc.createTextNode(' String 4'); e.appendChild(t1); e.appendChild(t2); e.appendChild(t3); e.appendChild(e1); e.appendChild(t4); e.normalize(); if e.childNodes.length != 3: test.error('Normalize did not work'); group.newTest("Testing cloneNode") p.appendChild(nodes[0]) #Shallow copy '''p1 = Node.cloneNode(p,0); if p1.nodeName != p.nodeName: test.error("CloneNode Failed Node Name"); if p1.nodeValue != p.nodeValue: test.error("CloneNode Failed Node Value") if p1._get_nodeType() != p._get_nodeType(): test.error("CloneNode Failed Node Type") if p1.ownerDocument.nodeName != p.ownerDocument.nodeName: test.error("CloneNode Failed Owner Document") if p1.firstChild == p.firstChild: test.error("CloneNode Failed FirstChild") if p1.lastChild == p.lastChild: test.error("CloneNode Failed LastChild") print "Shallow Copy works" #Deep copy p2 = Node.cloneNode(p,1); #Verify the same number of different children if p2.getChildNodes().getLength() != p.getChildNodes().getLength(): test.error("CloneNode Failed"); if p2.getChildNodes().item(0) == p.getChildNodes().item(0): test.error("CloneNode Failed"); print "Deep Copy works"''' return 1 if __name__ == '__main__': from Ft.Lib import TestSuite testSuite = TestSuite.TestSuite(4, None, 0, 1) test(testSuite) PyXML-0.8.2/test/dom/test.py0100644000076400001440000001041007413603006014772 0ustar martinusers#!/usr/bin/env python import string, time import TestSuite ### Methods ### def runTests(tests, testSuite): banner = 'Performing a test of DOM Core/Traversal/HTML' markers = '#'*((testSuite.columns - len(banner)) / 2 - 1) print markers, banner, markers total = 0.0 for test in tests: module = __import__('test_' + string.lower(test)) start = time.time() module.test(testSuite) total = total + time.time() - start return total ### Application ### if __name__ == '__main__': logLevel = 1 logFile = None haltOnError = 1 test_list = ['Node', 'NodeList', 'NamedNodeMap', 'NodeIterator', 'TreeWalker', 'Attr', 'Element', 'DocumentFragment', 'Document', 'DOMImplementation', 'CharacterData', 'Comment', 'Text', 'CDATASection', 'DocumentType', 'Entity', 'EntityReference', 'Notation', 'ProcessingInstruction', 'Range', 'Struct', 'HTML', #'Demo', #'Pythonic' ] import sys, os, getopt prog_name = os.path.split(sys.argv[0])[1] short_opts = 'hl:nqtv:' long_opts = ['help', 'log=', 'no-error' 'tests' 'quiet', 'verbose=' ] usage = '''Usage: %s [options] [[all] [test]...] Options: -h, --help Print this message and exit -l, --log Write output to a log file (default=%s) -n, --no-error Continue testing if error condition -q, --quiet Display as little as possible -t, --tests Show a list of tests that can be run -v, --verbose Set the output level (default=%s) 0 - display nothing 1 - errors only (same as --quiet) 2 - warnings and errors 3 - information, warnings and errors 4 - display everything ''' %(prog_name, logFile, logLevel) command_line_error = 0 bad_options = [] finished = 0 args = sys.argv[1:] while not finished: try: optlist, args = getopt.getopt(args, short_opts, long_opts) except getopt.error, data: bad_options.append(string.split(data)[1]) args.remove(bad_options[-1]) command_line_error = 1 else: finished = 1 display_usage = 0 display_tests = 0 for op in optlist: if op[0] == '-h' or op[0] == '--help': display_usage = 1 elif op[0] == "-l" or op[0] == '--log': logFile = op[1] elif op[0] == '-n' or op[0] == '--no-error': haltOnError = 0 elif op[0] == '-t' or op[0] == '--tests': display_tests = 1 elif op[0] == '-q' or op[0] == '--quiet': logLevel = 1 elif op[0] == '-v' or op[0] == '--verbose': logLevel = int(op[1]) all_tests = 0 if args: lower_test = [] for test in test_list: lower_test.append(string.lower(test)) for test in args: if string.lower(test) == 'all': all_tests = 1 break if string.lower(test) not in lower_test: print "%s: Test not found '%s'" %(prog_name, test) args.remove(test) display_tests = 1 if len(args) and not all_tests: tests = args elif not display_tests: tests = test_list if command_line_error or display_usage or display_tests: for op in bad_options: print "%s: Unrecognized option '%s'" %(prog_name,op) if display_usage: print usage if display_tests: print 'Available tests are:' for t in test_list: print ' %s' % t sys.exit(command_line_error) testSuite = TestSuite.TestSuite(haltOnError) total = runTests(tests, testSuite) print "Test Time - %.3f secs" % total PyXML-0.8.2/test/dom/test_attr.py0100644000076400001440000000313507413603006016032 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('Attr') tester.startTest('Checking syntax') try: from xml.dom import Attr from xml.dom.Attr import Attr except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') try: from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) except: tester.error('Error creating document') a = doc.createAttribute('TestNode'); e = doc.createElement('TestElement') tester.testDone() tester.startTest('Testing attributes') if a.name != 'TestNode': tester.error("name failed") if a.specified != 0: tester.error("specified failed") a.value = 'Test Value' if a.value != 'Test Value': tester.error("Error getting/seeting value") if a.specified != 1: tester.error("Assigning to value does not set specified") tester.testDone() tester.startTest('Testing cloneNode()') #Should always be done deep a1 = a.cloneNode(1) if a1.value != a.value: tester.error("cloneNode fails on value") if a1.name != a.name: tester.error("cloneNode fails on name") if a1.specified != a.specified: tester.error("cloneNode fails on specified") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_cdatasection.py0100644000076400001440000000203007406420550017515 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('CDATASection') tester.startTest('Testing syntax') try: from xml.dom import CDATASection from xml.dom.CDATASection import CDATASection except: tester.tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) cds = doc.createCDATASection("This is a CDATA Section") cds.data="This is a CDATA Section" tester.testDone() tester.startTest('Testing cloneNode()') #Should always be done deep cds1 = cds.cloneNode(1) if cds1.data != cds.data: tester.error("cloneNode does not copy data") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_characterdata.py0100644000076400001440000001005307413603006017643 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE from xml.dom import INDEX_SIZE_ERR from xml.dom import DOMException from xml.dom import implementation def get_exception_name(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name def test(tester): tester.startGroup('CharacterData') tester.startTest('Checking syntax') try: from xml.dom import CharacterData from xml.dom.CharacterData import CharacterData except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) #shouldn't try to instantiate a CharacterData node, so test it through Text t1 = doc.createTextNode("") t2 = doc.createTextNode('SUBSTRING') t3 = doc.createTextNode('APPEND') t4 = doc.createTextNode('INSERT') t5 = doc.createTextNode('DELETE') t6 = doc.createTextNode('TEST') tester.testDone() tester.startTest('Testing attributes') t1.data = 'TEST'; if t1.data != 'TEST': tester.error('Get/set data doesn\'t match') if t1.length != 4: tester.error('length returned wrong size') tester.testDone() tester.startTest('Testing substringData()') if t2.substringData(1,2) != 'UB': tester.error('substringData returns wrong section') if t2.substringData(5,100) != 'RING': tester.error('substringData fails on oversized \'count\'') try: t2.substringData(100,2) except DOMException, x: if x.code != INDEX_SIZE_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected INDEX_SIZE_ERR" % name) else: tester.error('substringData doesn\'t catch an invalid index') tester.testDone() tester.startTest('Testing appendData()') t3.appendData(' TEST') if t3.data != 'APPEND TEST': tester.error('appendData does not append') tester.testDone() tester.startTest('Testing insertData()') t4.insertData(2,'here') if t4.data != 'INhereSERT': tester.error('insertData did not properly insert'); try: t4.insertData(100,'TEST'); except DOMException, x: if x.code != INDEX_SIZE_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected INDEX_SIZE_ERR" % name) else: tester.error('insertData doesn\'t catch an invalid index') tester.testDone() tester.startTest('Testing deleteData()') # DELETE t5.deleteData(2,2) if t5.data != 'DETE': tester.error('deleteData did not properly get rid of the data') t5.deleteData(2,10) if t5.data != 'DE': tester.error('deleteData fails on oversized \'count\'') try: t5.deleteData(100,3); except DOMException, x: if x.code != INDEX_SIZE_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected INDEX_SIZE_ERR" % name) else: tester.error('deleteData doesn\'t catch an invalid index') tester.testDone() tester.startTest('Testing replaceData()') # REPLACE t6.replaceData(0,1,'CH') if t6.data != 'CHEST': tester.error('replaceData did not properly replace') t6.replaceData(3,7,'ESE') if t6.data != 'CHEESE': tester.error('replaceData did not properly replace') try: t6.replaceData(100,3,'Not Gonna Happen'); except DOMException, x: if x.code != INDEX_SIZE_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected INDEX_SIZE_ERR" % name) else: tester.error('replaceData doesn\'t catch an invalid index') tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_comment.py0100644000076400001440000000162107406420550016523 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('Comment') tester.startTest('Testing syntax') try: from xml.dom import Comment from xml.dom.Comment import Comment except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) c = doc.createComment("Comment") tester.testDone() tester.startTest('Test cloneNode()') c1 = c.cloneNode(1) if c1.data != c.data: tester.error("cloneNode does not copy data") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_demo.py0100644000076400001440000000162007413603006016001 0ustar martinusers#!/usr/bin/env python import os def test(testSuite): #rt = os.system("cd ../demo && python dom_from_html_file.py employee_table.html") #if rt: # return 0 rt = os.system("cd ../demo && python dom_from_xml_file.py addr_book1.xml") if rt: return 0 #os.system("cd ../demo && python generate_html1.py") #if rt: # return 0 rt = os.system("cd ../demo && python iterator1.py addr_book1.xml") if rt: return 0 rt = os.system("cd ../demo && python visitor1.py addr_book1.xml") if rt: return 0 rt = os.system("cd ../demo && python trace_ns.py book_catalog1.xml") if rt: return 0 rt = os.system("cd ../demo && python xll_replace.py addr_book1.xml") if rt: return 0 rt = os.system("cd ../demo && python xpointer_query.py root\(\).child\(1\) addr_book1.xml") if rt: return 0 return 1 PyXML-0.8.2/test/dom/test_document.py0100644000076400001440000003036507406420550016706 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('Document') tester.startTest('Checking syntax') try: from xml.dom import Document from xml.dom.Document import Document except: tester.error('Error in syntax' ,1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation from xml.dom import DOMException from xml.dom import INVALID_CHARACTER_ERR from xml.dom import NOT_SUPPORTED_ERR from xml.dom import HIERARCHY_REQUEST_ERR dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,None,dt); tester.testDone() tester.startTest('Testing ownerDocument') if doc.ownerDocument.nodeName != doc.nodeName: tester.error('ownerDocument failed') tester.testDone() tester.startTest('Testing createElement()') e = doc.createElement('ELEMENT') if e.ownerDocument.nodeName != doc.nodeName: tester.error('createElement does not set ownerDocument') if e.tagName != 'ELEMENT': tester.error('createElement does not set tagName') try: e2 = doc.createElement('BAD
    ' e1.appendChild(e2) e.appendChild(e1) e.appendChild(e3) doc.appendChild(e) nl = doc.getElementsByTagName('ELEMENT'); if nl.length != 1: tester.error('getElementsByTagName does not return root element') nl = doc.getElementsByTagName('SUB2') if nl.length != 2: tester.error('getElementsByTagName failed to search the tree') nl = doc.getElementsByTagName('*'); if nl.length != 4: tester.error('getElementsByTagName does not get all elements'); tester.testDone() tester.startTest('Testing cloneNode()') doc2 = doc.cloneNode(1) ret = RecursiveCompare(doc.documentElement, doc2.documentElement) if ret[0]: tester.error('cloneNode '+ret[1]) tester.testDone() tester.startTest('Testing importNode()') imp = doc2.importNode(e,1) if imp.parentNode != None: tester.error('importNode did not reset parentNode') if imp.ownerDocument != doc2: tester.error('importNode did not set ownerDocument') tester.testDone() tester.startTest('Testing appendChild() with a DocumentFragment') c1 = doc.createComment('C1') c2 = doc.createComment('C2') c3 = doc.createComment('C3') c4 = doc.createComment('C4') df.appendChild(c1) df.appendChild(c2) df.appendChild(c3) doc.appendChild(df) if df.childNodes.length != 0: tester.error('Appending does not remove all the children') if doc.childNodes.length != 5: tester.error('Appending does not add all the children') tester.testDone() tester.startTest('Testing insertBefore() with a DocumentFragment') doc.removeChild(c3) doc.removeChild(c2) df.appendChild(c2) df.appendChild(c3) df.appendChild(c4) doc.insertBefore(df,c1) if doc.childNodes[2].data != c2.data: tester.error('insertBefore failed to place children in proper order') if doc.lastChild.data != c1.data: tester.error('insertbefore failed to place children in proper order') if doc.childNodes.length != 6: tester.error('insertBefore failed to add all of the children') tester.testDone() tester.startTest('Testing replaceChild() with a DocumentFragment') doc.removeChild(c1) doc.removeChild(c2) doc.removeChild(c3) df.appendChild(c1) df.appendChild(c2) df.appendChild(c3) doc.replaceChild(df,c4) if doc.childNodes.length != 5: tester.error('replaceChild does not add all the children') if doc.childNodes[2].data != c1.data: tester.error('replaceChild failed to place children in proper order') if doc.lastChild.data != c3.data: tester.error('replaceChild failed to place children in proper order') tester.testDone() tester.startTest('Testing overridden appendChild()') e.removeChild(e1) e.removeChild(e3) e1.removeChild(e2) try: doc.appendChild(e1) except DOMException, data: if data.code != HIERARCHY_REQUEST_ERR: tester.error('appendChild throws wrong exception') else: tester.error('appendChild allows two elements') tester.testDone() tester.startTest('Testing overridden insertBefore()') try: doc.insertBefore(e1,e) except DOMException, data: if data.code != HIERARCHY_REQUEST_ERR: print data tester.error('insertBefore throws wrong exception') else: tester.error('insertBefore allows two elements') tester.testDone() tester.startTest('Testing overridden replaceChild()') doc.replaceChild(e1,e) if doc.documentElement.nodeName != e1.nodeName: tester.error('replaceChild did not set documentElement correctly'); try: doc.replaceChild(e,c1) except DOMException, data: if data.code != HIERARCHY_REQUEST_ERR: tester.error('replaceChild throws wrong exception') else: tester.error('replaceChild allows two elements') tester.testDone() tester.startTest('Testing createElementNS()') e = doc.createElementNS('www.fourthought.com','ft:ns') if e.nodeName != 'ft:ns': tester.error('createElementNS does not set nodeName') if e.tagName != 'ft:ns': tester.error('createElementNS does not set tagName') if e.namespaceURI != 'www.fourthought.com': tester.error('createElementNS does not set namespaceURI') if e.prefix != 'ft': tester.error('createElementNS does not set prefix') if e.localName != 'ns': tester.error('createElementNS does not set localName') tester.testDone() tester.startTest('Testing createAttributeNS()') a = doc.createAttributeNS('www.fourthought.com','ft:ans') e.setAttributeNodeNS(a) if a.nodeName != 'ft:ans': tester.error('createAttributeNS does not set nodeName') if a.name != 'ft:ans': tester.error('createAttributeNS does not set name') if a.namespaceURI != 'www.fourthought.com': tester.error('createAttributeNS does not set namespaceURI') if a.prefix != 'ft': tester.error('createAttributeNS does not set prefix') if a.localName != 'ans': tester.error('createAttributeNS does not set localName') tester.testDone() tester.startTest('Testing getElementsByTagNameNS()') e1 = doc.createElementNS('www.fourthought.com','ft:ns1') e2 = doc.createElementNS('www.fourthought.com','ft:ns2') e3 = doc.createElementNS('www.fourthought.com','ft:ns2') # XML string '' e1.appendChild(e2) e.appendChild(e1) e.appendChild(e3) doc.documentElement.appendChild(e) nl = doc.getElementsByTagNameNS('www.fourthought.com','ns') if nl.length != 1: tester.error('getElementsByTagNameNS does not return root element') nl = doc.getElementsByTagNameNS('www.fourthought.com','ns2') if nl.length != 2: tester.error('getElementsByTagNameNS failed to search the tree') nl = doc.getElementsByTagName('*'); if nl.length != 5: tester.error('getElementsByTagNameNS does not get all elements'); tester.testDone() return 1 def RecursiveCompare(old, new): if old.nodeName != new.nodeName: return (1, 'did not copy names') if old.nodeValue != new.nodeValue: return (1, 'did not copy values') if old.ownerDocument == new.ownerDocument: return (1, 'did not change ownerDocument') if old.childNodes.length != new.childNodes.length: return (1, 'did not copy all children') for i in range(old.childNodes.length): ret = RecursiveCompare(old.childNodes[i], new.childNodes[i]) if ret[0]: return ret return (0, 'passed') if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_documentfragment.py0100644000076400001440000000155407406420550020430 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('DocumentFragment') tester.startTest('Testing syntax') try: from xml.dom import DocumentFragment from xml.dom.DocumentFragment import DocumentFragment except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) df = doc.createDocumentFragment() tester.testDone() tester.startTest('Testing cloneNode()') df1 = df.cloneNode(1) tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_documenttype.py0100644000076400001440000000301407166146226017607 0ustar martinusersdef test(tester): tester.startGroup('DocumentType') tester.startTest('Testing syntax') try: from xml.dom import DocumentType from xml.dom.DocumentType import DocumentType except: tester.tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('TEST','PublicID','SystemID') tester.testDone() tester.startTest('Testing attributes') if dt.name != 'TEST': tester.error('name is incorrect') if dt.publicId != 'PublicID': tester.error('publicId is incorrect') if dt.systemId != 'SystemID': tester.error('systemId is incorrect') tester.testDone() tester.startTest('Testing cloneNode()') #Should always be done deep dt1 = dt.cloneNode(1) if dt1.name != dt.name: tester.error("cloneNode failed on name") if dt1.entities.length != dt.entities.length: tester.error("cloneNode did not copy all entities") if dt1.notations.length != dt.notations.length: tester.error("cloneNode did not copy all notations") if dt1.publicId != dt.publicId: tester.error("cloneNode fails on publicId") if dt1.systemId != dt.systemId: tester.error("cloneNode fails on systemId") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_domimplementation.py0100644000076400001440000000347607406420550020620 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('DOMImplementation') tester.startTest('Checking syntax') try: from xml.dom import DOMImplementation from xml.dom.DOMImplementation import DOMImplementation except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation di = implementation tester.testDone() tester.startTest('Testing hasFeature()') if di.hasFeature('XML', '2.0') == 0: tester.error('hasFeature does not get feature with version'); if di.hasFeature('XML', '') == 0: tester.error('hasFeature does not get feature (any version)'); tester.testDone() tester.startTest('Testing createDocumentType()') dt = di.createDocumentType('NAME','PUBLICID','SYSTEMID') if dt.nodeName != 'NAME': tester.error('createDocumnent does not set qualifiedName properly') if dt.publicId != 'PUBLICID': tester.error('createDocumnent does not set namespaceURI properly') if dt.systemId != 'SYSTEMID': tester.error('createDocumnent does not set doctype properly') tester.testDone() tester.startTest('Testing createDocument()') doc = di.createDocument(EMPTY_NAMESPACE,'NAME',dt) if doc.namespaceURI != None: tester.error('createDocumnent does not set namespaceURI properly') if doc.documentElement.nodeName != 'NAME': tester.error('createDocumnent does not set qualifiedName properly') if doc.doctype != dt: tester.error('createDocumnent does not set doctype properly') tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_element.py0100644000076400001440000002177707413603006016525 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def get_exception_name(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name def test(tester): tester.startGroup('Element') tester.startTest('Testing syntax') try: from xml.dom import Element from xml.dom.Element import Element except: tester.tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import DOMException from xml.dom import INVALID_CHARACTER_ERR from xml.dom import WRONG_DOCUMENT_ERR from xml.dom import INUSE_ATTRIBUTE_ERR from xml.dom import NOT_FOUND_ERR from xml.dom import NO_MODIFICATION_ALLOWED_ERR from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) doc_nons = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) ns = 'www.fourthought.com' e_ns = doc.createElementNS(ns, 'TEST') e = doc.createElement('TEST') tester.testDone() tester.startTest('Testing attributes') if e.tagName != 'TEST': tester.error("tagName failed") try: e.tagName = "test" except DOMException, exc: if exc.code != NO_MODIFICATION_ALLOWED_ERR: tester.error('Wrong exception on read-only violation') tester.testDone() tester.startTest('Testing setAttribute()') if e.setAttribute('Attr1','Value 1') != None: tester.error('setAttribvute returns a value') if e.attributes.length != 1: tester.error('setAttribute did not add the attribute') e.setAttribute('Attr1','Value 2'); if e.attributes.length != 1: tester.error('setAttribute did not replace the attribute') try: e.setAttribute('A','Value3') except DOMException , x: if x.code != INVALID_CHARACTER_ERR: tester.error('Wrong exception on illegal character: %s' % str(x.code)) else: tester.error('setAttributeNS allowed illegal characters') tester.testDone() tester.startTest('Testing getAttributeNS()') if e.getAttributeNS('www.fourthought.com','Attr1') != 'Value 2': tester.error('getAttributeNS returned the worng string') if e.getAttributeNS('www.fourthought.com','Attr2') != '': tester.error('getAttributeNS returns value for non-existant attribute') tester.testDone() tester.startTest('Testing hasAttributeNS()') if not e.hasAttributeNS('www.fourthought.com','Attr1'): tester.error('hasAttributeNS didn\'t find the attribute') if e.hasAttributeNS('www.fourthought.com','Attr2'): tester.error('hasAttributeNS found a non-existant attribute') tester.testDone() tester.startTest('Testing removeAttributeNS()') if e.removeAttributeNS('www.fourthought.com','Attr1') != None: tester.error('removeAttributeNS returns something') if e.attributes.length != 0: tester.error('removeAttributeNS did not remove it') tester.testDone() tester.startTest('Testing setAttributeNodeNS()') attr = doc.createAttributeNS('www.fourthought.com','ft:ns1') attr.value = 'TEST' if e.setAttributeNodeNS(attr) != None: tester.error('setAttributeNodeNS returns a value') attr1 = doc.createAttributeNS('www.fourthought.com','ft:ns1') if e.setAttributeNodeNS(attr1).nodeName != attr.nodeName: tester.error('setAttributeNS does not return the replaced value') tester.testDone() tester.startTest('Testing getAttributeNodeNS()') if e.getAttributeNodeNS('www.fourthought.com', 'ns1').nodeName != attr1.nodeName: tester.error('getAttributeNodeNS does not return the correct value') if e.getAttributeNodeNS('www.fourthought.com','ns2') != None: tester.error('getAttributeNodeNS returns a value when it shouldn;t') tester.testDone() tester.startTest('Testing getElementsByTagNameNS()') eNs = doc.createElementNS('www.fourthought.com','ft:ns') e.appendChild(eNs) rt = e.getElementsByTagNameNS('www.fourthought.com','ns') if len(rt) != 1: tester.error('failed with specified namespace and localName') rt = e.getElementsByTagNameNS('www.fourthought.com','*') if len(rt) != 1: tester.error('failed with specified namespace and * localName') rt = e.getElementsByTagNameNS('*','ns') if len(rt) != 1: print rt tester.error('failed with * namespace and specified localName') rt = e.getElementsByTagNameNS('*','*') if len(rt) != 5: print rt tester.error('failed with * namespace and localName') tester.testDone() tester.startTest('Testing ext.ReleaseNode()') from xml.dom import ext ext.ReleaseNode(e) if e.childNodes.length != 0: tester.error('ReleaseNode did not remove from parent') if e5.parentNode != None: tester.error('ReleaseNode did not set parent to None') tester.testDone() tester.startTest('Test cloneNode()') e.setAttribute('ATT1','VALUE 1') e6 = e.cloneNode(1) if e.attributes.length != e6.attributes.length: tester.error("cloneNode didn't do the right number of attributes") a1 = e.attributes.item(0) a2 = e6.attributes.item(0) if a1.name != a2.name: tester.error('cloneNode did not copy the attribute names') if a1.value != a2.value: tester.error('cloneNode did not copy the attribute values') tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_entity.py0100644000076400001440000000242007406420550016373 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('Entity') tester.startTest('Testing syntax') try: from xml.dom import Entity from xml.dom.Entity import Entity except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) ent = doc._4dom_createEntity("-//FOURTHOUGHT//EN", "/tmp/entity", "") tester.testDone() tester.startTest('Testing attributes') if ent.publicId != '-//FOURTHOUGHT//EN': tester.error('publicId is incorrect') if ent.systemId != '/tmp/entity': tester.error('systemId is incorrect') tester.testDone() tester.startTest('Test cloneNode()') ent1 = ent.cloneNode(1) if ent1.publicId != ent.publicId: tester.error("cloneNode fails on publicId") if ent1.systemId != ent.systemId: tester.error("cloneNode fails on systemId") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_entityreference.py0100644000076400001440000000170707410647353020270 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('EntityReference') tester.startTest('Testing syntax') try: from xml.dom import EntityReference from xml.dom.EntityReference import EntityReference except: tester.error('Error in syntax',1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) entr = doc.createEntityReference("TestEntity") tester.testDone() tester.startTest('Test cloneNode()') entr1 = entr.cloneNode(1) if entr1.nodeName != entr.nodeName: tester.error("cloneNode failed") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_html.py0100644000076400001440000000133607244341126016031 0ustar martinusersdef test(tester): import os, string, sys if not os.path.exists('html/test.py'): tester.error('Cannot run the HTML test suite') return 1 currdir = os.getcwd() os.chdir('html') files = __import__('test').fileList for file in files: modName = 'test_%s' % string.lower(file) if sys.modules.has_key(modName): del sys.modules[modName] tester.startGroup('HTML %s' % file) module = __import__('test_%s' % string.lower(file)) module.test() tester.groupDone() os.chdir(currdir) return if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_namednodemap.py0100644000076400001440000000721107413603006017507 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def get_exception_name(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name def test(tester): tester.startGroup('NamedNodeMap') tester.startTest('Checking syntax') try: from xml.dom import NamedNodeMap from xml.dom.NamedNodeMap import NamedNodeMap except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest("Creating test environment") nodes = [] from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) try: for ctr in range(3): n = doc.createElement('Node%d'%(ctr+1)) nodes.append(n) except: tester.error("Unable to create test nodes") nm = doc.createElement('TEST').attributes tester.testDone() tester.startTest("Testing setNamedItem()") if nm.setNamedItem(nodes[0]) != None: tester.error("setNamedItem failed") if nm.length != 1: tester.error("setNamedItem failed") nodes[2] = doc.createElement('Node1') if nm.setNamedItem(nodes[2]).nodeName != nodes[0].nodeName: tester.error("setNamedItem failed on replace") if nm.length != 1: tester.error("setNamedItem failed") tester.testDone() tester.startTest("Testing getNamedItem()") if nm.getNamedItem(nodes[2].nodeName).nodeName != nodes[2].nodeName: tester.error("getNamedItem returns wrong Node") if nm.getNamedItem(nodes[1].nodeName) != None: tester.error("getNamedItem returns a Node instead of null") tester.testDone() tester.startTest("Testing removeNamedItem()") nodes[0] = doc.createElement("NewNode1") nm.setNamedItem(nodes[0]); if nm.length != 2: tester.error("setNamedItem failed") if nm.removeNamedItem(nodes[0].nodeName).nodeName != nodes[0].nodeName: tester.error("removeNamedItem failed") if nm.length != 1: tester.error("removeNamedItem failed") from xml.dom import DOMException from xml.dom import NOT_FOUND_ERR try: nm.removeNamedItem(nodes[0].nodeName) except DOMException, err: if err.code != NOT_FOUND_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected NOT_FOUND_ERR" % name) if nm.length != 1: tester.error("removeNamedItem failed") tester.testDone() tester.startTest("Testing item()") if nm.item(0).nodeName != nodes[2].nodeName: tester.error("item failed") if nm.item(1) != None: tester.error("item failed") tester.testDone() tester.startTest("Testing setNamedItemNS()") node = doc.createElementNS('www.fourthought.com', 'ft:Node4') if nm.setNamedItemNS(node) != None: tester.error('setNamedItemNS returns a value; should be (null)') tester.testDone() tester.startTest("Testing getNamedItemNS()") if nm.getNamedItemNS('www.fourthought.com', 'Node4').nodeName != node.nodeName: tester.error("getNamedItemNS failed") tester.testDone() tester.startTest("Testing removeNamedItemNS()") if nm.removeNamedItemNS('www.fourthought.com', 'Node4').nodeName != node.nodeName: tester.error("removeNamedItemNS failed") if nm.length != 1: tester.error("removeNamedItemNS failed") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite testSuite = TestSuite.TestSuite() retVal = test(testSuite) sys.exit(retVal) PyXML-0.8.2/test/dom/test_node.py0100644000076400001440000002103407413603007016004 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE from xml.dom import DOMException from xml.dom import HIERARCHY_REQUEST_ERR from xml.dom import WRONG_DOCUMENT_ERR from xml.dom import NOT_FOUND_ERR def get_exception_name(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name def test(tester): tester.startGroup('Node') tester.startTest('Testing syntax') try: from xml.dom import Node from xml.dom.FtNode import FtNode except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating the test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt); # We cannot use just plain old nodes, we need to use Elements p = doc.createElement('PARENT') nodes = [] for ctr in range(3): n = doc.createElement('Child%d' % ctr) nodes.append(n) tester.testDone() tester.startTest("Testing attributes") if p.nodeName != 'PARENT': tester.error("Error getting nodeName"); p.nodeValue = 'NodeValue'; if p.nodeValue != 'NodeValue': tester.error('Error getting/setting nodeValue'); if p.nodeType != Node.ELEMENT_NODE: tester.error('Error getting nodeType'); if p.parentNode != None: tester.error('Error getting parentNode'); p._4dom_setParentNode(None) if p.firstChild != None: tester.error('Error getting firstChild'); if p.lastChild != None: tester.error('Error getting lastChild'); if p.nextSibling != None: tester.error('Error getting nextSibling'); if p.previousSibling != None: tester.error('Error getting previousSibling'); if p.attributes == None: tester.error('Error getting attributes'); if p.ownerDocument.nodeName != doc.nodeName: tester.error('Error getting ownerDocument'); if p.namespaceURI != None: tester.error('Error getting namespaceURI') if p.prefix != None: tester.error('Error getting') if p.localName != None: tester.error('Error getting localName') tester.testDone() tester.startTest("Testing insertBefore()") if p.insertBefore(nodes[0],None).nodeName != nodes[0].nodeName: tester.error("Error inserting"); if p.firstChild.nodeName != nodes[0].nodeName: tester.error("Error insert failed"); if p.lastChild.nodeName != nodes[0].nodeName: tester.error("Error insert failed"); if p.insertBefore(nodes[1],nodes[0]).nodeName != nodes[1].nodeName: tester.error("Error inserting"); if p.firstChild.nodeName != nodes[1].nodeName: tester.error("Error insert failed"); if p.lastChild.nodeName != nodes[0].nodeName: tester.error("Error insert failed"); if nodes[0].nextSibling != None: tester.error("Error insert failed"); if nodes[0].previousSibling.nodeName != nodes[1].nodeName: tester.error("Error insert failed"); if nodes[1].nextSibling.nodeName != nodes[0].nodeName: tester.error("Error insert failed"); if nodes[1].previousSibling != None: tester.error("Error insert failed"); if p.removeChild(nodes[1]).nodeName != nodes[1].nodeName: tester.error("Error Removing") if p.firstChild.nodeName != nodes[0].nodeName: tester.error("Error Remove Failed") if p.lastChild.nodeName != nodes[0].nodeName: tester.error("Error RemoveFailed") if nodes[1].nextSibling != None: tester.error("Error Remove Failed"); if nodes[1].previousSibling != None: tester.error("Error Remove Failed"); if nodes[0].nextSibling != None: tester.error("Error Remove Failed"); if nodes[0].previousSibling != None: tester.error("Error Remove Failed"); try: p.insertBefore(nodes[2],nodes[1]); except DOMException, x: if x.code != NOT_FOUND_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected NOT_FOUND_ERR" % name) tester.testDone() tester.startTest("Testing replaceChild") if p.replaceChild(nodes[1], nodes[0]).nodeName != nodes[0].nodeName: tester.error("ReplaceChild Does not work") if p.firstChild.nodeName != nodes[1].nodeName: tester.error("ReplaceChild Does not work") if p.lastChild.nodeName != nodes[1].nodeName: tester.error("ReplaceChild Does not work") if nodes[1].nextSibling != None: tester.error("ReplaceChild Does not work") if nodes[1].previousSibling != None: tester.error("ReplaceChild Does not work") if nodes[0].nextSibling != None: tester.error("ReplaceChild Does not work") if nodes[0].previousSibling != None: tester.error("ReplaceChild Does not work") try: p.replaceChild(nodes[0],nodes[0] ) except DOMException, x: if x.code != NOT_FOUND_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected NOT_FOUND_ERR" % name) tester.testDone() tester.startTest("Testing removeChild") try: p.removeChild(nodes[0]); except DOMException, x: if x.code != NOT_FOUND_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected NOT_FOUND_ERR" % name) if p.removeChild(nodes[1]).nodeName != nodes[1].nodeName: tester.error("Error Remove Failed"); if p.firstChild != None: tester.error("Error Remove Failed"); if p.lastChild != None: tester.error("Error Remove Failed"); if nodes[1].nextSibling != None: tester.error("Error Remove Fialed"); if nodes[1].previousSibling != None: tester.error("Error Remove Failed"); tester.testDone() tester.startTest("Testing appendChild()") if p.appendChild(nodes[0]).nodeName != nodes[0].nodeName: tester.error("Error Append Failed"); if nodes[0].parentNode.nodeName != p.nodeName: tester.error('AppendChild faild to set parent'); if p.firstChild.nodeName != nodes[0].nodeName: tester.error("Error Append Failed"); if p.lastChild.nodeName != nodes[0].nodeName: tester.error("Error Append Failed"); if nodes[0].nextSibling!= None: tester.error("Error Append Failed"); if nodes[0].previousSibling != None: tester.error("Error Append Failed") tester.testDone() tester.startTest("Testing hasChildNodes()") if not p.hasChildNodes(): tester.error("Error hasChildNodes"); p.removeChild(nodes[0]); if p.hasChildNodes(): tester.error("Error hasChildNodes") tester.testDone() tester.startTest("Testing supports()") if nodes[1].supports('XML','') != 1: tester.error("Supports failed") tester.testDone() tester.startTest('Testing normalize()') e = doc.createElement('TEST'); e1 = doc.createElement('TAG3') t1 = doc.createTextNode('String1'); t2 = doc.createTextNode(' String2'); t3 = doc.createTextNode(' String 3'); t4 = doc.createTextNode(' String 4'); e.appendChild(t1); e.appendChild(t2); e.appendChild(t3); e.appendChild(e1); e.appendChild(t4); e.normalize(); if e.childNodes.length != 3: tester.error('Normalize did not work'); tester.testDone() tester.startTest("Testing cloneNode() [single]") p1 = e.cloneNode(0) if p1.nodeName != e.nodeName: tester.error("cloneNode failed on nodeName") if p1.nodeValue != e.nodeValue: tester.error("cloneNode failed on nodeValue") if p1.nodeType != e.nodeType: tester.error("cloneNode failed on nodeType") if p1.ownerDocument.nodeName != e.ownerDocument.nodeName: tester.error("cloneNode failed on ownerDocument") tester.testDone() tester.startTest("Testing cloneNode() [deep]") p2 = e.cloneNode(1) #Verify the same number of different children if p2.childNodes.length != e.childNodes.length: tester.error("cloneNode didn\'t copy all of the nodes"); if p2.firstChild == e.firstChild: tester.error("cloneNode failed on firstChild") if p2.lastChild == e.lastChild: tester.error("cloneNode failed on lastChild") if p2.childNodes.item(1) == e.childNodes.item(1): tester.error("cloneNode has the same children"); tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite(1, 1) retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_nodeiterator.py0100644000076400001440000000355707413603007017570 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('NodeIterator') tester.startTest('Checking syntax') try: from xml.dom import NodeIterator from xml.dom.NodeIterator import NodeIterator except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation doc = implementation.createDocument(EMPTY_NAMESPACE,None,None); #xml_string = '' try: a = doc.createElement('a') b = doc.createElement('b') c = doc.createElement('c') d = doc.createElement('d') e = doc.createElement('e') f = doc.createElement('f') g = doc.createElement('g') except: tester.error('Couldn\'t create elements') try: b.appendChild(c) b.appendChild(d) a.appendChild(b) e.appendChild(f) e.appendChild(g) a.appendChild(e) doc.appendChild(a) except: tester.error('Counl\'t append to DOM tree') from xml.dom.NodeFilter import NodeFilter nit = doc.createNodeIterator(doc, NodeFilter.SHOW_ELEMENT, None,1) tester.testDone() tester.startTest('Iterating forward') curr_node = nit.nextNode() while curr_node: curr_node = nit.nextNode() tester.testDone() tester.startTest('Iterating in reverse') curr_node = nit.previousNode() while curr_node: curr_node = nit.previousNode() tester.testDone() tester.startTest('Iterating forward again') curr_node = nit.nextNode() while curr_node: curr_node = nit.nextNode() tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_nodelist.py0100644000076400001440000000412507413603007016702 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE from xml.dom import DOMException from xml.dom import NO_MODIFICATION_ALLOWED_ERR def get_exception_name(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name def test(tester): tester.startGroup('NodeList') tester.startTest('Checking syntax') try: from xml.dom import NodeList from xml.dom.NodeList import NodeList except: tester.error('Error in syntax',1) tester.testDone() tester.startTest('Creating the test environment') try: from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) except: tester.error('Error creating document') nodes = [] try: for ctr in range(3): nodes.append(doc.createElement('Node%d' %ctr)) except: tester.error("Error creating nodes") e = doc.createElement('PARENT') try: for n in nodes: e.appendChild(n) except: tester.error('Error appending nodes') nl = e.childNodes tester.testDone() tester.startTest("Testing attributes") if nl.length != 3: tester.error('length reports wrong amount') try: nl.length = 5 except DOMException, x: if x.code != NO_MODIFICATION_ALLOWED_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected NOMODIFICATION_ALLOWED_ERR" % name) else: tester.error('length not read-only') tester.testDone() tester.startTest("Testing item()") if nl.item(0).nodeName != nodes[0].nodeName: tester.error("Item returns wrong item") if nl.item(3) != None: tester.error("Item returns something on invalid index") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_notation.py0100644000076400001440000000246307406420550016721 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('Notation') tester.startTest('Testing syntax') try: from xml.dom import Notation from xml.dom.Notation import Notation except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) nota = doc._4dom_createNotation("-//FOURTHOUGHT//EN", "/tmp/notation", "TestNotation") tester.testDone() tester.startTest('Testing attributes') if nota.publicId != '-//FOURTHOUGHT//EN': tester.error('publicId is incorrect') if nota.systemId != '/tmp/notation': tester.error('systemId is incorrect') tester.testDone() tester.startTest('Test cloneNode()') nota1 = nota.cloneNode(1) if nota1.publicId != nota.publicId: tester.error("cloneNode fails on publicId") if nota1.systemId != nota.systemId: tester.error("cloneNode fails on systemId") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_processinginstruction.py0100644000076400001440000000242207406420550021537 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('ProcessingInstruction') tester.startTest('Testing syntax') try: from xml.dom import ProcessingInstruction from xml.dom.ProcessingInstruction import ProcessingInstruction except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) pi = doc.createProcessingInstruction("xml", 'version = "1.0"') tester.testDone() tester.startTest('Testing attributes') if pi.target != 'xml': tester.error('Problems with target') if pi.data != 'version = "1.0"': tester.error('Problems with data') tester.testDone() tester.startTest('Test cloneNode()') pi1 = pi.cloneNode(1) if pi1.target != pi.target: tester.error("cloneNode fails on target") if pi1.data != pi.data: tester.error("cloneNode fails on data") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_pythonic.py0100644000076400001440000000513507406420550016722 0ustar martinusers#!/usr/bin/env python from TestSuite import EMPTY_NAMESPACE def test(tester): tester.startGroup('Python Representation') tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) c = doc.createComment("Comment") tester.testDone() tester.startTest('Test Attribute') a = doc.createAttribute('ATTR_NAME') a.value = 'ATTR_VALUE' tester.message(str(a)) tester.testDone() tester.startTest('Testing CDATASection') c1 = doc.createCDATASection('Short String') tester.message(str(c1)) c2 = doc.createCDATASection('This is a much longer string, over 20 characters') tester.message(str(c2)) tester.testDone() tester.startTest('Testing Comment') c1 = doc.createComment('Short Comment') tester.message(str(c1)) c2 = doc.createComment('This is a much longer comment, over 20 characters') tester.message(str(c2)) tester.testDone() tester.startTest('Testing Document') tester.message(str(doc)) tester.testDone() tester.startTest('Testing Document Fragment') df = doc.createDocumentFragment() tester.message(str(df)) tester.testDone() tester.startTest('Testing Element') e = doc.createElement('ELEMENT') tester.message(str(e)) tester.testDone() tester.startTest('Testing Entity') e = doc._4dom_createEntity("ID1","ID2","NAME") tester.message(str(e)) tester.testDone() tester.startTest('Testing Entity Reference') e = doc.createEntityReference('E-Ref') tester.message(str(e)) tester.testDone() tester.startTest('Testing NamedNodeMap') nnm = implementation._4dom_createNamedNodeMap() tester.message(str(nnm)) tester.testDone() tester.startTest('Testing NodeList') nl = implementation._4dom_createNodeList([e]) tester.message(str(nl)) tester.testDone() tester.startTest('Testing Notation') n = doc._4dom_createNotation("ID1","ID2","NAME") tester.message(str(n)) tester.testDone() tester.startTest('Testing ProcessingInstruction') p = doc.createProcessingInstruction('This-is-a-long-target', 'short data') tester.message(str(p)) tester.testDone() tester.startTest('Testing Text') t = doc.createTextNode('This is a very long text string') tester.message(str(t)) tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_range.py0100644000076400001440000005137107413603007016162 0ustar martinusersTEST_FILE = '../../demo/dom/addr_book1.xml' from xml.dom.ext.reader import PyExpat from xml.dom import Node from xml.dom import Range def ReadDoc(): #Read in a doc r = PyExpat.Reader() global doc global ADDRBOOK global ENTRIES global PA global PA_NAME global PA_ADDR global PA_WORK global PA_FAX global PA_PAGER global PA_EMAIL global EN global EN_NAME global EN_ADDR global EN_WORK global EN_FAX global EN_PAGER global EN_EMAIL global VZ doc = r.fromUri(TEST_FILE) ADDRBOOK = doc.documentElement elementType = lambda n, nt=Node.ELEMENT_NODE: n.nodeType == nt ENTRIES = filter(elementType, ADDRBOOK.childNodes) PA = ENTRIES[0] children = filter(elementType, PA.childNodes) PA_NAME = children[0] PA_ADDR = children[1] PA_WORK = children[2] PA_FAX = children[3] PA_PAGER = children[4] PA_EMAIL = children[5] EN = ENTRIES[2] children = filter(elementType, EN.childNodes) EN_NAME = children[0] EN_ADDR = children[1] EN_WORK = children[2] EN_FAX = children[3] EN_PAGER = children[4] EN_EMAIL = children[5] VZ = ENTRIES[3] def test(tester=None): if tester is None: import TestSuite tester = TestSuite.TestSuite(1,1) tester.startGroup('DOM Level II Ranges') tester.startTest('Creating test environment') ReadDoc() tester.testDone() tester.startTest("Compare Positions") range = doc.createRange() #CASE 1 tester.testResults(Range.Range.POSITION_EQUAL,range._Range__comparePositions(ADDRBOOK,0,ADDRBOOK,0),done=0) tester.testResults(Range.Range.POSITION_LESS_THAN,range._Range__comparePositions(ADDRBOOK,0,ADDRBOOK,1),done=0) tester.testResults(Range.Range.POSITION_GREATER_THAN,range._Range__comparePositions(ADDRBOOK,1,ADDRBOOK,0),done=0) #CASE 2 tester.testResults(Range.Range.POSITION_LESS_THAN,range._Range__comparePositions(ADDRBOOK,0,EN,1),done=0,msg = 'CASE 2 #1') tester.testResults(Range.Range.POSITION_LESS_THAN,range._Range__comparePositions(ADDRBOOK,5,EN,1),done=0,msg = 'CASE 2 #2') tester.testResults(Range.Range.POSITION_GREATER_THAN,range._Range__comparePositions(ADDRBOOK,6,EN,1),done=0,msg = 'CASE 2 #3') #CASE 3 tester.testResults(Range.Range.POSITION_GREATER_THAN,range._Range__comparePositions(EN,1,ADDRBOOK,0),done=0,msg = 'CASE 3 #1') tester.testResults(Range.Range.POSITION_GREATER_THAN,range._Range__comparePositions(EN,1,ADDRBOOK,5),done=0,msg = 'CASE 3 #2') tester.testResults(Range.Range.POSITION_LESS_THAN,range._Range__comparePositions(EN,1,ADDRBOOK,6),done=0,msg = 'CASE 3 #3') #CASE 4 tester.testResults(Range.Range.POSITION_LESS_THAN,range._Range__comparePositions(PA,0,EN_NAME,0),done=0,msg = 'CASE 4 #1') tester.testResults(Range.Range.POSITION_GREATER_THAN,range._Range__comparePositions(EN,0,PA_NAME,0),done=0,msg = 'CASE 4 #2') #TEst with one as doc tester.testResults(Range.Range.POSITION_LESS_THAN,range._Range__comparePositions(doc,0,EN_NAME,0),done=0,msg = 'w/doc') tester.testDone() tester.startTest("Range.setStart") range.setStart(PA,1) tester.testResults(PA,range.startContainer,done=0,msg='setStart 1') tester.testResults(1,range.startOffset,done=0,msg='setStart 2') tester.testResults(PA,range.endContainer,done=0,msg='setStart 3') tester.testResults(1,range.endOffset,done=0,msg='setStart 4') tester.testResults(PA,range.commonAncestorContainer,done=0,msg='setStart 5') tester.testResults(1,range.collapsed,done=0,msg='collapsed') tester.testDone() tester.startTest("Range.setEnd") range.setEnd(PA_NAME,1) tester.testResults(PA,range.startContainer,done=0,msg='setEnd 1') tester.testResults(1,range.startOffset,done=0,msg='setEnd 2') tester.testResults(PA_NAME,range.endContainer,done=0,msg='setEnd 3') tester.testResults(1,range.endOffset,done=0,msg='setEnd 4') tester.testResults(PA,range.commonAncestorContainer,done=0,msg='setEnd 5') tester.testResults(0,range.collapsed,done=0,msg='collapsed') range.setEnd(EN_NAME,1) tester.testResults(PA,range.startContainer,done=0,msg='setEnd 6') tester.testResults(1,range.startOffset,done=0,msg='setEnd 7') tester.testResults(EN_NAME,range.endContainer,done=0,msg='setEnd 8') tester.testResults(1,range.endOffset,done=0,msg='setEnd 9') tester.testResults(ADDRBOOK,range.commonAncestorContainer,done=0,msg='setEnd 10') tester.testResults(0,range.collapsed,done=0,msg='collapsed') range.setEnd(doc,0) tester.testResults(doc,range.startContainer,done=0,msg='setEnd 11') tester.testResults(0,range.startOffset,done=0,msg='setEnd 12') tester.testResults(doc,range.endContainer,done=0,msg='setEnd 13') tester.testResults(0,range.endOffset,done=0,msg='setEnd 14') tester.testResults(doc,range.commonAncestorContainer,done=0,msg='setEnd 15') tester.testResults(1,range.collapsed,done=0,msg='collapsed') tester.testDone() tester.startTest("Range.startAfter") range.setEnd(EN_NAME,1) range.setStartAfter(EN) tester.testResults(ADDRBOOK,range.startContainer,done=0,msg='startAfter 1') tester.testResults(6,range.startOffset,done=0,msg='startAfter 2') tester.testResults(ADDRBOOK,range.commonAncestorContainer,done=0,msg='startAfter 3') tester.testDone() tester.startTest("Range.startBefore") range.setEnd(EN_NAME,1) range.setStartBefore(EN) tester.testResults(ADDRBOOK,range.startContainer,done=0,msg='startBefore 1') tester.testResults(5,range.startOffset,done=0,msg='startBefore 2') tester.testResults(ADDRBOOK,range.commonAncestorContainer,done=0,msg='startBefore 3') tester.testDone() tester.startTest("Range.endAfter") range.setStart(ADDRBOOK,0) range.setEndAfter(EN_NAME) tester.testResults(EN,range.endContainer,done=0,msg='endAfter 1') tester.testResults(2,range.endOffset,done=0,msg='endAfter 2') tester.testResults(ADDRBOOK,range.commonAncestorContainer,done=0,msg='endAfter 3') tester.testDone() tester.startTest("Range.endBefore") range.setStart(ADDRBOOK,0) range.setEndBefore(EN_NAME) tester.testResults(EN,range.endContainer,done=0,msg='endBefore 1') tester.testResults(1,range.endOffset,done=0,msg='endBefore 2') tester.testResults(ADDRBOOK,range.commonAncestorContainer,done=0,msg='endBefore 3') tester.testDone() tester.startTest("Range.collapse") range.setStart(ADDRBOOK,0) range.setEndBefore(EN_NAME) range.collapse(1) tester.testResults(ADDRBOOK,range.startContainer,done=0,msg='collapse 1') tester.testResults(0,range.startOffset,done=0,msg='collapse 2') tester.testResults(ADDRBOOK,range.endContainer,done=0,msg='collapse 3') tester.testResults(0,range.endOffset,done=0,msg='collapse 4') range.setStart(ADDRBOOK,0) range.setEndBefore(EN_NAME) range.collapse(0) tester.testResults(EN,range.startContainer,done=0,msg='collapse 5') tester.testResults(1,range.startOffset,done=0,msg='collapse 6') tester.testResults(EN,range.endContainer,done=0,msg='collapse 7') tester.testResults(1,range.endOffset,done=0,msg='collapse 8') tester.testDone() tester.startTest("Range.selectNode") range.selectNode(EN) tester.testResults(ADDRBOOK,range.startContainer,done=0,msg='selectNode 1') tester.testResults(5,range.startOffset,done=0,msg='selectNode 2') tester.testResults(ADDRBOOK,range.endContainer,done=0,msg='selectNode 3') tester.testResults(6,range.endOffset,done=0,msg='selectNode 4') tester.testDone() tester.startTest("Range.selectNodeContents") range.selectNodeContents(EN) tester.testResults(EN,range.startContainer,done=0,msg='selectNodeContents 1') tester.testResults(0,range.startOffset,done=0,msg='selectNodeContents 2') tester.testResults(EN,range.endContainer,done=0,msg='selectNodeContents 3') tester.testResults(13,range.endOffset,done=0,msg='selectNodeContents 4') tester.testDone() tester.startTest("Range.compareBoundaryPoints") range.selectNodeContents(EN) r2 = doc.createRange() r2.selectNode(PA) tester.testResults(1,range.compareBoundaryPoints(range.START_TO_START,r2),done=0,msg='compareBoundaryPoints 1') tester.testResults(1,range.compareBoundaryPoints(range.START_TO_END,r2),done=0,msg='compareBoundaryPoints 2') tester.testResults(1,range.compareBoundaryPoints(range.END_TO_START,r2),done=0,msg='compareBoundaryPoints 3') tester.testResults(1,range.compareBoundaryPoints(range.END_TO_END,r2),done=0,msg='compareBoundaryPoints 4') tester.testDone() tester.startTest("Range.deleteContents") range.setStart(EN_NAME.firstChild,2) range.setEnd(EN_NAME.firstChild,11) range.deleteContents() tester.testResults('Emsi',EN_NAME.firstChild.data,done=0,msg='deleteContents 1') ReadDoc() range = doc.createRange() range.setStart(EN,2) range.setEnd(EN,12) range.deleteContents() tester.testResults(2,len(EN.childNodes),done=0,msg='deleteContents 2') tester.testResults(EN_NAME,EN.childNodes[1],done=0,msg='deleteContents 3') #Start is the ancestor ReadDoc() range = doc.createRange() range.setStart(ADDRBOOK,0) range.setEnd(EN_PAGER,1) range.deleteContents() tester.testResults(4,len(ADDRBOOK.childNodes),done=0,msg='deleteContents 4') tester.testResults(4,len(EN.childNodes),done=0,msg='deleteContents 5') tester.testResults(EN_PAGER,EN.childNodes[0],done=0,msg='deleteContents 6') tester.testResults(None,EN.childNodes[0].firstChild,done=0,msg='deleteContents 7') #End is the acnestor ReadDoc() range = doc.createRange() range.setStart(PA_NAME,0) range.setEnd(ADDRBOOK,4) range.deleteContents() tester.testResults(6,len(ADDRBOOK.childNodes),done=0,msg='deleteContents 18') tester.testResults(2,len(PA.childNodes),done=0,msg='deleteContents 19') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='deleteContents 20') tester.testResults(None,PA.childNodes[1].firstChild,done=0,msg='deleteContents 21') #Text to text deep ancestor ReadDoc() range = doc.createRange() range.setStart(PA_NAME.firstChild,2) range.setEnd(EN_PAGER.firstChild,4) range.deleteContents() tester.testResults(2,len(PA.childNodes),done=0,msg='deleteContents 2') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='deleteContents 3') tester.testResults(6,len(ADDRBOOK.childNodes),done=0,msg='deleteContents 4') tester.testResults(4,len(EN.childNodes),done=0,msg='deleteContents 5') tester.testResults(EN_PAGER,EN.childNodes[0],done=0,msg='deleteContents 6') ReadDoc() range = doc.createRange() range.setStart(PA_NAME,0) range.setEnd(EN_PAGER,1) range.deleteContents() tester.testResults(2,len(PA.childNodes),done=0,msg='deleteContents 7') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='deleteContents 8') tester.testResults(None,PA.childNodes[1].firstChild,done=0,msg='deleteContents 9') tester.testResults(6,len(ADDRBOOK.childNodes),done=0,msg='deleteContents 10') tester.testResults(4,len(EN.childNodes),done=0,msg='deleteContents 11') tester.testResults(EN_PAGER,EN.childNodes[0],done=0,msg='deleteContents 12') tester.testResults(None,EN.childNodes[0].firstChild,done=0,msg='deleteContents 13') tester.testDone() tester.startTest("Range.extractContents") #Test two text nodes same ReadDoc() range = doc.createRange() range.setStart(EN_NAME.firstChild,2) range.setEnd(EN_NAME.firstChild,11) df = range.extractContents() tester.testResults('Emsi',EN_NAME.firstChild.data,done=0,msg='extractContents 1') tester.testResults(1,len(df.childNodes),done=0,msg='extractContents 2') tester.testResults('eka Ndubui',df.childNodes[0].data,done=0,msg='extractContents 3') #Two elements, same node ReadDoc() range = doc.createRange() range.setStart(EN,2) range.setEnd(EN,12) df = range.extractContents() tester.testResults(2,len(EN.childNodes),done=0,msg='extractContents 4') tester.testResults(EN_NAME,EN.childNodes[1],done=0,msg='extractContents 5') tester.testResults(11,len(df.childNodes),done=0,msg='extractContents 6') tester.testResults(EN_ADDR,df.childNodes[1],done=0,msg='extractContents 7') tester.testResults(EN_EMAIL,df.childNodes[9],done=0,msg='extractContents 8') #Start is the ancestor ReadDoc() range = doc.createRange() range.setStart(ADDRBOOK,0) range.setEnd(EN_PAGER,1) df = range.extractContents() tester.testResults(4,len(ADDRBOOK.childNodes),done=0,msg='extractContents 9') tester.testResults(4,len(EN.childNodes),done=0,msg='extractContents 10') tester.testResults(EN_PAGER,EN.childNodes[0],done=0,msg='extractContents 11') tester.testResults(None,EN.childNodes[0].firstChild,done=0,msg='extractContents 12') tester.testResults(6,len(df.childNodes),done=0,msg='extractContents 13') #End is the acnestor ReadDoc() range = doc.createRange() range.setStart(PA_NAME,0) range.setEnd(ADDRBOOK,4) df = range.extractContents() tester.testResults(6,len(ADDRBOOK.childNodes),done=0,msg='extractContents 14') tester.testResults(2,len(PA.childNodes),done=0,msg='extractContents 15') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='extractContents 16') tester.testResults(None,PA.childNodes[1].firstChild,done=0,msg='extractContents 17') tester.testResults(4,len(df.childNodes),done=0,msg='extractContents 18') #Text to text deep ancestor ReadDoc() range = doc.createRange() range.setStart(PA_NAME.firstChild,2) range.setEnd(EN_PAGER.firstChild,4) df = range.extractContents() tester.testResults(2,len(PA.childNodes),done=0,msg='extractContents 19') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='extractContents 20') tester.testResults(6,len(ADDRBOOK.childNodes),done=0,msg='extractContents 21') tester.testResults(4,len(EN.childNodes),done=0,msg='extractContents 22') tester.testResults(EN_PAGER,EN.childNodes[0],done=0,msg='extractContents 23') tester.testResults(5,len(df.childNodes),done=0,msg='extractContents 24') ReadDoc() range = doc.createRange() range.setStart(PA_NAME,0) range.setEnd(EN_PAGER,1) df = range.extractContents() tester.testResults(2,len(PA.childNodes),done=0,msg='extractContents 25') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='extractContents 26') tester.testResults(None,PA.childNodes[1].firstChild,done=0,msg='extractContents 27') tester.testResults(6,len(ADDRBOOK.childNodes),done=0,msg='extractContents 28') tester.testResults(4,len(EN.childNodes),done=0,msg='extractContents 29') tester.testResults(EN_PAGER,EN.childNodes[0],done=0,msg='extractContents 30') tester.testResults(None,EN.childNodes[0].firstChild,done=0,msg='extractContents 31') tester.testResults(5,len(df.childNodes),done=0,msg='extractContents 32') tester.testDone() tester.startTest("Range.cloneContents") #Test two text nodes same ReadDoc() range = doc.createRange() range.setStart(EN_NAME.firstChild,2) range.setEnd(EN_NAME.firstChild,11) df = range.cloneContents() tester.testResults('Emeka Ndubuisi',EN_NAME.firstChild.data,done=0,msg='cloneContents 1') tester.testResults(1,len(df.childNodes),done=0,msg='cloneContents 2') tester.testResults('eka Ndubui',df.childNodes[0].data,done=0,msg='cloneContents 3') #Two elements, same node ReadDoc() range = doc.createRange() range.setStart(EN,2) range.setEnd(EN,12) df = range.cloneContents() tester.testResults(13,len(EN.childNodes),done=0,msg='cloneContents 4') tester.testResults(EN_NAME,EN.childNodes[1],done=0,msg='cloneContents 5') tester.testResults(11,len(df.childNodes),done=0,msg='cloneContents 6') tester.testResults('42 Spam Blvd',df.childNodes[1].firstChild.data,done=0,msg='cloneContents 7') tester.testResults('endubuisi@spamtron.com',df.childNodes[9].firstChild.data,done=0,msg='cloneContents 8') #Start is the ancestor ReadDoc() range = doc.createRange() range.setStart(ADDRBOOK,0) range.setEnd(EN_PAGER,1) df = range.cloneContents() tester.testResults(9,len(ADDRBOOK.childNodes),done=0,msg='cloneContents 9') tester.testResults(13,len(EN.childNodes),done=0,msg='cloneContents 10') tester.testResults(EN_PAGER,EN.childNodes[9],done=0,msg='cloneContents 11') tester.testResults('800-SKY-PAGEx767676',EN_PAGER.firstChild.data,done=0,msg='cloneContents 12') tester.testResults(6,len(df.childNodes),done=0,msg='cloneContents 13') #End is the acnestor ReadDoc() range = doc.createRange() range.setStart(PA_NAME,0) range.setEnd(ADDRBOOK,4) df = range.cloneContents() tester.testResults(9,len(ADDRBOOK.childNodes),done=0,msg='cloneContents 14') tester.testResults(13,len(PA.childNodes),done=0,msg='cloneContents 15') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='cloneContents 16') tester.testResults('Pieter Aaron',PA_NAME.firstChild.data,done=0,msg='cloneContents 17') tester.testResults(4,len(df.childNodes),done=0,msg='cloneContents 18') #Text to text deep ancestor ReadDoc() range = doc.createRange() range.setStart(PA_NAME.firstChild,2) range.setEnd(EN_PAGER.firstChild,4) df = range.cloneContents() tester.testResults(13,len(PA.childNodes),done=0,msg='cloneContents 19') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='cloneContents 20') tester.testResults(9,len(ADDRBOOK.childNodes),done=0,msg='cloneContents 21') tester.testResults(13,len(EN.childNodes),done=0,msg='cloneContents 22') tester.testResults(EN_PAGER,EN.childNodes[9],done=0,msg='cloneContents 23') tester.testResults(5,len(df.childNodes),done=0,msg='cloneContents 24') ReadDoc() range = doc.createRange() range.setStart(PA_NAME,0) range.setEnd(EN_PAGER,1) df = range.cloneContents() tester.testResults(13,len(PA.childNodes),done=0,msg='cloneContents 25') tester.testResults(PA_NAME,PA.childNodes[1],done=0,msg='cloneContents 26') tester.testResults(9,len(ADDRBOOK.childNodes),done=0,msg='cloneContents 27') tester.testResults(13,len(EN.childNodes),done=0,msg='cloneContents 29') tester.testResults(EN_PAGER,EN.childNodes[9],done=0,msg='cloneContents 30') tester.testResults(5,len(df.childNodes),done=0,msg='cloneContents 32') tester.testDone() tester.startTest("Range.insertNode") ReadDoc() range = doc.createRange() range.setStart(PA_NAME.firstChild,1) range.setEnd(EN_PAGER,1) newNode = doc.createElement('FOO') range.insertNode(newNode) tester.testResults(3,len(PA_NAME.childNodes),done=0,msg='insertNode 1') tester.testResults('P',PA_NAME.firstChild.data,done=0,msg='insertNode 2') tester.testResults(newNode,PA_NAME.childNodes[1],done=0,msg='insertNode 3') ReadDoc() range = doc.createRange() range.setStart(PA,1) range.setEnd(EN_PAGER,1) newNode = doc.createElement('FOO') range.insertNode(newNode) tester.testResults(14,len(PA.childNodes),done=0,msg='insertNode 3') tester.testResults(newNode,PA.childNodes[2],done=0,msg='insertNode 4') tester.testDone() tester.startTest("Range.surroundContents") ReadDoc() range = doc.createRange() range.setStart(PA,0) range.setEnd(PA,9) newNode = doc.createElement('FOO') range.surroundContents(newNode) tester.testResults(4,len(PA.childNodes),done=0,msg='insertNode 1') tester.testResults(newNode,PA.childNodes[1],done=0,msg='insertNode 2') tester.testDone() tester.startTest("Range.cloneRange") ReadDoc() range = doc.createRange() range.setStart(PA,0) range.setEnd(PA,9) newRange = range.cloneRange() tester.testResults(newRange.endOffset,range.endOffset,done=0,msg='cloneRange 1') tester.testResults(newRange.endContainer,range.endContainer,done=0,msg='cloneRange 2') tester.testResults(newRange.startOffset,range.startOffset,done=0,msg='cloneRange 3') tester.testResults(newRange.startContainer,range.startContainer,done=0,msg='cloneRange 4') tester.testResults(newRange.collapsed,range.collapsed,done=0,msg='cloneRange 5') tester.testResults(newRange.commonAncestorContainer,range.commonAncestorContainer,done=0,msg='cloneRange 6') tester.testDone() tester.startTest("Range.toString") ReadDoc() range = doc.createRange() range.setStart(PA,0) range.setEnd(PA,9) range.toString() range.setStart(PA_NAME.firstChild,3) range.setEnd(EN_EMAIL.firstChild,9) range.toString() tester.testDone() tester.startTest("Range.detach") ReadDoc() range = doc.createRange() range.detach() from xml.dom import InvalidStateErr try: print range.startOffset except InvalidStateErr, e: tester.testDone else: tester.testError() tester.groupDone() if __name__ == '__main__': test() PyXML-0.8.2/test/dom/test_readers.py0100644000076400001440000000414607413603007016511 0ustar martinusersimport cStringIO from xml.dom import DOMException from xml.dom.ext import Print from xml.dom.ext.reader import PyExpat, Sax2 def GetExceptionName(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name expected_1 = source_1 = """\ Marketing Request Re: Widget 404 Request We need 5 of Widget 404 doo-dad to send out to reviewers this week. """ expected_2 = source_2 = """\ """ #expected_1 = """""" def Test(tester): tester.startGroup("Testing PyExpat") reader = PyExpat.Reader() tester.startTest('Basic test') doc = reader.fromString(source_1) stream = cStringIO.StringIO() Print(doc, stream=stream) result = stream.getvalue() print result #if result != expected_1: # tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_1), repr(result))) reader.releaseNode(doc) tester.groupDone() tester.startGroup("Testing Sax2") reader = Sax2.Reader() tester.startTest('Basic test') doc = reader.fromString(source_1) stream = cStringIO.StringIO() Print(doc, stream=stream) result = stream.getvalue() print result #if result != expected_1: # tester.error('Expected\n"""%s"""\ngot\n"""%s"""'%(repr(expected_1), repr(result))) reader.releaseNode(doc) return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = Test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_struct.py0100644000076400001440000000773707406420550016423 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def testRestriction(tester, doc, mapping, node, good): # Any keys that are in the mapping but not in good are automaticly bad bad = [] for key in mapping.keys(): if not key in good: bad.append(key) df = doc.createDocumentFragment() # Make sure none of the good fail for type in good: try: node.appendChild(mapping[type]) except: tester.error('Didn\'t allow addition of %s' % type) else: df.appendChild(mapping[type]) # Add the good nodes in a DocFrag too try: node.appendChild(df) except: tester.error('Could not append DocumentFragment') # And none of the bad work for type in bad: try: node.appendChild(mapping[type]) except: pass else: tester.error('Allowed addition of %s' % type) def test(tester): tester.startGroup('DOM Structure Model') tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('dt1', '', '') doc = implementation.createDocument(EMPTY_NAMESPACE, None, dt) df = doc.createDocumentFragment() element = doc.createElement('TestElement') Nodes = { 'Document' : implementation.createDocument(EMPTY_NAMESPACE,'ROOT2', dt), 'DocType' : implementation.createDocumentType('dt2', '', ''), 'Element' : doc.createElement('tagName1'), 'Text' : doc.createTextNode('data'), 'Comment' : doc.createComment('data'), 'CDATA' : doc.createCDATASection('data'), 'ProcInstruct' : doc.createProcessingInstruction('target', 'data'), 'Attr' : doc.createAttribute('name'), 'EntityRef' : doc.createEntityReference('name'), } tester.testDone() tester.startTest('Testing Document') good = ['Element', 'ProcInstruct', 'Comment', ] # Add duplicate Element & DocType Nodes['Element2'] = doc.createElement('tagName2') testRestriction(tester, doc, Nodes, doc, good) # Remove added items del Nodes['Element2'] tester.testDone() tester.startTest('Testing DocumentFragment') good = ['Element', 'ProcInstruct', 'Comment', 'Text', 'CDATA', 'EntityRef', ] testRestriction(tester, doc, Nodes, df, good) tester.testDone() tester.startTest('Testing DocumentType') good = [ ] testRestriction(tester, doc, Nodes, dt, good) tester.testDone() tester.startTest('Testing EntityReference') good = ['Element', 'ProcInstruct', 'Comment', 'Text', 'CDATA', 'EntityRef' ] ref = doc.createEntityReference('test') testRestriction(tester, doc, Nodes, ref, good) tester.testDone() tester.startTest('Testing Element') good = ['Element', 'ProcInstruct', 'Comment', 'Text', 'CDATA', 'EntityRef', ] testRestriction(tester, doc, Nodes, element, good) tester.testDone() tester.startTest('Testing Attr') good = ['Text', 'EntityRef', ] testRestriction(tester, doc, Nodes, Nodes['Attr'], good) tester.testDone() tester.startTest('Testing Comment') good = [ ] testRestriction(tester, doc, Nodes, Nodes['Comment'], good) tester.testDone() tester.startTest('Testing Text') good = [ ] testRestriction(tester, doc, Nodes, Nodes['Text'], good) tester.testDone() tester.startTest('Testing CDATASection') good = [ ] testRestriction(tester, doc, Nodes, Nodes['CDATA'], good) tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite(0,1) retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_text.py0100644000076400001440000000333307413603007016045 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE from xml.dom import DOMException from xml.dom import INDEX_SIZE_ERR def get_exception_name(code): import types from xml import dom for (name,value) in vars(dom).items(): if (type(value) == types.IntType and value == code): return name def test(tester): tester.startGroup('Text') tester.startTest('Testing syntax') try: from xml.dom import Text from xml.dom.Text import Text except: tester.error('Error in syntax', 1) tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,'ROOT',dt) t = doc.createTextNode("ONETWO") tester.testDone() tester.startTest('Testing splitText()') t2 = t.splitText(3) if t.data != 'ONE': tester.error('splitText did not properly split first half') if t2.data != 'TWO': tester.error('splitText did not properly split second half') try: t.splitText(100) except DOMException, x: if x.code != INDEX_SIZE_ERR: name = get_exception_name(x.code) tester.error("Wrong exception '%s', expected INDEX_SIZE_ERR" % name) else: tester.error('splitText doesn\'t catch an invalid index') tester.testDone() tester.startTest('Testing cloneNode()') t3 = t.cloneNode(0) if t3.data != t.data: error("cloneNode does not copy data") tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite() retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/dom/test_treewalker.py0100644000076400001440000000630107406420550017226 0ustar martinusersfrom TestSuite import EMPTY_NAMESPACE def printer(tester, tw, spc): n = tw.currentNode tester.message("%s<%s>" % (spc, n.nodeName)) child = tw.firstChild() while child: printer(tester, tw, spc + ' ') child = tw.nextSibling() if not child: tw.parentNode() tester.message("%s" % (spc, n.nodeName)) def test(tester): tester.startGroup('TreeWalker') tester.startTest('Checking syntax') from xml.dom.TreeWalker import TreeWalker tester.testDone() tester.startTest('Creating test environment') from xml.dom import implementation from xml.dom.NodeFilter import NodeFilter from xml.dom.ext.reader import Sax dt = implementation.createDocumentType('','','') doc = implementation.createDocument(EMPTY_NAMESPACE,None,dt); xml_string = '' doc = Sax.FromXml(xml_string) from xml.dom.ext import PrettyPrint tw = TreeWalker(doc.documentElement, NodeFilter.SHOW_ELEMENT, None, 1) tester.testDone() tester.startTest('Testing attributes') if tw.root != doc.documentElement: tester.error('root was not set') if tw.whatToShow != NodeFilter.SHOW_ELEMENT: tester.error('whatToShow was not set') if tw.filter != None: tester.error('filter was not set') if tw.expandEntityReferences != 1: tester.error('expandEntityReferences was not set') tw.currentNode = doc.documentElement.lastChild if tw.currentNode != doc.documentElement.lastChild: tester.error('currentNode does not set/get properly') tester.testDone() tester.startTest("Navigating in document order") tw.currentNode = tw.root if tw.currentNode.nodeName != 'a': tester.error('currentNode failed') t = doc.createTextNode('Text') # tw.currentNode.insertBefore(t,tw.firstChild()) if tw.firstChild().nodeName != 'b': tester.error('Wrong firstChild') if tw.nextSibling().nodeName != 'e': tester.error('Wrong nextSibling') if tw.nextSibling() != None: tester.error('nextSibling returns a value; should be (null)') if tw.parentNode().nodeName != 'a': tester.error('Wrong parentNode') if tw.lastChild().nodeName != 'e': tester.error('Wrong lastChild') if tw.nextNode().nodeName != 'f': tester.error('Wrong nextNode') # See if whatToShow works tw.currentNode.appendChild(t) if tw.firstChild() != None: tester.error('whatToShow failed in firstChild()') if tw.previousSibling() != None: tester.error('previousSibling returns a value; should be (null)') if tw.previousNode().nodeName != 'e': tester.error('Wrong previousNode') tw.currentNode.appendChild(t) # See if whatToShow works if tw.lastChild().nodeName != 'g': tester.error('whatToShow failed in lastChlid()') tester.testDone() # tester.startTest('Printing hierarchy') # xml.dom.ext.PrettyPrint(tw.root) # tw.currentNode = tw.root # printer(tester, tw, '') # tester.testDone() return tester.groupDone() if __name__ == '__main__': import sys import TestSuite tester = TestSuite.TestSuite(0,1) retVal = test(tester) sys.exit(retVal) PyXML-0.8.2/test/domapi/0040755000076400001440000000000007614726123014153 5ustar martinusersPyXML-0.8.2/test/domapi/Base.py0100644000076400001440000002165107413603012015365 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import xml.dom from xml.dom import Node import sys import unittest # Namespace URI for namespace tests TEST_NAMESPACE = 'uri:namespacetests' # Convenience map for assert messages TYPE_NAME = { Node.ATTRIBUTE_NODE: 'Attribute', Node.CDATA_SECTION_NODE: 'CDATA Section', Node.COMMENT_NODE: 'Comment', Node.DOCUMENT_FRAGMENT_NODE: 'Document Fragment', Node.DOCUMENT_NODE: 'Document', Node.DOCUMENT_TYPE_NODE: 'DocumentType', Node.ELEMENT_NODE: 'Element', Node.ENTITY_NODE: 'Entity', Node.ENTITY_REFERENCE_NODE: 'Entity Reference', Node.NOTATION_NODE: 'Notation', Node.PROCESSING_INSTRUCTION_NODE: 'Processing Instruction', Node.TEXT_NODE: 'Text', } def checkAttribute(node, attribute, value): """Check that an attribute holds the expected value, and that the corresponding accessor method, if provided, returns an equivalent value.""" # v1 = getattr(node, attribute) if v1 != value: raise AssertionError( "attribute value does not match\n expected: %s\n found: %s" % (`value`, `v1`)) if hasattr(node, "_get_" + attribute): v2 = getattr(node, "_get_" + attribute)() if v2 != value: raise AssertionError( "accessor result does not match\n expected: %s\n found: %s" % (`value`, `v2`)) if v1 != v2: raise AssertionError( "attribute & accessor result don't compare equal\n" " attribute: %s\n accessor: %s" % (`v1`, `v2`)) def checkAttributeNot(node, attribute, value): """Check that an attribute doesn't hold a specific failing value, and that the corresponding accessor method, if provided, returns an equivalent value.""" # v1 = getattr(node, attribute) if v1 == value: raise AssertionError( "attribute value should not match\n found: %s" % `v1`) if hasattr(node, "_get_" + attribute): v2 = getattr(node, "_get_" + attribute)() if v2 == value: raise AssertionError( "accessor result should not match\n found: %s" % `v2`) if v1 != v2: raise AssertionError( "attribute & accessor result don't compare equal\n" " attribute: %s\n accessor: %s" % (`v1`, `v2`)) def checkAttributeSameNode(node, attribute, value): v1 = getattr(node, attribute) if value is None: if v1 is not None: raise AssertionError( "attribute value does not match\n expected: %s\n found: %s" % (`value`, `v1`)) else: if not isSameNode(value, v1): raise AssertionError( "attribute value does not match\n expected: %s\n found: %s" % (`value`, `v1`)) if hasattr(node, "_get_" + attribute): v2 = getattr(node, "_get_" + attribute)() if value is None: if v2 is not None: raise AssertionError( "accessor result does not match\n" " expected: %s\n found: %s" % (`value`, `v2`)) elif not isSameNode(value, v2): raise AssertionError( "accessor result does not match\n" " expected: %s\n found: %s" % (`value`, `v2`)) def checkReadOnly(node, attribute): try: setattr(node, attribute, "don't set this!") except xml.dom.NoModificationAllowedErr: pass else: raise AssertionError("write-access to the '%s' attribute not blocked" % attribute) if hasattr(node, "_set_" + attribute): # setter implemented; make sure it won't allow update try: getattr(node, "_set_" + attribute)("don't set this!") except xml.dom.NoModificationAllowedErr: pass else: raise AssertionError("_set_%s() allowed attribute update" % attribute) def checkLength(node, value): checkAttribute(node, "length", value) if len(node) != value: raise AssertionError("broken support for __len__()") checkReadOnly(node, "length") def isSameNode(node1, node2): """Compare two nodes, returning true if they are the same. Use the DOM lvl 3 Node.isSameNode method if available, otherwise use a simple 'is' test. """ if hasattr(node1, 'isSameNode'): return node1.isSameNode(node2) else: return node1 is node2 class TestCaseBase(unittest.TestCase): def createDocumentNS(self): self.document = self.implementation.createDocument( TEST_NAMESPACE, 'foo:bar', None) return self.document def createDocument(self): self.document = self.implementation.createDocument(None, 'root', None) return self.document def buildCases(modName, feature, level): cases = [] add = cases.append objects = sys.modules[modName].__dict__ for obj in objects.keys(): if obj[-8:] != 'TestCase': continue add((objects[obj], feature, level)) return list(cases) PyXML-0.8.2/test/domapi/CoreLvl1.py0100644000076400001440000024772407534565153016176 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * import string import xml.dom from xml.dom import Node # --- DOMImplementation class DOMImplementationReadTestCase(TestCaseBase): def setUp(self): # self.implementation is already set. pass # Combinations to feed to the hasFeature method; some of these will always # return false, of course. # ('Core', '1.0') was never defined for DOM level 1, it was implicit. Most # DOM level 2 implementations return true, but this is a courtesy. featureMatrix = ( ('Core', None), #('Core', '1.0'), ('Core', '2.0'), ('Core', '3.0'), ('XML', None), ('XML', '1.0'), ('XML', '2.0'), ('XML', '3.0'), ('Traversal', None), ('Traversal', '1.0'), ('Traversal', '2.0'), ('Traversal', '3.0'), ('BogusFeature', None), ('BogusFeature', '1.0'), ('BogusFeature', '2.0'), ('BogusFeature', '3.0'), ) def checkHasFeature(self): impl = self.implementation for feature, level in self.featureMatrix: result1 = impl.hasFeature(feature, level) result2 = impl.hasFeature(string.upper(feature), level) result3 = impl.hasFeature(string.lower(feature), level) expect = ((feature, level) in self.supportedFeatures) self.assertEqual( result1, result2, "Different results from different case feature string.") self.assertEqual( result1, result3, "Different results from different case feature string.") self.assertEqual( (result1 and 1 or 0), expect, "Test for %s, version %s should have returned %s, " "returned %s" % (repr(feature), repr(level), repr(expect), repr(result1))) # --- Node class NodeReadTestCaseBase(TestCaseBase): nodeTypes = ( 'ATTRIBUTE_NODE', 'CDATA_SECTION_NODE', 'COMMENT_NODE', 'DOCUMENT_FRAGMENT_NODE', 'DOCUMENT_NODE', 'DOCUMENT_TYPE_NODE', 'ELEMENT_NODE', 'ENTITY_NODE', 'ENTITY_REFERENCE_NODE', 'NOTATION_NODE', 'PROCESSING_INSTRUCTION_NODE', 'TEXT_NODE', ) def checkNodeTypeConstants(self): for type in self.nodeTypes: checkAttribute(self.node, type, getattr(Node, type)) def checkAttributes(self): if self.node.nodeType == Node.ELEMENT_NODE: checkLength(self.node.attributes, 0) else: checkAttribute(self.node, 'attributes', None) checkReadOnly(self.node, 'attributes') def checkChildNodes(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expectedLength = 1 else: expectedLength = 0 checkLength(self.node.childNodes, expectedLength) checkReadOnly(self.node, 'childNodes') def checkFirstChild(self): # The following node types are expected to have one childNode. if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expected = None else: expected = self.node.childNodes[0] checkAttributeSameNode(self.node, 'firstChild', expected) checkReadOnly(self.node, 'firstChild') if expected: checkAttributeSameNode(self.node.firstChild, 'parentNode', self.node) def checkLastChild(self): # The following node types are expected to have one childNode. if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expected = None else: expected = self.node.childNodes[0] checkAttributeSameNode(self.node, 'lastChild', expected) checkReadOnly(self.node, 'lastChild') if expected: checkAttributeSameNode(self.node.lastChild, 'parentNode', self.node) def checkNextSibling(self): checkAttribute(self.node, 'nextSibling', None) checkReadOnly(self.node, 'nextSibling') nodeNameMap = { Node.CDATA_SECTION_NODE: '#cdata-section', Node.COMMENT_NODE: '#comment', Node.DOCUMENT_NODE: '#document', Node.DOCUMENT_FRAGMENT_NODE: '#document-fragment', Node.TEXT_NODE: '#text', } def checkNodeName(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_TYPE_NODE): expected = self.node.name elif self.node.nodeType == Node.ELEMENT_NODE: expected = self.node.tagName elif self.node.nodeType in (Node.ENTITY_NODE, Node.ENTITY_REFERENCE_NODE, Node.NOTATION_NODE): expected = self.expectedNodeName elif self.node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: expected = self.node.target else: expected = self.nodeNameMap[self.node.nodeType] checkAttribute(self.node, 'nodeName', expected) checkReadOnly(self.node, "nodeName") def checkNodeType(self): checkAttribute(self.node, 'nodeType', self.expectedType) checkReadOnly(self.node, "nodeType") emptyNodeValueList = ( Node.DOCUMENT_FRAGMENT_NODE, Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE, Node.ELEMENT_NODE, Node.ENTITY_NODE, Node.ENTITY_REFERENCE_NODE, Node.NOTATION_NODE, ) def checkNodeValue(self): if self.node.nodeType in self.emptyNodeValueList: expected = None elif self.node.nodeType in (Node.CDATA_SECTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.PROCESSING_INSTRUCTION_NODE): expected = self.node.data elif self.node.nodeType == Node.ATTRIBUTE_NODE: expected = self.node.value checkAttribute(self.node, 'nodeValue', expected) def checkParentNode(self): checkAttribute(self.node, 'parentNode', None) checkReadOnly(self.node, 'parentNode') def checkPreviousSibling(self): checkAttribute(self.node, 'previousSibling', None) checkReadOnly(self.node, 'previousSibling') def hasChildNodes(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expectTrue = 1 else: expectTrue = 0 if expectTrue: self.failUnless( self.node.hasChildNodes(), "hasChildNodes returned 'false' when 'true' was expected.") else: self.failIf( self.node.hasChildNodes(), "hasChildNodes returned 'true' when 'false' was expected.") class NodeWriteTestCaseBase(TestCaseBase): TEST_NAME = 'somename' emptyNodeValueList = NodeReadTestCaseBase.emptyNodeValueList readOnlyNodeList = ( Node.ENTITY_NODE, Node.ENTITY_REFERENCE_NODE, Node.NOTATION_NODE, ) def checkNodeValue(self): # Nodetypes that are read-only. if self.node.nodeType in self.readOnlyNodeList: checkReadOnly(self.node, 'nodeValue') return # Nodetypes that should ignore changes. if self.node.nodeType in self.emptyNodeValueList: self.node.nodeValue = "Ignore this." checkAttribute(self.node, "nodeValue", None) return # Nodetypes where nodeValue is an alias. if self.node.nodeType in (Node.CDATA_SECTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.PROCESSING_INSTRUCTION_NODE): alias = 'data' elif self.node.nodeType == Node.ATTRIBUTE_NODE: alias = 'value' self.node.nodeValue = 'foo' checkAttribute(self.node, 'nodeValue', 'foo') checkAttribute(self.node, alias, 'foo') allowedChildrenMap = { Node.DOCUMENT_NODE: ( Node.ELEMENT_NODE, # Maximum of one, special case Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE, # Maximum of one, special case ), Node.DOCUMENT_FRAGMENT_NODE: ( Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.DOCUMENT_TYPE_NODE: (), Node.ENTITY_REFERENCE_NODE: ( Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.ELEMENT_NODE: ( Node.ELEMENT_NODE, Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.ATTRIBUTE_NODE: ( Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.PROCESSING_INSTRUCTION_NODE: (), Node.COMMENT_NODE: (), Node.TEXT_NODE: (), Node.CDATA_SECTION_NODE: (), Node.ENTITY_NODE: ( Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.NOTATION_NODE: (), } nodeCreateMap = { # from Document 'createAttribute': ('anAttr',), 'createCDATASection': ('a CDATA Section',), 'createComment': ('a Comment',), 'createDocumentFragment': (), 'createElement': ('anElement',), 'createEntityReference': ('anEntityReference',), 'createProcessingInstruction': ('aPI', 'data for PI'), 'createTextNode': ('A Text Node',), # From DOMImplementation (marked as tuples) ('createDocument',): (None, 'aDocument', None), ('createDocumentType',): ('aDocType', 'uri:public', 'uri:system'), } def checkAppendChild(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] if self.node.nodeType == Node.DOCUMENT_NODE: # To create a better test for Document Nodes, we remove the # documentElement Node. self.node.removeChild(self.node.documentElement) # Since appending a Document Type Node to a Document Node isn't # allowed, we remove it from the allowed children list for now. allowedChildren = allowedChildren[:-1] # We add Document Fragment to the list if any child is allowed. Document # Fragments can also hold such children. This test only adds empty # Document Fragments. if allowedChildren: allowedChildren = allowedChildren + (Node.DOCUMENT_FRAGMENT_NODE,) for factoryMethod, factoryArgs in self.nodeCreateMap.items(): if type(factoryMethod) is type(()): # DOMImplementation methods factory = self.implementation factoryMethod = factoryMethod[0] else: factory = self.document newNode = apply(getattr(factory, factoryMethod), factoryArgs) numberOfChildren = self.node.childNodes.length try: # We append two different copies to see how we fare. Esp. handy # with testing the restrictions of a Document Node returnedNode = self.node.appendChild(newNode) newNode = apply(getattr(factory, factoryMethod), factoryArgs) returnedNode = self.node.appendChild(newNode) except xml.dom.HierarchyRequestErr: if self.node.nodeType == Node.DOCUMENT_NODE: if newNode.nodeType == Node.ELEMENT_NODE: self.assert_(self.node.documentElement, "Couldn't add a Element node to" " an empty Document.") else: # tried to append nonElement to a Document node self.assert_( newNode.nodeType not in allowedChildren, "Couldn't append a %s Node." % TYPE_NAME[newNode.nodeType]) else: # tried to append a node to a nonDocument node self.assert_( newNode.nodeType not in allowedChildren, "Couldn't append a %s Node." % TYPE_NAME[newNode.nodeType]) except xml.dom.NoModificationAllowedErr: self.assert_(self.node.nodeType in self.readOnlyNodeList, "Claim of read-only-ness on a modifiable node. " "Tried to append a %s Node" % TYPE_NAME[newNode.nodeType]) else: if newNode.nodeType != Node.DOCUMENT_FRAGMENT_NODE: self.assert_( isSameNode(newNode, returnedNode), "Returned Node is not the same as has been added.") checkAttributeSameNode(self.node, 'lastChild', newNode) checkLength(self.node.childNodes, numberOfChildren + 2) else: checkLength(self.node.childNodes, numberOfChildren) self.assert_(newNode.nodeType in allowedChildren, "Was allowed to append a %s Node." % TYPE_NAME[newNode.nodeType]) self.assert_( self.node.nodeType not in self.readOnlyNodeList, "Was allowed to append a %s Node to a read-only Node" % TYPE_NAME[newNode.nodeType]) def checkAppendChildForeignNode(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return foreignDoc = self.implementation.createDocument(None, 'anotherDoc', None) if Node.TEXT_NODE in allowedChildren: foreignNode = foreignDoc.createTextNode('a Text Node') else: foreignNode = foreignDoc.createComment('a Comment Node') self.assertRaises(xml.dom.WrongDocumentErr, self.node.appendChild, foreignNode) def checkAppendChildAncestorNode(self): nodeType = self.node.nodeType if nodeType in self.readOnlyNodeList: return if Node.ELEMENT_NODE not in self.allowedChildrenMap[nodeType]: return if nodeType not in self.allowedChildrenMap[Node.ELEMENT_NODE]: return ancestorNode = self.document.createElement('foo') ancestorNode.appendChild(self.node) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.appendChild, ancestorNode) def checkAppendChildSelf(self): # See DOM erratum core-6 if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in self.allowedChildrenMap[ self.node.nodeType]: return self.assertRaises(xml.dom.HierarchyRequestErr, self.node.appendChild, self.node) def checkAppendChildWithAttachedNode(self): # Test appending a Node that itself is part of a tree allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: newNode = self.document.createTextNode('a Text Node') else: newNode = self.document.createComment('a Comment Node') oldParent = self.document.createElement('aParentElement') oldParent.appendChild(newNode) self.node.appendChild(newNode) self.failIf(oldParent.hasChildNodes(), "Appended Node not removed from previous parent.") def checkAppendChildNodeParentReadOnly(self): # See DOM erratum core-2 http://www.w3.org/2000/11/DOM-Level-2-errata if self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType in [Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE]: return # can't import doc = self.parse(""" ]> """) # This Text Node has a read-only parent. textNode = doc.doctype.entities.getNamedItem('entity').firstChild # we need self.node to have the same doc as textNode self.node = doc.importNode(self.node, 1) self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.appendChild, textNode) def checkRemoveChild(self): if self.node.nodeType in self.readOnlyNodeList: if self.node.hasChildNodes(): # Test for read-only self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.removeChild, self.node.firstChild) return # If this is a Document Node, let's try and remove the doctype. # We actually test this when we have a doctype, as the Document Node # created for the Document Node tests doesn't *have* a doctype. if self.node.nodeType == Node.DOCUMENT_TYPE_NODE: doc = self.implementation.createDocument('', 'foo', self.node) self.assertRaises(xml.dom.NoModificationAllowedErr, doc.removeChild, doc.doctype) allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed if not allowedChildren: return if Node.TEXT_NODE in allowedChildren: newNode = self.document.createTextNode('a Text Node') else: newNode = self.document.createComment('a Comment Node') self.node.appendChild(newNode) returnedNode = self.node.removeChild(newNode) self.assert_(isSameNode(newNode, returnedNode), "Returned Node is not the appended Node.") checkAttribute(newNode, "parentNode", None) checkAttribute(returnedNode, "parentNode", None) def checkRemoveChildNotFound(self): if self.node.nodeType in self.readOnlyNodeList: return loseNode = self.document.createTextNode('booh') self.assertRaises(xml.dom.NotFoundErr, self.node.removeChild, loseNode) def checkInsertBefore(self): if self.node.nodeType in self.readOnlyNodeList: if self.node.hasChildNodes(): # Test for read-only newNode = self.document.createTextNode('a Text Node') self.assertRaises( xml.dom.NoModificationAllowedErr, self.node.insertBefore, newNode, self.node.firstChild) return allowedChildren = self.allowedChildrenMap[self.node.nodeType] if self.node.nodeType == Node.DOCUMENT_NODE: # To create a better test for Document Nodes, we remove the # documentElement Node. self.node.removeChild(self.node.documentElement) # Since inserting a Document Type Node into a Document Node isn't # allowed, we remove it from the allowed children list for now. allowedChildren = allowedChildren[:-1] # No use when no children are allowed. if not allowedChildren: return else: # Append DOCUMENT_FRAGMENT to alowed, because we'll add an empty # fragment. allowedChildren = allowedChildren + (Node.DOCUMENT_FRAGMENT_NODE,) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') # Now create the reference to insert before. self.node.appendChild(refNode) for factoryMethod, factoryArgs in self.nodeCreateMap.items(): if type(factoryMethod) is type(()): # DOMImplementation methods factory = self.implementation factoryMethod = factoryMethod[0] else: factory = self.document newNode = apply(getattr(factory, factoryMethod), factoryArgs) numberOfChildren = self.node.childNodes.length try: returnedNode = self.node.insertBefore(newNode, refNode) except xml.dom.HierarchyRequestErr: if self.node.nodeType == Node.DOCUMENT_NODE: if newNode.nodeType == Node.ELEMENT_NODE: self.assert_( self.node.documentElement, "Couldn't add a Element node to an empty Document.") self.assert_(newNode.nodeType not in allowedChildren, "Couldn't append a %s Node." % TYPE_NAME[newNode.nodeType]) except xml.dom.NoModificationAllowedErr: self.assert_(self.node.nodeType in self.readOnlyNodeList, "Claim of read-only-ness on a modifiable node. " "Tried to append a %s Node" % TYPE_NAME[self.node.nodeType]) else: if newNode.nodeType != Node.DOCUMENT_FRAGMENT_NODE: self.assert_( isSameNode(newNode, returnedNode), "Returned Node is not the same as has been added.") checkAttributeSameNode(newNode, 'nextSibling', refNode) checkAttributeSameNode(refNode, 'previousSibling', newNode) checkLength(self.node.childNodes, numberOfChildren + 1) else: checkLength(self.node.childNodes, numberOfChildren) self.assert_(newNode.nodeType in allowedChildren, "Was allowed to insert a %s Node." % TYPE_NAME[newNode.nodeType]) def checkInsertBeforeNotFound(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.assertRaises( xml.dom.NotFoundErr, self.node.insertBefore, refNode, refNode.cloneNode(0)) def checkInsertBeforeExtraElementToDocument(self): if self.node.nodeType == Node.DOCUMENT_NODE: newNode = self.document.createElement('foo') self.assertRaises( xml.dom.HierarchyRequestErr, self.node.insertBefore, newNode, self.node.documentElement) def checkInsertBeforeForeignNode(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return foreignDoc = self.implementation.createDocument(None, 'anotherDoc', None) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') foreignNode = foreignDoc.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') foreignNode = foreignDoc.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.WrongDocumentErr, self.node.insertBefore, foreignNode, refNode) def checkInsertBeforeAncestorNode(self): if self.node.nodeType in self.readOnlyNodeList: return if Node.ELEMENT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType not in self.allowedChildrenMap[Node.ELEMENT_NODE]: return ancestorNode = self.document.createElement('foo') ancestorNode.appendChild(self.node) if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.insertBefore, ancestorNode, refNode) def checkInsertBeforeSelf(self): # See DOM erratum core-7 if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in self.allowedChildrenMap[ self.node.nodeType]: return if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.insertBefore, self.node, refNode) def checkInsertBeforeWithAttachedNode(self): # Test appending a Node that itself is part of a tree allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') newNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') newNode = self.document.createComment('a Comment Node') oldParent = self.document.createElement('aParentElement') oldParent.appendChild(newNode) self.node.appendChild(refNode) self.node.insertBefore(newNode, refNode) self.failIf(oldParent.hasChildNodes(), "Appended Node not removed from previous parent.") def checkInsertBeforeNodeParentReadOnly(self): # See DOM erratum core-2 http://www.w3.org/2000/11/DOM-Level-2-errata if self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType in [Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE]: return # can't import doc = self.parse(""" ]> """) # This Text Node has a read-only parent. textNode = doc.doctype.entities.getNamedItem('entity').firstChild refNode = doc.createTextNode('a Text Node') # we need self.node to have the same doc as textNode self.node = doc.importNode(self.node, 1) self.node.appendChild(refNode) self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.insertBefore, textNode, refNode) def checkReplaceChild(self): if self.node.nodeType in self.readOnlyNodeList: if self.node.hasChildNodes(): # Test for read-only newNode = self.document.createTextNode('a Text Node') self.assertRaises( xml.dom.NoModificationAllowedErr, self.node.replaceChild, newNode, self.node.firstChild) return allowedChildren = self.allowedChildrenMap[self.node.nodeType] if self.node.nodeType == Node.DOCUMENT_NODE: # To create a better test for Document Nodes, we remove the # documentElement Node. self.node.removeChild(self.node.documentElement) # Since replacing with a Document Type Node on a Document Node isn't # allowed, we remove it from the allowed children list for now. allowedChildren = allowedChildren[:-1] # No use when no children are allowed. if not allowedChildren: return else: # Append DOCUMENT_FRAGMENT to alowed, because we'll use an empty # fragment. allowedChildren = allowedChildren + (Node.DOCUMENT_FRAGMENT_NODE,) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') for factoryMethod, factoryArgs in self.nodeCreateMap.items(): if type(factoryMethod) is type(()): # DOMImplementation methods factory = self.implementation factoryMethod = factoryMethod[0] else: factory = self.document # Now create the reference to replace. We do this for every Node # type we try and replace with. self.node.appendChild(refNode) newNode = apply(getattr(factory, factoryMethod), factoryArgs) numberOfChildren = self.node.childNodes.length try: returnedNode = self.node.replaceChild(newNode, refNode) except xml.dom.HierarchyRequestErr: if self.node.nodeType == Node.DOCUMENT_NODE \ and newNode.nodeType == Node.ELEMENT_NODE: self.assert_( self.node.documentElement, "Couldn't add an Element node to an empty Document.") self.assert_( newNode.nodeType not in allowedChildren, "Couldn't replace an old Node with a %s Node." % TYPE_NAME[newNode.nodeType]) except xml.dom.NoModificationAllowedErr: self.assert_( self.node.nodeType in self.readOnlyNodeList, "Claim of read-only-ness on a modifiable node. " "Tried to replace an old Node with a %s Node" % TYPE_NAME[self.node.nodeType]) else: if newNode.nodeType != Node.DOCUMENT_FRAGMENT_NODE: self.assert_( isSameNode(refNode, returnedNode), "Returned Node is not the same as has been replaced.") checkAttributeSameNode(self.node, 'lastChild', newNode) checkLength(self.node.childNodes, numberOfChildren) self.assert_( isSameNode(refNode, returnedNode), "Returned Node is not the same as has been replaced.") else: checkLength(self.node.childNodes, numberOfChildren - 1) self.assert_(newNode.nodeType in allowedChildren, "Was allowed to replace an old Node with a " "%s Node." % TYPE_NAME[newNode.nodeType]) def checkReplaceChildNotFound(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.assertRaises( xml.dom.NotFoundErr, self.node.replaceChild, refNode, refNode.cloneNode(0)) def checkReplaceChildExtraElementToDocument(self): if self.node.nodeType == Node.DOCUMENT_NODE: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) newNode = self.document.createElement('foo') self.assertRaises(xml.dom.HierarchyRequestErr, self.node.replaceChild, newNode, refNode) def checkReplaceChildForeignNode(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return foreignDoc = self.implementation.createDocument(None, 'anotherDoc', None) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') foreignNode = foreignDoc.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') foreignNode = foreignDoc.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.WrongDocumentErr, self.node.replaceChild, foreignNode, refNode) def checkReplaceChildAncestorNode(self): if self.node.nodeType in self.readOnlyNodeList: return if Node.ELEMENT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType not in self.allowedChildrenMap[Node.ELEMENT_NODE]: return ancestorNode = self.document.createElement('foo') ancestorNode.appendChild(self.node) if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.replaceChild, ancestorNode, refNode) def checkReplaceChildSelf(self): # See DOM erratum core-8 if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in self.allowedChildrenMap[ self.node.nodeType]: return if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.replaceChild, self.node, refNode) def checkReplaceChildWithAttachedNode(self): # Test replacing with a Node that itself is part of a tree allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') newNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') newNode = self.document.createComment('a Comment Node') oldParent = self.document.createElement('aParentElement') oldParent.appendChild(newNode) self.node.appendChild(refNode) self.node.replaceChild(newNode, refNode) self.failIf(oldParent.hasChildNodes(), "Replacing Node not removed from previous parent.") def checkReplaceChildNodeParentReadOnly(self): # See DOM erratum core-2 http://www.w3.org/2000/11/DOM-Level-2-errata if self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType in [Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE]: return # can't import doc = self.parse(""" ]> """) # This Text Node has a read-only parent. textNode = doc.doctype.entities.getNamedItem('entity').firstChild # we need self.node to have the same doc as textNode self.node = doc.importNode(self.node, 1) refNode = doc.createTextNode('a Text Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.replaceChild, textNode, refNode) # --- Document class DocumentReadTestCase(NodeReadTestCaseBase): def setUp(self): self.createDocument() self.node = self.document self.expectedType = Node.DOCUMENT_NODE def checkGetDoctype(self): checkAttribute(self.document, "doctype", None) checkReadOnly(self.document, "doctype") def checkGetImplementation(self): checkAttribute(self.document, "implementation", self.implementation) checkReadOnly(self.document, "implementation") def checkGetDocumentElement(self): checkAttributeNot(self.document, "documentElement", None) checkReadOnly(self.document, "documentElement") def checkCloneNode(self): # TODO: Implementation dependent, what should we test? pass class DocumentWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.node = self.createDocument() def checkGetElementsByTagName(self): doc = self.document elements = {} names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for c in names: elements[c] = doc.createElement(c) # set up simple tree elements['a'].appendChild(elements['b']) elements['a'].appendChild(elements['d']) elements['b'].appendChild(elements['c']) elements['d'].appendChild(elements['e']) elements['d'].appendChild(elements['h']) elements['e'].appendChild(elements['f']) elements['e'].appendChild(elements['g']) elements['h'].appendChild(elements['i']) doc.documentElement.appendChild(elements['a']) # now test # find all elements in the right order result = doc.getElementsByTagName('*') self.assertEqual(len(result), len(names) + 1) for name, element in map(None, names, result[1:]): self.assertEqual(name, element.tagName) # find single element, top result = doc.getElementsByTagName('a') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'a') # find single element somewhere in tree result = doc.getElementsByTagName('h') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'h') def checkCreateAttribute(self): attr = self.document.createAttribute(self.TEST_NAME) checkAttribute(attr, 'nodeType', Node.ATTRIBUTE_NODE) checkAttribute(attr, 'name', self.TEST_NAME) checkAttribute(attr, 'localName', None) checkAttribute(attr, 'prefix', None) checkAttribute(attr, 'namespaceURI', None) checkAttribute(attr, 'value', '') checkAttributeSameNode(attr, 'ownerDocument', self.document) # Note the ':' in the name, createAttribute does not know about # namespaces, so the colon has no special meaning. attr = self.document.createAttribute('not_a_prefix:not_a_localname') checkAttribute(attr, 'name', 'not_a_prefix:not_a_localname') checkAttribute(attr, 'localName', None) checkAttribute(attr, 'prefix', None) self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createAttribute, '5_illegal') def checkCreateCDATASection(self): cdata = self.document.createCDATASection('A CDATA Section') checkAttribute(cdata, 'nodeType', Node.CDATA_SECTION_NODE) checkAttribute(cdata, 'data', 'A CDATA Section') checkAttributeSameNode(cdata, 'ownerDocument', self.document) def checkCreateComment(self): comment = self.document.createComment('A Comment') checkAttribute(comment, 'nodeType', Node.COMMENT_NODE) checkAttribute(comment, 'data', 'A Comment') checkAttributeSameNode(comment, 'ownerDocument', self.document) def checkCreateDocumentFragment(self): fragment = self.document.createDocumentFragment() checkAttribute(fragment, 'nodeType', Node.DOCUMENT_FRAGMENT_NODE) checkLength(fragment.childNodes, 0) checkAttributeSameNode(fragment, 'ownerDocument', self.document) def checkCreateElement(self): el = self.document.createElement(self.TEST_NAME) checkAttribute(el, 'nodeType', Node.ELEMENT_NODE) checkAttribute(el, 'tagName', self.TEST_NAME) checkAttribute(el, 'localName', None) checkAttribute(el, 'prefix', None) checkAttribute(el, 'namespaceURI', None) checkAttributeSameNode(el, 'ownerDocument', self.document) # Note the ':' in the name, createElement does not know about # namespaces, so the colon has no special meaning. el = self.document.createElement('not_a_prefix:not_a_localname') checkAttribute(el, 'tagName', 'not_a_prefix:not_a_localname') checkAttribute(el, 'localName', None) checkAttribute(el, 'prefix', None) def checkCreateElementInvalidCharacter(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createElement, '5_illegal') def checkCreateEntityReference(self): entRef = self.document.createEntityReference('entityReference') checkAttribute(entRef, 'nodeType', Node.ENTITY_REFERENCE_NODE) checkAttribute(entRef, 'nodeName', 'entityReference') checkAttributeSameNode(entRef, 'ownerDocument', self.document) def checkCreateEntityReferenceInvalidCharacter(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createEntityReference, '5_illegal') def checkCreateProcessingInstruction(self): pi = self.document.createProcessingInstruction('PITarget', 'PI Data') checkAttribute(pi, 'nodeType', Node.PROCESSING_INSTRUCTION_NODE) checkAttribute(pi, 'target', 'PITarget') checkAttribute(pi, 'data', 'PI Data') checkAttributeSameNode(pi, 'ownerDocument', self.document) def checkCreateProcessingInstructionInvalidCharacter(self): self.assertRaises( xml.dom.InvalidCharacterErr, self.document.createProcessingInstruction, '5_illegal', 'data') def checkCreateTextNode(self): text = self.document.createTextNode('A Text Node') checkAttribute(text, 'nodeType', Node.TEXT_NODE) checkAttribute(text, 'data', 'A Text Node') checkAttributeSameNode(text, 'ownerDocument', self.document) # --- Element class ElementReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.createDocument() self.element = self.node = doc.createElement("per") self.expectedType = Node.ELEMENT_NODE self.floating_element = self.element self.attached_element = doc.createElement("attached") doc.documentElement.appendChild(self.attached_element) def checkDocumentElementChildNodes(self): checkLength(self.document.documentElement.childNodes, 1) def checkAttachedElementParentNode(self): checkAttributeSameNode(self.attached_element, "parentNode", self.document.documentElement) def checkDocumentElementFirstChild(self): checkAttributeSameNode(self.document.documentElement, "firstChild", self.attached_element) checkAttributeSameNode( self.document.documentElement.firstChild, "parentNode", self.document.documentElement) def checkTagName(self): checkAttribute(self.floating_element, "tagName", "per") checkAttribute(self.attached_element, "tagName", "attached") checkReadOnly(self.floating_element, "tagName") def checkGetAttribute(self): self.assertEqual(self.element.getAttribute("ugga"), "", "non-existant attribute should return ''") def checkGetAttributeNode(self): self.assert_(self.element.getAttributeNode("ugga") is None, "non-existant attribute node should return None") def checkCloneNode(self): el = self.element doc = self.document el.appendChild(doc.createTextNode('A Text Node')) el.appendChild(doc.createComment('A Comment')) el.setAttribute('attr1', 'An attribute') el.setAttribute('attr2', 'Another attribute') el.appendChild(el.cloneNode(0)) clone = el.cloneNode(1) self.failIf(isSameNode(el, clone), "Clone is same Node as original.") self.failIf(isSameNode(el, clone.lastChild), "Clone is same Node as original.") checkAttribute(clone, 'parentNode', None) checkLength(clone.childNodes, el.childNodes.length) checkLength(clone.attributes, el.attributes.length) checkLength(clone.lastChild.childNodes, 0) checkLength(clone.lastChild.attributes, el.attributes.length) checkAttribute(clone, 'nodeName', el.nodeName) checkAttribute(clone.lastChild, 'nodeName', el.nodeName) checkAttribute(clone, 'nodeType', el.nodeType) checkAttribute(clone.lastChild, 'nodeType', el.nodeType) checkAttribute(clone, 'nodeValue', el.nodeValue) checkAttribute(clone.lastChild, 'nodeValue', el.nodeValue) for i in range(clone.childNodes.length): checkAttribute(clone.childNodes.item(i), 'nodeType', el.childNodes.item(i).nodeType) if clone.childNodes.item(i).nodeType != Node.ELEMENT_NODE: checkAttribute(clone.childNodes.item(i), 'data', el.childNodes.item(i).data) for i in range(clone.attributes.length): checkAttribute(clone.attributes.item(i), 'name', el.attributes.item(i).name) checkAttribute(clone.lastChild.attributes.item(i), 'name', el.attributes.item(i).name) checkAttribute(clone.attributes.item(i), 'value', el.attributes.item(i).value) checkAttribute(clone.lastChild.attributes.item(i), 'value', el.attributes.item(i).value) # deep and shallow clones should clone attributes value = clone.attributes.item(i).value el.attributes.item(i).value = 'spam' checkAttribute(clone.attributes.item(i), 'value', value) checkAttribute(clone.lastChild.attributes.item(i), 'value', value) checkAttributeSameNode(clone.attributes.item(i), 'ownerElement', clone) checkAttributeSameNode(clone.lastChild.attributes.item(i), 'ownerElement', clone.lastChild) self.failIf(isSameNode(el.attributes.item(i), clone.attributes.item(i))) class ElementWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.createDocument() self.element = self.node = doc.createElement("per") self.floating_element = self.element self.attached_element = doc.createElement("attached") self.attached_element2 = doc.createElement("attached2") doc.documentElement.appendChild(self.attached_element) doc.documentElement.appendChild(self.attached_element2) def checkAttachedElementsNextSibling(self): checkAttributeSameNode(self.attached_element, "nextSibling", self.attached_element2) checkAttributeSameNode(self.attached_element2, "nextSibling", None) def checkAttachedElementsPreviousSibling(self): checkAttributeSameNode(self.attached_element, "previousSibling", None) checkAttributeSameNode(self.attached_element2, "previousSibling", self.attached_element) def checkGetElementsByTagName(self): doc = self.document el = self.element elements = {} names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for c in names: elements[c] = doc.createElement(c) # set up simple tree elements['a'].appendChild(elements['b']) elements['a'].appendChild(elements['d']) elements['b'].appendChild(elements['c']) elements['d'].appendChild(elements['e']) elements['d'].appendChild(elements['h']) elements['e'].appendChild(elements['f']) elements['e'].appendChild(elements['g']) elements['h'].appendChild(elements['i']) el.appendChild(elements['a']) # now test # find all elements in the right order result = el.getElementsByTagName('*') self.assertEqual(len(result), len(names)) for name, element in map(None, names, result): self.assertEqual(name, element.tagName) # find single element, top result = el.getElementsByTagName('a') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'a') # find single element somewhere in tree result = el.getElementsByTagName('h') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'h') def checkSetAttribute(self): self.element.setAttribute("ugga", "foo") self.assert_(self.element.hasAttribute("ugga"), "Test for presence of created attribute returned false.") value = self.element.getAttribute("ugga") self.assertEqual(value, 'foo', "Incorrect attr value returned. Expected 'foo', got " + repr(value)) def checkSetAttributeIllegalCharacter(self): self.assertRaises( xml.dom.InvalidCharacterErr, self.element.setAttribute, '5_illegal', "Don't eat this") def checkSetAttributeNode(self): node = self.document.createAttribute("ugga") node.value = 'foo' returnValue = self.element.setAttributeNode(node) self.assert_( self.element.hasAttribute("ugga"), "Test for presence of created attribute returned false.") self.assert_(returnValue is None, "Returned value is %s" % repr(returnValue)) value = self.element.getAttribute("ugga") self.assertEqual(value, 'foo', "Incorrect attr value returned. Expected 'foo', got " + repr(value)) returnedNode = self.element.getAttributeNode("ugga") self.assert_(isSameNode(node, returnedNode), "Incorrect node returned from getAttributeNode.") def checkSetAttributeNodeReplaceExisting(self): node = self.document.createAttribute("ugga") self.element.setAttributeNode(node) newNode = self.document.createAttribute("ugga") returnValue = self.element.setAttributeNode(newNode) if returnValue is None: self.fail("setAttributeNode did not replace original attribute") self.assert_(isSameNode(node, returnValue), "setAttributeNode returned %s" % repr(returnValue)) def checkSetAttributeNodeWrongDocument(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = foreignDoc.createAttribute('spam') self.assertRaises(xml.dom.WrongDocumentErr, self.element.setAttributeNodeNS, foreignAttr) def checkSetAttributeNodeAlreadyInUse(self): otherElement = self.document.createElement('foo') otherAttr = self.document.createAttribute('spam') otherElement.setAttributeNodeNS(otherAttr) self.assertRaises(xml.dom.InuseAttributeErr, self.element.setAttributeNodeNS, otherAttr) def checkRemoveAttribute(self): node1 = self.document.createAttribute("foo") node2 = self.document.createAttribute("bar") self.element.setAttributeNode(node1) self.element.setAttributeNode(node2) self.element.removeAttribute("foo") self.failIf( self.element.hasAttribute("foo"), "Test for presence of created attribute still returns true.") self.assert_(self.element.hasAttribute("bar"), "Test for presence of created attribute returned false.") checkAttribute(node1, 'ownerElement', None) def checkRemoveAttributeNode(self): node1 = self.document.createAttribute("foo") node2 = self.document.createAttribute("bar") self.element.setAttributeNode(node1) self.element.setAttributeNode(node2) returnedNode = self.element.removeAttributeNode(node1) self.assert_( isSameNode(node1, returnedNode), "Returned node not the same as the one removed.") checkAttribute(node1, 'ownerElement', None) self.failIf( self.element.hasAttribute("foo"), "Test for presence of created attribute still returns true.") self.assert_( self.element.hasAttribute("bar"), "Test for presence of created attribute returned false.") def checkRemoveAttributeNodeNotFound(self): node = self.document.createAttribute("foo") self.assertRaises(xml.dom.NotFoundErr, self.element.removeAttributeNode, node) # --- CharacterData class CharacterDataReadTestCaseBase(NodeReadTestCaseBase): def checkGetData(self): checkAttribute(self.chardata, "data", "com") def checkGetLength(self): checkLength(self.chardata, 3) self.assertEqual(len(self.chardata.data), 3) self.assertEqual(len(self.chardata._get_data()), 3) def checkSubstringData(self): self.assertEqual(self.chardata.substringData(0, 2), "co") def checkSubstringDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.substringData, -2, 0) def checkSubstringDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.substringData, 10, 0) def checkSubstringDataNegativeCount(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.substringData, 0, -2) def checkSubstringDataOffsetAndCountGreaterThanLength(self): self.assertEqual(self.chardata.substringData(1, 10), "om") def checkCloneNode(self): clone = self.chardata.cloneNode(0) deepClone = self.chardata.cloneNode(1) self.failIf(isSameNode(self.chardata, clone), "Clone is same as original.") self.failIf(isSameNode(self.chardata, deepClone), "Clone is same as original.") checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.chardata.nodeType) checkAttribute(deepClone, 'nodeType', self.chardata.nodeType) checkAttribute(clone, 'data', self.chardata.data) checkAttribute(deepClone, 'data', self.chardata.data) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, 0) class CharacterDataWriteTestCaseBase(NodeWriteTestCaseBase): def checkSetData(self): self.chardata._set_data("data") checkAttribute(self.chardata, "data", "data") def checkAppendData(self): self.chardata.appendData("com") checkAttribute(self.chardata, "data", "comcom") def checkInsertData(self): self.chardata.insertData(2, "com") checkAttribute(self.chardata, "data", "cocomm") def checkInsertDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.insertData, -2, 'foo') def checkInsertDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.insertData, 10, 'foo') def checkDeleteData(self): self.chardata.deleteData(1, 1) checkAttribute(self.chardata, "data", "cm") def checkDeleteDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.deleteData, -2, 0) def checkDeleteDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.deleteData, 10, 0) def checkDeleteDataNegativeCount(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.deleteData, 0, -2) def checkDeleteDataOffsetAndCountGreaterThanLength(self): self.chardata.deleteData(0, 10) checkAttribute(self.chardata, "data", "") def checkReplaceData(self): self.chardata.replaceData(1, 3, "uuuu") checkAttribute(self.chardata, "data", "cuuuu") def checkReplaceDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.replaceData, -2, 0, 'foo') def checkReplaceDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.replaceData, 10, 0, 'foo') def checkReplaceDataNegativeCount(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.replaceData, 0, -2, 'foo') def checkReplaceDataOffsetAndCountGreaterThanLength(self): self.chardata.replaceData(0, 10, "foo") checkAttribute(self.chardata, "data", "foo") # --- Comment class CommentReadTestCase(CharacterDataReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createComment("com") self.expectedType = Node.COMMENT_NODE class CommentWriteTestCase(CharacterDataWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createComment("com") # --- Text class TextReadTestCase(CharacterDataReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createTextNode("com") self.expectedType = Node.TEXT_NODE class TextWriteTestCase(CharacterDataWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createTextNode("com") def checkAcquisition(self): if 1: # This test is disabled. Simple implicit acquisition # causes removeAttribute() to be acquired when it # probably should not, but this issue is not of # sufficient importance for now. return cdata = self.document.createTextNode("com") self.document.documentElement.appendChild(cdata) cdata2 = self.document.createTextNode("com2") self.document.documentElement.appendChild(cdata2) attr = self.document.createAttribute("attrName") self.document.documentElement.setAttributeNode(attr) # Technically these should raise. Because of acquisition they # might not. We want to make sure that they don't affect # the tree. try: self.document.documentElement.firstChild.normalize() except: pass try: self.document.documentElement.firstChild.removeAttribute( "attrName") except: pass else: self.fail('removeAttribute() was acquired from documentElement.') checkAttribute(self.document.documentElement.childNodes, "length", 2) checkAttribute(self.document.documentElement.attributes, "length", 1) def checkSplitText(self): newNode = self.chardata.splitText(2) checkAttribute(self.chardata, 'data', 'co') checkAttribute(newNode, 'data', 'm') def checkSplitTextOffsetEqualToLength(self): try: newNode = self.chardata.splitText(self.chardata.length) except xml.dom.IndexSizeErr: self.fail( "INDEX_SIZE_ERR raised on splitText with offset == length.") checkAttribute(self.chardata, 'data', 'com') checkAttribute(newNode, 'data', '') def checkSplitTextNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.splitText, -2) def checkSplitTextOffsetGreateThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.splitText, 10) def checkSplitTextWithParent(self): el = self.document.createElement('foo') el.appendChild(self.chardata) newNode = self.chardata.splitText(2) checkAttributeSameNode(self.chardata, 'nextSibling', newNode) # --- Attr class AttrReadTestCase(NodeReadTestCaseBase): def setUp(self): self.attr = self.node = self.createDocument().createAttribute("name") self.expectedType = Node.ATTRIBUTE_NODE def checkGetName(self): checkAttribute(self.attr, "name", "name") def checkGetSpecified(self): self.assert_(self.attr._get_specified()) self.assert_(self.attr.specified) def checkGetValue(self): checkAttribute(self.attr, "value", "") checkLength(self.attr.childNodes, 1) checkAttribute(self.attr.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(self.attr.firstChild, 'data', '') def checkCloneNode(self): clone = self.attr.cloneNode(0) deepClone = self.attr.cloneNode(1) self.failIf(isSameNode(self.attr, clone), "Clone is same as original.") self.failIf(isSameNode(self.attr, deepClone), "Clone is same as original.") checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.attr.nodeType) checkAttribute(deepClone, 'nodeType', self.attr.nodeType) checkAttribute(clone, 'name', self.attr.name) checkAttribute(deepClone, 'name', self.attr.name) checkAttribute(clone, 'value', self.attr.value) checkAttribute(deepClone, 'value', self.attr.value) checkAttribute(clone, 'specified', 1) checkAttribute(deepClone, 'specified', 1) checkAttribute(clone, 'nodeName', self.attr.nodeName) checkAttribute(deepClone, 'nodeName', self.attr.nodeName) checkAttribute(clone, 'nodeValue', self.attr.nodeValue) checkAttribute(deepClone, 'nodeValue', self.attr.nodeValue) checkLength(clone.childNodes, 1) # Subtree models value checkAttribute(clone.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(clone.firstChild, 'data', self.attr.value) checkLength(deepClone.childNodes, 1) checkAttribute(deepClone.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(deepClone.firstChild, 'data', self.attr.value) class AttrWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.attr = self.node = self.createDocument().createAttribute( "attrName") self.element = self.document.createElement("eltName") def checkSetValue(self): self.attr._set_value("14") checkAttribute(self.attr, "value", "14") checkLength(self.attr.childNodes, 1) checkAttribute(self.attr.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(self.attr.firstChild, 'data', '14') def checkManipulateSubTree(self): attr = self.attr self.assert_(attr.hasChildNodes(), "Attr doesn't have subtree to manipulate!") newNode = self.document.createTextNode('New Value') attr.replaceChild(newNode, attr.firstChild) checkAttribute(attr.firstChild, 'data', 'New Value') checkAttribute(attr, 'value', 'New Value') attr.appendChild(self.document.createTextNode(' (appended)')) checkAttribute(attr, 'value', 'New Value (appended)') attr.firstChild.appendData(' ') attr.replaceChild(self.document.createEntityReference('foo'), attr.lastChild) checkAttribute(attr, 'value', 'New Value ') # Setting the value with a string containing an XML reference does *not* # cause it to create an EntiyReference. Everything is a string literal. attr.value = 'Some Value &test;' checkLength(attr.childNodes, 1) checkAttribute(attr.firstChild, 'data', 'Some Value &test;') def checkOwnerElement(self): checkAttribute(self.attr, "ownerElement", None) checkReadOnly(self.attr, "ownerElement") self.element.setAttributeNode(self.attr) checkAttributeSameNode(self.attr, "ownerElement", self.element) checkReadOnly(self.attr, "ownerElement") def checkAttrTwoReferencesIntegrity(self): #XXX this test should be generalized to any reference attr = self.document.createAttribute('spam') self.document.documentElement.setAttributeNode(attr) a1 = self.document.documentElement.attributes.item(0) a2 = self.document.documentElement.attributes.item(0) a1.appendChild(self.document.createTextNode('eggs')) self.assertEqual( a1.childNodes.length, a2.childNodes.length, "Write to one attr reference isn't reflected in another ref.") def checkAttrReferenceElementAttributeIntegrity(self): "changing an attribute node should be reflected by getAttribute" attr = self.document.createAttribute('spam') self.document.documentElement.setAttributeNode(attr) a1 = self.document.documentElement.attributes.item(0) a1.value = 'eggs' self.assertEqual( self.document.documentElement.getAttribute('spam'), 'eggs', "setting value of attr reference isn't reflected by getAttribute") a1.appendChild(self.document.createTextNode('ham')) self.assertEqual( self.document.documentElement.getAttribute('spam'), 'eggsham', "appendChild on attr reference isn't reflected by getAttribute.") def checkSetAttrWithSubtree(self): "setAttributeNode shouldn't lose attr subtree information" eggs = self.document.createTextNode('eggs') ham = self.document.createTextNode('ham') self.attr.appendChild(eggs) self.attr.appendChild(ham) self.element.setAttributeNode(self.attr) # check that getting the attr from the element preserves subtree checkAttribute(self.element.attributes.item(0).childNodes, "length", 3) self.assert_( self.attr.firstChild.nextSibling.isSameNode(eggs), "setting an attribute node destroys children") self.assert_( self.attr.firstChild.nextSibling.nextSibling.isSameNode(ham), "setting an attribute node destroys children") # check that another ref preserves subtree, too attr2 = self.element.getAttributeNode('attrName') checkAttribute(attr2.childNodes, "length", 3) self.assert_( attr2.firstChild.nextSibling.isSameNode(eggs), "setting an attribute node destroys children") self.assert_( attr2.firstChild.nextSibling.nextSibling.isSameNode(ham), "setting an attribute node destroys children") def checkCloneNode(self): attr = self.attr clone = attr.cloneNode(0) self.failIf(isSameNode(attr, clone), "Clone is same Node as original.") checkAttribute(clone, 'value', attr.value) # make sure the cloned attr isn't sharing data with the original oldValue = self.attr.value self.attr.value = 'spam' checkAttribute(clone, 'value', oldValue) # --- Default attributes class DefaultAttrTestCase(TestCaseBase): def setUp(self): self.document = self.parse(""" ]> """) def checkHasAttribute(self): el = self.document.documentElement self.assert_(el.hasAttribute('foo'), 'Default attribute not found.') def checkGetAttribute(self): el = self.document.documentElement self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % repr(el.getAttribute('foo'))) def checkCreateElement(self): el = self.document.createElement('doc') self.assert_( el.hasAttribute('foo'), 'Newly created Element Node should have default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkCloneNode(self): attr = self.document.documentElement.getAttributeNode('foo') clone = attr.cloneNode(0) checkAttribute(clone, 'specified', 1) def checkCloneNodeElement(self): clone = self.document.documentElement.cloneNode(0) checkAttribute(clone.getAttributeNode('foo'), 'specified', 0) # XXX also check that cloned attrs aren't the same nodes, changes # aren't reflected across refs def checkRemoveAttribute(self): el = self.document.documentElement # Replace default with specified attr el.setAttribute('foo', 'baz') el.removeAttribute('foo') self.assert_( el.hasAttribute('foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkRemoveAttributeNode(self): el = self.document.documentElement newAttr = self.document.createAttribute('foo') newAttr.value = 'baz' # Replace default with specified attr el.setAttributeNode(newAttr) el.removeAttributeNode(newAttr) self.assert_( el.hasAttribute('foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkRemoveNamedItem(self): el = self.document.documentElement # Replace default with specified attr el.setAttribute('foo', 'baz') el.attributes.removeNamedItem('foo') self.assert_( el.hasAttribute('foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkSpecified(self): checkAttribute(self.document.documentElement.getAttributeNode('foo'), 'specified', 0) def checkSetAttribute(self): el = self.document.documentElement el.setAttribute('foo', 'baz') checkAttribute(el.getAttributeNode('foo'), 'specified', 1) def checkSetAttributeNode(self): el = self.document.documentElement newAttr = self.document.createAttribute('foo') newAttr.value = 'baz' el.setAttributeNode(newAttr) checkAttribute(el.getAttributeNode('foo'), 'specified', 1) # --- DocumentFragment class DocumentFragmentReadTestCase(NodeReadTestCaseBase): def setUp(self): self.docfrag = self.createDocument().createDocumentFragment() self.node = self.docfrag self.expectedType = Node.DOCUMENT_FRAGMENT_NODE def checkCloneNode(self): frag = self.docfrag frag.appendChild(self.document.createComment('foo')) frag.appendChild(self.document.createTextNode('bar')) clone = frag.cloneNode(0) deepClone = frag.cloneNode(1) self.failIf(isSameNode(frag, clone), "Clone is same Node as original.") self.failIf(isSameNode(frag, deepClone), "Clone is same Node as original.") checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, frag.childNodes.length) for i in range(deepClone.childNodes.length): checkAttribute(deepClone.childNodes.item(i), 'nodeType', frag.childNodes.item(i).nodeType) checkAttribute(deepClone.childNodes.item(i), 'data', frag.childNodes.item(i).data) class DocumentFragmentWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.createDocument() self.docfrag = self.node = self.document.createDocumentFragment() def checkInsertBeforeEnd(self): doc = self.document fragment = self.docfrag fragment.appendChild(doc.createElement('foo')) fragment.appendChild(doc.createTextNode('textual magic')) docelem = doc.documentElement docelem.insertBefore(fragment, None) checkAttribute(docelem.childNodes[0], "nodeName", "foo") checkAttribute(docelem.childNodes[1], "nodeValue", "textual magic") checkLength(docelem.childNodes, 2) checkAttribute(docelem.firstChild, "nodeName", "foo") # --- NodeList class NodeListReadTestCase(TestCaseBase): def setUp(self): self.createDocument() self.list = self.document.createElement("foo")._get_childNodes() def checkGetLength(self): checkLength(self.list, 0) checkLength(self.document.childNodes, 1) def checkItem(self): self.assert_(self.list.item(0) is None) def checkGetItem(self): self.assertRaises(xml.dom.IndexSizeErr, self.list[0]) # there's no cmp for NodeList right now #def checkCmp(self): # list1 = self.document.documentElement._get_childNodes() # list2 = self.document.firstChild._get_childNodes() # self.assertEqual(list1, list2, # "two NodeLists of the same thing don't compare" ## def checkGetSlice(self): ## self.assertEqual(self.list[2:5], []) class NodeListWriteTestCase(TestCaseBase): def setUp(self): self.createDocument() self.list = self.document.childNodes def checkGetLength(self): checkLength(self.list, 1) self.document.appendChild(self.document.createComment('foo')) # A NodeList is 'live', changes to source Node should be reflected checkLength(self.list, 2) def checkItem(self): newNode = self.document.createComment('foo') self.document.appendChild(newNode) # A NodeList is 'live', changes to source Node should be reflected isSameNode(newNode, self.list.item(1)) # This extends to the Nodes contained in the NodeList newNode.data = 'bar' checkAttribute(self.list.item(1), 'data', 'bar') # --- NamedNodeMap class NamedNodeMapReadTestCase(TestCaseBase): def setUp(self): self.map = self.createDocument().createElement("foo")._get_attributes() def checkGetLength(self): checkLength(self.map, 0) def checkGetNamedItem(self): self.assert_(self.map.getNamedItem("uuu") is None) def checkRemoveNamedItem(self): self.assertRaises(xml.dom.NotFoundErr, self.map.removeNamedItem, "uuu") def checkItem(self): self.assert_(self.map.item(0) is None) def checkGetItem(self): try: self.map["uuu"] self.fail("expected KeyError to be raised") except KeyError: pass def checkGet(self): self.assertEqual(self.map.get("uuu", 5), 5) def checkHasKey(self): self.failIf(self.map.has_key("uuu")) def checkItems(self): self.assertEqual(self.map.items(), []) def checkKeys(self): self.assertEqual(self.map.keys(), []) def checkValues(self): self.assertEqual(self.map.values(), []) class NonemptyNamedNodeMapWriteTestCase(TestCaseBase): def setUp(self): self.map = self.createDocument().createElement("foo")._get_attributes() self.attribute = self.document.createAttribute("attrName") self.attribute.value = "attrValue" self.map.setNamedItem(self.attribute) def checkRemoveNonexistentNamedItem(self): self.assertRaises(xml.dom.DOMException, self.map.removeNamedItem, "uuu") def checkRemoveNamedItem(self): attribute2 = self.document.createAttribute("attrName2") self.map.setNamedItem(attribute2) attrOut = self.map.removeNamedItem("attrName2") self.assert_(isSameNode(attrOut, attribute2)) def checkRemoveNamedItemNotFound(self): self.assertRaises(xml.dom.NotFoundErr, self.map.removeNamedItem, "bogus") def checkGetLength(self): checkLength(self.map, 1) def checkGetNamedItem(self): self.assert_(isSameNode(self.attribute, self.map.getNamedItem("attrName"))) def checkGetNonexistentNamedItem(self): self.assert_(self.map.getNamedItem("uuu") is None) def checkItem(self): self.assert_(isSameNode(self.map.item(0), self.attribute)) self.assert_(isSameNode(self.attribute, self.map.item(0))) def checkGetNonexistentItem(self): try: self.map["uuu"] self.fail("expected KeyError to be raised") except KeyError: pass def checkGetItem(self): self.assert_(isSameNode(self.attribute, self.map["attrName"])) def checkGet(self): self.assert_(isSameNode(self.attribute, self.map.get("attrName"))) def checkHasKey(self): self.assert_(self.map.has_key("attrName")) self.assert_(not self.map.has_key("uuu")) def checkItems(self): key, node = self.map.items()[0] self.assertEqual(key, "attrName") self.assert_(isSameNode(self.attribute, node)) def checkKeys(self): self.assertEqual(self.map.keys(), ["attrName"]) def checkValues(self): L = [] for attr in self.map.values(): L.append(attr.value) self.assertEqual(L, ["attrValue"], "bad values list: %s" % `L`) def checkSetNamedItem(self): newAttr = self.document.createAttribute('someAttr') newAttr.value = 'spam' retVal = self.map.setNamedItem(newAttr) self.assert_( retVal is None, "setNamedItem returned %s" % repr(retVal)) checkLength(self.map, 2) self.assert_( isSameNode(self.map.getNamedItem('someAttr'), newAttr), "setNamedItem store seems to have failed, can't retrieve.") def checkSetNamedItemReplacingExistingNode(self): newAttr = self.document.createAttribute('someAttr') self.map.setNamedItem(newAttr) anotherAttr = self.document.createAttribute('someAttr') anotherAttr.value = 'eggs' retVal = self.map.setNamedItem(newAttr) self.assert_(retVal is not None, "setNamedItem returned None") self.assert_(isSameNode(retVal, newAttr), "setNamedItem didn't return replaced Node.") checkLength(self.map, 2) def checkSetNamedItemWrongDocument(self): newDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = newDoc.createAttribute('someAttr') self.assertRaises(xml.dom.WrongDocumentErr, self.map.setNamedItem, foreignAttr) def checkSetNamedItemAlreadyInUse(self): el = self.document.createElement('someElement') attr = self.document.createAttribute('someAttribute') el.setAttributeNode(attr) self.assertRaises(xml.dom.InuseAttributeErr, self.map.setNamedItem, attr) def checkSetNamedItemHierarchyRequestErr(self): # See DOM erratum core-4. textNode = self.document.createTextNode('text node') self.assertRaises(xml.dom.HierarchyRequestErr, self.map.setNamedItem, textNode) cases = buildCases(__name__, 'Core', None) PyXML-0.8.2/test/domapi/CoreLvl2.py0100644000076400001440000017640407534565153016173 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * import CoreLvl1 _DOMImplCase = CoreLvl1.DOMImplementationReadTestCase _NodeTestCaseBase = CoreLvl1.NodeWriteTestCaseBase del CoreLvl1 import sys import string import xml.dom from xml.dom import Node # --- DOMIMplementation class DOMImplementationReadTestCase(TestCaseBase): TEST_NAMESPACE = TEST_NAMESPACE TEST_PREFIX = 'aprefix' TEST_LOCAL_NAME = 'somelocalname' TEST_QUALIFIED_NAME = '%s:%s' % (TEST_PREFIX, TEST_LOCAL_NAME) def setUp(self): # self.implementation is already set. pass def checkCreateDocument(self): # Non namespace Document newDoc = self.implementation.createDocument(None, self.TEST_LOCAL_NAME, None) checkAttribute(newDoc, 'nodeType', Node.DOCUMENT_NODE) checkAttribute(newDoc, 'doctype', None) checkAttributeNot(newDoc, 'documentElement', None) self.assert_(newDoc.implementation is self.implementation, 'Created Document has different implementation.') checkAttribute(newDoc.documentElement, 'namespaceURI', None) checkAttribute(newDoc.documentElement, 'tagName', self.TEST_LOCAL_NAME) def checkCreateDocumentWithNamespace(self): newDoc = self.implementation.createDocument(self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME, None) checkAttribute(newDoc.documentElement, 'namespaceURI', self.TEST_NAMESPACE) checkAttribute(newDoc.documentElement, 'tagName', self.TEST_QUALIFIED_NAME) def checkCreateDocumentWithDocumentType(self): docType = self.implementation.createDocumentType( self.TEST_QUALIFIED_NAME, 'uri:public', 'uri:system') newDoc = self.implementation.createDocument(None, self.TEST_LOCAL_NAME, docType) checkAttributeSameNode(newDoc, 'doctype', docType) def checkCreateDocumentIllegalCharacterErr(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.implementation.createDocument, self.TEST_NAMESPACE, '4_prefix:5_illegal', None) def checkCreateDocumentMalformedQA(self): self.assertRaises(xml.dom.NamespaceErr, self.implementation.createDocument, self.TEST_NAMESPACE, 'malformed:qualfied:name', None) self.assertRaises(xml.dom.NamespaceErr, self.implementation.createDocument, self.TEST_NAMESPACE, ':malformed_qn', None) def checkCreateDocumentWithPrefixNoNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.implementation.createDocument, None, self.TEST_QUALIFIED_NAME, None) def checkCreateDocumentWithXMLPrefixWrongNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.implementation.createDocument, self.TEST_NAMESPACE, 'xml:nope', None) def checkCreateDocumentWithUsedDocType(self): docType = self.implementation.createDocumentType( self.TEST_QUALIFIED_NAME, 'uri:public', 'uri:system') self.implementation.createDocument(None, self.TEST_LOCAL_NAME, docType) self.assertRaises(xml.dom.WrongDocumentErr, self.implementation.createDocument, None, self.TEST_LOCAL_NAME, docType) def checkCreateDocumentType(self): docType = self.implementation.createDocumentType( self.TEST_QUALIFIED_NAME, 'uri:public', 'uri:system') checkAttribute(docType, 'ownerDocument', None) checkAttribute(docType, 'name', self.TEST_QUALIFIED_NAME) checkAttribute(docType, 'publicId', 'uri:public') checkAttribute(docType, 'systemId', 'uri:system') checkLength(docType.entities, 0) checkLength(docType.notations, 0) def checkCreateDocumentTypeIllegalCharacterErr(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.implementation.createDocumentType, '4_prefix:5_illegal', 'uri:public', 'uri:system') def checkCreateDocumentTypeMalformedQA(self): self.assertRaises(xml.dom.NamespaceErr, self.implementation.createDocumentType, 'malformed:qualfied:name', 'uri:public', 'uri:system') self.assertRaises(xml.dom.NamespaceErr, self.implementation.createDocumentType, ':malformed_qn', 'uri:public', 'uri:system') # --- Node class NodeReadTestCaseBase(TestCaseBase): TEST_NAMESPACE = TEST_NAMESPACE TEST_PREFIX = 'aprefix' TEST_LOCAL_NAME = 'somelocalname' TEST_QUALIFIED_NAME = '%s:%s' % (TEST_PREFIX, TEST_LOCAL_NAME) def checkLocalName(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): expect = self.TEST_LOCAL_NAME noNS = self.nodeNoNS else: expect = None noNS = None checkAttribute(self.node, 'localName', expect) checkReadOnly(self.node, 'localName') if noNS: checkAttribute(noNS, 'localName', None) def checkNameSpaceURI(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): expect = self.TEST_NAMESPACE noNS = self.nodeNoNS else: expect = None noNS = None checkAttribute(self.node, 'namespaceURI', expect) checkReadOnly(self.node, 'namespaceURI') if noNS: checkAttribute(noNS, 'namespaceURI', None) def checkOwnerDocument(self): if self.node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE): expect = None else: expect = self.document checkAttributeSameNode(self.node, 'ownerDocument', expect) checkReadOnly(self.node, 'ownerDocument') def checkPrefix(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): expect = self.TEST_PREFIX noNS = self.nodeNoNS else: expect = None noNS = None checkAttribute(self.node, 'prefix', expect) if noNS: checkAttribute(noNS, 'prefix', None) def hasAttributes(self): self.failIf(self.node.hasAttributes(), "hasAttributes returned 'true' when 'false' was expected.") featureMatrix = _DOMImplCase.featureMatrix def checkIsSupported(self): for feature, level in self.featureMatrix: result1 = self.node.isSupported(feature, level) result2 = self.node.isSupported(string.upper(feature), level) result3 = self.node.isSupported(string.lower(feature), level) expect = ((feature, level) in self.supportedFeatures) self.assertEqual( result1, result2, "Different results from different case feature string.") self.assertEqual( result1, result3, "Different results from different case feature string.") self.assertEqual( (result1 and 1 or 0), expect, "Test for %s, version %s should have returned %s, " "returned %s" % (repr(feature), repr(level), repr(expect), repr(result1))) class NodeWriteTestCaseBase(TestCaseBase): TEST_NAMESPACE = NodeReadTestCaseBase.TEST_NAMESPACE TEST_PREFIX = NodeReadTestCaseBase.TEST_PREFIX TEST_LOCAL_NAME = NodeReadTestCaseBase.TEST_LOCAL_NAME TEST_QUALIFIED_NAME = NodeReadTestCaseBase.TEST_QUALIFIED_NAME readOnlyNodeList = _NodeTestCaseBase.readOnlyNodeList def checkPrefix(self): # Nodetypes that are read-only. if self.node.nodeType in self.readOnlyNodeList: checkReadOnly(self.node, 'nodeValue') return # Nodetypes that should ignore changes. if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): self.node.prefix = "Ignore_this" checkAttribute(self.node, "prefix", None) return # All other node types self.node.prefix = 'foo' checkAttribute(self.node, 'prefix', 'foo') checkAttribute(self.node, 'nodeName', 'foo:%s' % self.TEST_LOCAL_NAME) # Changing the prefix also changes other attributes newQualifiedName = '%s:%s' % ('foo', self.TEST_LOCAL_NAME) checkAttribute(self.node, 'nodeName', newQualifiedName) if self.node.nodeType == Node.ATTRIBUTE_NODE: checkAttribute(self.node, 'name', newQualifiedName) else: checkAttribute(self.node, 'tagName', newQualifiedName) def checkPrefixInvalidCharacter(self): if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): return try: self.node.prefix = '5_illegal_prefix' except xml.dom.InvalidCharacterErr: pass else: self.fail("Setting of illegal prefix succeeded.") def checkPrefixMalformedPrefix(self): if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): return try: self.node.prefix = ':prefix_with_colon' except xml.dom.NamespaceErr: pass else: self.fail("Setting of malformed prefix with ':' succeeded.") def checkPrefixNamespaceErr(self): if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): return try: self.nodeNoNS.prefix = 'foo' except xml.dom.NamespaceErr: pass else: self.fail('Changing prefix on Node without namespace succeeded.') def checkPrefixXMLNamespace(self): if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): return try: self.node.prefix = 'xml' except xml.dom.NamespaceErr: pass else: self.fail("Changing prefix to 'xml' on Node without" " W3C XML namespace succeeded.") def checkPrefixXMLNSNamespace(self): if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.ELEMENT_NODE): return if self.node.nodeType == Node.ATTRIBUTE_NODE: try: self.node.prefix = 'xmlns' except xml.dom.NamespaceErr: pass else: self.fail("Changing prefix to 'xmlns' on Attribute without" " W3C XML Namespaces namespace succeeded.") # --- Document class DocumentReadTestCase(NodeReadTestCaseBase): def setUp(self): self.node = self.createDocumentNS() def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) self.assertRaises(xml.dom.NotSupportedErr, foreignDoc.importNode, self.document, 0) class DocumentWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.node = self.createDocumentNS() def checkGetElementsByTagNameNS(self): doc = self.document elements = {} names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for c in names: elements[c + '1'] = doc.createElementNS('uri:1', 'one:' + c) elements[c + '2'] = doc.createElementNS('uri:2', 'two:' + c) # set up simple tree elements['a1'].appendChild(elements['a2']) elements['a1'].appendChild(elements['b1']) elements['a1'].appendChild(elements['d1']) elements['b1'].appendChild(elements['b2']) elements['b1'].appendChild(elements['c1']) elements['c1'].appendChild(elements['c2']) elements['d1'].appendChild(elements['d2']) elements['d1'].appendChild(elements['e1']) elements['d1'].appendChild(elements['h1']) elements['e1'].appendChild(elements['e2']) elements['e1'].appendChild(elements['f1']) elements['e1'].appendChild(elements['g1']) elements['f1'].appendChild(elements['f2']) elements['g1'].appendChild(elements['g2']) elements['h1'].appendChild(elements['h2']) elements['h1'].appendChild(elements['i1']) elements['i1'].appendChild(elements['i2']) doc.documentElement.appendChild(elements['a1']) # now test # find all elements in the right order result = doc.getElementsByTagNameNS('*', '*') allnames = [] add = allnames.append for name in names: add(name) add(name) self.assertEqual(len(result), len(allnames) + 1) for name, element in map(None, allnames, result[1:]): self.assertEqual(name, element.localName) # find all elements in one namespace in the right order result = doc.getElementsByTagNameNS('uri:1', '*') self.assertEqual(len(result), len(names)) for name, element in map(None, names, result): self.assertEqual(name, element.localName) # find single element, top result = doc.getElementsByTagNameNS('uri:1', 'a') checkLength(result, 1) self.assertEqual(result[0].tagName, 'one:a') # find single element somewhere in tree result = doc.getElementsByTagNameNS('uri:2', 'h') checkLength(result, 1) self.assertEqual(result[0].tagName, 'two:h') # find elements in the tree from all namespaces result = doc.getElementsByTagNameNS('*', 'f') checkLength(result, 2) self.assertEqual(result[0].tagName, 'one:f') self.assertEqual(result[1].tagName, 'two:f') def checkNormalize(self): doc = self.document docEl = doc.documentElement # First build a tree with adjacent and empty Text nodes, intermingled # with other Nodes. docEl.appendChild(doc.createTextNode('This')) docEl.appendChild(doc.createTextNode('')) docEl.appendChild(doc.createTextNode(' is')) docEl.appendChild(doc.createTextNode(' ')) docEl.appendChild(doc.createTextNode('a test.')) docEl.appendChild(doc.createCDATASection("Don't merge")) docEl.appendChild(doc.createTextNode('1')) docEl.appendChild(doc.createComment('foo')) docEl.appendChild(doc.createTextNode('2')) subEl = doc.createElement('baz') attr = doc.createAttribute('eggs') subEl.setAttributeNode(attr) docEl.appendChild(subEl) subEl.appendChild(doc.createTextNode('To ')) subEl.appendChild(doc.createTextNode('')) subEl.appendChild(doc.createTextNode('be or')) subEl.appendChild(doc.createEntityReference('amp')) subEl.appendChild(doc.createTextNode('not ')) subEl.appendChild(doc.createTextNode('to')) subEl.appendChild(doc.createTextNode(' be')) attr.appendChild(doc.createTextNode('Spanish ')) attr.appendChild(doc.createTextNode('Inquisition')) docEl.appendChild(doc.createTextNode('3')) docEl.appendChild(doc.createProcessingInstruction('bar', 'spam')) docEl.appendChild(doc.createTextNode('4')) # Now test doc.normalize() checkLength(docEl.childNodes, 9) checkLength(subEl.childNodes, 3) checkLength(attr.childNodes, 1) checkAttribute(docEl.childNodes[0], 'nodeType', Node.TEXT_NODE) checkAttribute(docEl.childNodes[0], 'data', 'This is a test.') checkAttribute(docEl.childNodes[1], 'nodeType', Node.CDATA_SECTION_NODE) checkAttribute(docEl.childNodes[2], 'nodeType', Node.TEXT_NODE) checkAttribute(docEl.childNodes[3], 'nodeType', Node.COMMENT_NODE) checkAttribute(docEl.childNodes[4], 'nodeType', Node.TEXT_NODE) checkAttribute(docEl.childNodes[5], 'nodeType', Node.ELEMENT_NODE) checkAttribute(docEl.childNodes[6], 'nodeType', Node.TEXT_NODE) checkAttribute(docEl.childNodes[7], 'nodeType', Node.PROCESSING_INSTRUCTION_NODE) checkAttribute(docEl.childNodes[8], 'nodeType', Node.TEXT_NODE) checkAttribute(subEl.childNodes[0], 'nodeType', Node.TEXT_NODE) checkAttribute(subEl.childNodes[1], 'nodeType', Node.ENTITY_REFERENCE_NODE) checkAttribute(subEl.childNodes[2], 'nodeType', Node.TEXT_NODE) checkAttribute(subEl.childNodes[0], 'data', 'To be or') checkAttribute(subEl.childNodes[2], 'data', 'not to be') checkAttribute(attr.childNodes[0], 'data', 'Spanish Inquisition') def checkCreateAttributeNS(self): attr = self.document.createAttributeNS(self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) checkAttribute(attr, 'nodeType', Node.ATTRIBUTE_NODE) checkAttribute(attr, 'name', self.TEST_QUALIFIED_NAME) checkAttribute(attr, 'localName', self.TEST_LOCAL_NAME) checkAttribute(attr, 'prefix', self.TEST_PREFIX) checkAttribute(attr, 'namespaceURI', self.TEST_NAMESPACE) checkAttribute(attr, 'value', '') checkAttributeSameNode(attr, 'ownerDocument', self.document) def checkCreateAttributeNSNoPrefix(self): attr = self.document.createAttributeNS(self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) checkAttribute(attr, 'name', self.TEST_LOCAL_NAME) checkAttribute(attr, 'localName', self.TEST_LOCAL_NAME) checkAttribute(attr, 'prefix', None) checkAttribute(attr, 'namespaceURI', self.TEST_NAMESPACE) def checkCreateAttributeNSIllegalCharacter(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createAttributeNS, self.TEST_NAMESPACE, '4_prefix:5_illegal') def checkCreateAttributeNSMalformedQA(self): self.assertRaises(xml.dom.NamespaceErr, self.document.createAttributeNS, self.TEST_NAMESPACE, 'malformed:qualfied:name') self.assertRaises(xml.dom.NamespaceErr, self.document.createAttributeNS, self.TEST_NAMESPACE, ':malformed_qn') def checkCreateAttributeNSPrefixNoNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.document.createAttributeNS, None, self.TEST_QUALIFIED_NAME) def checkCreateAttributeNSXMLNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.document.createAttributeNS, self.TEST_NAMESPACE, 'xml:nope') def checkCreateAttributeNSXMLNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.document.createAttributeNS, self.TEST_NAMESPACE, 'xmlns:nope') def checkCreateElementNS(self): el = self.document.createElementNS(self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) checkAttribute(el, 'nodeType', Node.ELEMENT_NODE) checkAttribute(el, 'tagName', self.TEST_QUALIFIED_NAME) checkAttribute(el, 'localName', self.TEST_LOCAL_NAME) checkAttribute(el, 'prefix', self.TEST_PREFIX) checkAttribute(el, 'namespaceURI', self.TEST_NAMESPACE) checkAttributeSameNode(el, 'ownerDocument', self.document) def checkCreateElementNSNoPrefix(self): el = self.document.createElementNS(self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) checkAttribute(el, 'tagName', self.TEST_LOCAL_NAME) checkAttribute(el, 'localName', self.TEST_LOCAL_NAME) checkAttribute(el, 'prefix', None) checkAttribute(el, 'namespaceURI', self.TEST_NAMESPACE) def checkCreateElementNSIllegalCharacter(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createElementNS, self.TEST_NAMESPACE, '4_prefix:5_illegal') def checkCreateElementNSMalformedQA(self): self.assertRaises(xml.dom.NamespaceErr, self.document.createElementNS, self.TEST_NAMESPACE, 'malformed:qualfied:name') self.assertRaises(xml.dom.NamespaceErr, self.document.createElementNS, self.TEST_NAMESPACE, ':malformed_qn') def checkCreateElementNSPrefixNoNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.document.createElementNS, None, self.TEST_QUALIFIED_NAME) def checkCreateElementNSXMLNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.document.createElementNS, self.TEST_NAMESPACE, 'xml:nope') class GetElementByIdTestCase(TestCaseBase): PROLOGUE = """\ ]> """ def setup(self): pass def checkWithoutId(self): doc = self.parse(self.PROLOGUE + "") self.assert_(doc.getElementById("foo") is None) def checkWithDifferentId(self): doc = self.parse(self.PROLOGUE + "") self.assert_(doc.getElementById("foo") is None) def checkWithIdOnRootElement(self): doc = self.parse(self.PROLOGUE + "") self.assert_(isSameNode(doc.getElementById("foo"), doc.documentElement)) def checkWithIdOnChildElement(self): doc = self.parse(self.PROLOGUE + "") self.assert_(isSameNode(doc.getElementById("foo"), doc.documentElement.firstChild)) # --- Element class ElementReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.createDocument() self.element = self.nodeNoNS = self.elementNoNS = doc.createElement( self.TEST_LOCAL_NAME) self.elementNS = self.node = doc.createElementNS( self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) def checkGetAttributeNS(self): self.assertEqual(self.element.getAttributeNS("uri:bugga", "ugga"), "", "non-existant attribute should return ''") def checkGetAttributeNodeNS(self): self.assert_( self.element.getAttributeNodeNS("uri:bugga", "ugga") is None, "non-existant attribute should return None") def checkCloneNode(self): el = self.element clone = el.cloneNode(0) self.failIf(isSameNode(el, clone), "Clone is same Node as original.") checkAttribute(clone, 'localName', el.localName) checkAttribute(clone, 'namespaceURI', el.namespaceURI) checkAttribute(clone, 'prefix', el.prefix) def checkImportNode(self): el = self.element doc = self.document el.appendChild(doc.createTextNode('A Text Node')) el.appendChild(doc.createComment('A Comment')) el.setAttribute('attr1', 'An attribute') el.setAttribute('attr2', 'Another attribute') foreignDoc = self.implementation.createDocument(None, 'foo', None) clone = foreignDoc.importNode(self.element, 0) deepClone = foreignDoc.importNode(self.element, 1) self.failIf(isSameNode(el, clone), "Clone is same Node as original.") self.failIf(isSameNode(el, deepClone), "Clone is same Node as original.") checkAttributeSameNode(clone, 'ownerDocument', foreignDoc) checkAttributeSameNode(deepClone, 'ownerDocument', foreignDoc) checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, el.childNodes.length) checkLength(clone.attributes, el.attributes.length) checkLength(deepClone.attributes, el.attributes.length) checkAttribute(clone, 'nodeName', el.nodeName) checkAttribute(deepClone, 'nodeName', el.nodeName) checkAttribute(clone, 'nodeType', el.nodeType) checkAttribute(deepClone, 'nodeType', el.nodeType) checkAttribute(clone, 'nodeValue', el.nodeValue) checkAttribute(deepClone, 'nodeValue', el.nodeValue) for i in range(deepClone.childNodes.length): checkAttribute(deepClone.childNodes.item(i), 'nodeType', el.childNodes.item(i).nodeType) checkAttributeSameNode(deepClone.childNodes.item(i), 'ownerDocument', foreignDoc) if deepClone.childNodes.item(i).nodeType != Node.ELEMENT_NODE: checkAttribute(deepClone.childNodes.item(i), 'data', el.childNodes.item(i).data) for i in range(deepClone.attributes.length): checkAttribute(clone.attributes.item(i), 'name', el.attributes.item(i).name) checkAttribute(deepClone.attributes.item(i), 'name', el.attributes.item(i).name) checkAttribute(clone.attributes.item(i), 'value', el.attributes.item(i).value) checkAttribute(deepClone.attributes.item(i), 'value', el.attributes.item(i).value) checkAttributeSameNode(clone.attributes.item(i), 'ownerElement', clone) checkAttributeSameNode(deepClone.attributes.item(i), 'ownerElement', deepClone) class ElementWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.createDocument() self.element = self.nodeNoNS = self.elementNoNS = doc.createElement( self.TEST_LOCAL_NAME) self.elementNS = self.node = doc.createElementNS(self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) def checkHasAttribute(self): self.failIf(self.element.hasAttribute('ugga'), "Test for non-exisiting attribute returned true.") self.element.setAttribute("ugga", "foo") self.assert_(self.element.hasAttribute('ugga'), "Test for exisiting attribute returned false.") def checkSetAttributeNS(self): self.element.setAttributeNS("uri:bugga", "b:ugga", "foo") self.element.setAttributeNS("uri:bar", "bar:ugga", "baz") self.assert_(self.element.hasAttributeNS("uri:bar", "ugga"), "Test for presence of created attribute returned false.") value = self.element.getAttributeNS("uri:bugga", "ugga") self.assertEqual(value, 'foo', "Incorrect attr value returned. Expected 'foo', got " + repr(value)) node = self.element.getAttributeNodeNS("uri:bugga", "ugga") self.assertEqual(node.prefix, 'b', "New Attr has incorrect prefix, expected 'b', got " + repr(node.prefix)) #"Note that because the DOM does no lexical checking, the empty string #will be treated as a real namespace URI in DOM Level 2 methods. #Applications must use the value null as the namespaceURI parameter for #methods if they wish to have no namespace." - the rec # The NamespaceURI must be a namespace name, which Namespaces in XML # states is a URI reference. I'm assuming that "" is not a valid URI # reference, so we're not testing using that. def checkSetAttributeEmptyNS(self): self.element.setAttributeNS(None, "ugga", "foo") self.assert_(self.element.hasAttributeNS(None, "ugga"), "Test for presence of created attribute returned false.") value = self.element.getAttributeNS(None, "ugga") self.assertEqual(value, 'foo', "Incorrect attr value returned. Expected 'foo', got " + repr(value)) node = self.element.getAttributeNodeNS(None, "ugga") self.assert_(node.prefix is None, "New Attr node has incorrect prefix, expected None, got " + repr(node.prefix)) def checkSetAttributeNSDifferentPrefix(self): self.element.setAttributeNS("uri:bugga", "b:ugga", "foo") self.element.setAttributeNS("uri:bar", "bar:ugga", "baz") self.element.setAttributeNS("uri:bugga", "c:ugga", "new value") self.assert_(self.element.hasAttributeNS("uri:bar", "ugga"), "Test for presence of created attribute returned false.") value = self.element.getAttributeNS("uri:bugga", "ugga") self.assertEqual( value, 'new value', "Wrong attr value returned. Expected 'new value', got " + repr(value)) node = self.element.getAttributeNodeNS("uri:bugga", "ugga") self.assertEqual(node.prefix, 'c', "New Attr has incorrect prefix, expected 'c', got " + repr(node.prefix)) def checkSetAttributeNSNoPrefix(self): self.element.setAttributeNS(TEST_NAMESPACE, 'foo', 'bar') self.assert_(self.element.hasAttributeNS(TEST_NAMESPACE, "foo"), "Test for presence of created attribute returned false.") value = self.element.getAttributeNS(TEST_NAMESPACE, "foo") self.assertEqual(value, 'bar', "Incorrect attr value returned. Expected 'bar', got " + repr(value)) node = self.element.getAttributeNodeNS(TEST_NAMESPACE, "foo") checkAttribute(node, 'prefix', None) def checkSetAttributeNSXMLNSDeclaration(self): XMLNSNamespace = 'http://www.w3.org/2000/xmlns/' self.element.setAttributeNS(XMLNSNamespace, 'xmlns', TEST_NAMESPACE) self.assert_( self.element.hasAttributeNS(XMLNSNamespace, "xmlns"), "Test for presence of created xmlns attribute returned false.") value = self.element.getAttributeNS(XMLNSNamespace, "xmlns") self.assertEqual(value, TEST_NAMESPACE, "Incorrect attr value returned. Expected %s, got " + repr((`TEST_NAMESPACE`, `value`))) node = self.element.getAttributeNodeNS(XMLNSNamespace, "xmlns") checkAttribute(node, 'prefix', None) def checkSetAttributeNSIllegalCharacter(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.element.setAttributeNS, "uri:bugga", "5_b:ugga", "illegal") def checkSetAttributeNSMalformedQA(self): self.assertRaises(xml.dom.NamespaceErr, self.element.setAttributeNS, "uri:bugga", 'malformed:qualfied:name', "malformed") self.assertRaises(xml.dom.NamespaceErr, self.element.setAttributeNS, "uri:bugga", ':malformed_qn', "malformed") def checkSetAttributeNSPrefixNoNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.element.setAttributeNS, None, 'prefix:localName', 'Nono') def checkSetAttributeNSXMLNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.element.setAttributeNS, 'uri:unknown', 'xml:localName', 'Nono') def checkSetAttributeNSXMLNSNamespace(self): self.assertRaises(xml.dom.NamespaceErr, self.element.setAttributeNS, 'uri:unknown', 'xmlns:localName', 'No') def checkSetAttributeNodeNS(self): node1 = self.document.createAttributeNS("uri:bugga", "b:ugga") node1.value = 'foo' node2 = self.document.createAttributeNS("uri:bar", "bar:ugga") returnValue = self.element.setAttributeNode(node1) self.element.setAttributeNode(node2) self.assert_(returnValue is None, "setAttributeNodeNS returned " + repr(returnValue)) self.assert_(self.element.hasAttributeNS("uri:bar", "ugga"), "Test for presence of created attribute returned false.") value = self.element.getAttributeNS("uri:bugga", "ugga") self.assertEqual(value, 'foo', "Incorrect attr value returned. Expected 'foo', got " + repr(value)) node = self.element.getAttributeNodeNS("uri:bugga", "ugga") self.assert_(isSameNode(node1, node), "Incorrect node returned from getAttributeNodeNS.") def checkSetAttributeNodeNSReplaceExisting(self): # Try a new node with same namespaceURI and localname, but differing # prefix. This should replace the existing node, returning it. node1 = self.document.createAttributeNS("uri:bugga", "b:ugga") self.element.setAttributeNode(node1) node2 = self.document.createAttributeNS("uri:bugga", "c:ugga") returnValue = self.element.setAttributeNodeNS(node2) self.failIf(returnValue is None, "setAttributeNodeNS did not replace original attribute") self.assert_(isSameNode(node1, returnValue), "setAttributeNodeNS returned " + repr(returnValue)) def checkSetAttributeNodeNSWrongDocument(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = foreignDoc.createAttributeNS('uri:spam', 'spam:eggs') self.assertRaises(xml.dom.WrongDocumentErr, self.element.setAttributeNodeNS, foreignAttr) def checkSetAttributeNodeNSAlreadyInUse(self): otherElement = self.document.createElement('foo') otherAttr = self.document.createAttributeNS('uri:spam', 'spam:eggs') otherElement.setAttributeNodeNS(otherAttr) self.assertRaises(xml.dom.InuseAttributeErr, self.element.setAttributeNodeNS, otherAttr) def checkRemoveAttributeNS(self): node1 = self.document.createAttributeNS("uri:bugga", "b:ugga") node2 = self.document.createAttributeNS("uri:bar", "bar:ugga") self.element.setAttributeNode(node1) self.element.setAttributeNode(node2) self.element.removeAttributeNS("uri:bugga", "ugga") self.failIf( self.element.hasAttributeNS("uri:bugga", "ugga"), "Test for presence of created attribute still returns true.") self.assert_( self.element.hasAttributeNS("uri:bar", "ugga"), "Test for presence of created attribute returned false.") def checkGetElementsByTagNameNS(self): doc = self.document el = self.element elements = {} names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for c in names: elements[c + '1'] = doc.createElementNS('uri:1', 'one:' + c) elements[c + '2'] = doc.createElementNS('uri:2', 'two:' + c) # set up simple tree elements['a1'].appendChild(elements['a2']) elements['a1'].appendChild(elements['b1']) elements['a1'].appendChild(elements['d1']) elements['b1'].appendChild(elements['b2']) elements['b1'].appendChild(elements['c1']) elements['c1'].appendChild(elements['c2']) elements['d1'].appendChild(elements['d2']) elements['d1'].appendChild(elements['e1']) elements['d1'].appendChild(elements['h1']) elements['e1'].appendChild(elements['e2']) elements['e1'].appendChild(elements['f1']) elements['e1'].appendChild(elements['g1']) elements['f1'].appendChild(elements['f2']) elements['g1'].appendChild(elements['g2']) elements['h1'].appendChild(elements['h2']) elements['h1'].appendChild(elements['i1']) elements['i1'].appendChild(elements['i2']) el.appendChild(elements['a1']) # now test # find all elements in the right order result = el.getElementsByTagNameNS('*', '*') allnames = [] add = allnames.append for name in names: add(name) add(name) self.assertEqual(len(result), len(allnames)) for name, element in map(None, allnames, result): self.assertEqual(name, element.localName) # find all elements in one namespace in the right order result = el.getElementsByTagNameNS('uri:1', '*') self.assertEqual(len(result), len(names)) for name, element in map(None, names, result): self.assertEqual(name, element.localName) # find single element, top result = el.getElementsByTagNameNS('uri:1', 'a') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'one:a') # find single element somewhere in tree result = el.getElementsByTagNameNS('uri:2', 'h') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'two:h') # find elements in the tree from all namespaces result = el.getElementsByTagNameNS('*', 'f') self.assertEqual(len(result), 2) self.assertEqual(result[0].tagName, 'one:f') self.assertEqual(result[1].tagName, 'two:f') def checkNormalize(self): doc = self.document el = self.element # Build test nodes el1 = el.appendChild(doc.createElement('e1')) el2 = el.appendChild(doc.createElement('e2')) el1.appendChild(doc.createTextNode('foo')) el1.appendChild(doc.createTextNode('bar')) el2.appendChild(doc.createTextNode('spam')) el2.appendChild(doc.createTextNode('eggs')) # Now test # Only normalize on element, sibling should be unaffected el1.normalize() checkAttribute(el1.childNodes, 'length', 1) checkAttribute(el2.childNodes, 'length', 2) checkAttribute(el1.childNodes[0], 'data', 'foobar') # Now normalize the whole test tree el.normalize() checkAttribute(el1.childNodes, 'length', 1) checkAttribute(el2.childNodes, 'length', 1) checkAttribute(el1.childNodes[0], 'data', 'foobar') checkAttribute(el2.childNodes[0], 'data', 'spameggs') # --- CharacterData class CharacterDataReadTestCaseBase(NodeReadTestCaseBase): def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) clone = foreignDoc.importNode(self.chardata, 0) deepClone = foreignDoc.importNode(self.chardata, 1) self.failIf(isSameNode(self.chardata, clone), "Clone is same as original.") self.failIf(isSameNode(self.chardata, deepClone), "Clone is same as original.") checkAttributeSameNode(clone, 'ownerDocument', foreignDoc) checkAttributeSameNode(deepClone, 'ownerDocument', foreignDoc) checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.chardata.nodeType) checkAttribute(deepClone, 'nodeType', self.chardata.nodeType) checkAttribute(clone, 'data', self.chardata.data) checkAttribute(deepClone, 'data', self.chardata.data) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, 0) class CharacterDataWriteTestCaseBase(NodeWriteTestCaseBase): pass # --- Comment class CommentReadTestCase(CharacterDataReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createComment("com") class CommentWriteTestCase(CharacterDataWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createComment("com") # --- Text class TextReadTestCase(CharacterDataReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createTextNode("com") self.expectedType = Node.TEXT_NODE class TextWriteTestCase(CharacterDataWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createTextNode("com") self.expectedType = Node.TEXT_NODE # --- Attr class AttrReadTestCase(NodeReadTestCaseBase): def setUp(self): self.attr = self.node = self.createDocument().createAttributeNS( self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) self.attrNoNS = self.nodeNoNS = self.document.createAttribute( self.TEST_LOCAL_NAME) def checkCloneNode(self): attr = self.attr clone = attr.cloneNode(0) self.failIf(isSameNode(attr, clone), "Clone is same Node as original.") checkAttribute(clone, 'localName', attr.localName) checkAttribute(clone, 'namespaceURI', attr.namespaceURI) checkAttribute(clone, 'prefix', attr.prefix) # make sure the cloned attr isn't sharing data with the original newPrefix = 'foo' newQname = '%s:%s' % (newPrefix, self.TEST_LOCAL_NAME) oldPrefix = self.attr.prefix oldQname = self.attr.name self.attr.prefix = newPrefix checkAttribute(clone, 'prefix', oldPrefix) checkAttribute(clone, 'name', oldQname) def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) clone = foreignDoc.importNode(self.attr, 0) deepClone = foreignDoc.importNode(self.attr, 1) self.failIf(isSameNode(self.attr, clone), "Clone is same as original.") self.failIf(isSameNode(self.attr, deepClone), "Clone is same as original.") checkAttributeSameNode(clone, 'ownerDocument', foreignDoc) checkAttributeSameNode(deepClone, 'ownerDocument', foreignDoc) checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.attr.nodeType) checkAttribute(deepClone, 'nodeType', self.attr.nodeType) checkAttribute(clone, 'name', self.attr.name) checkAttribute(deepClone, 'name', self.attr.name) checkAttribute(clone, 'value', self.attr.value) checkAttribute(deepClone, 'value', self.attr.value) checkAttribute(clone, 'specified', 1) checkAttribute(deepClone, 'specified', 1) checkAttribute(clone, 'nodeName', self.attr.nodeName) checkAttribute(deepClone, 'nodeName', self.attr.nodeName) checkAttribute(clone, 'nodeValue', self.attr.nodeValue) checkAttribute(deepClone, 'nodeValue', self.attr.nodeValue) checkLength(clone.childNodes, 1) # Subtree models value checkAttribute(clone.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(clone.firstChild, 'data', self.attr.value) checkLength(deepClone.childNodes, 1) checkAttribute(deepClone.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(deepClone.firstChild, 'data', self.attr.value) class AttrWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.attr = self.node = self.createDocument().createAttributeNS( self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) self.attrNoNS = self.nodeNoNS = self.document.createAttribute( self.TEST_LOCAL_NAME) def checkAttrNodePrefixMultipleRefs(self): "changing the attribute prefix should change the name of other refs" # qualified name with different prefix newPrefix = 'foo' newQname = '%s:%s' % (newPrefix, self.TEST_LOCAL_NAME) self.attr.value = 'spam' self.document.documentElement.setAttributeNode(self.attr) attr2 = self.document.documentElement.getAttributeNodeNS( self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) self.attr.prefix = newPrefix attr3 = self.document.documentElement.getAttributeNodeNS( self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) # orig attr checkAttribute(self.attr, 'nodeName', newQname) # attr gotten before set checkAttribute(attr2, 'nodeName', newQname) # attr gotten after set checkAttribute(attr3, 'nodeName', newQname) def checkElementAttrPrefixMultipleRefs(self): "changing the attribute prefix should change the name of other refs" # qualified name with different prefix newPrefix = 'foo' newQname = '%s:%s' % (newPrefix, self.TEST_LOCAL_NAME) self.attr.value = 'spam' self.document.documentElement.setAttributeNode(self.attr) attr2 = self.document.documentElement.getAttributeNodeNS( self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) # change the prefix and value of the attr. Since we're giving the same # localname and namespaceURI, the existing attr should be changed. self.document.documentElement.setAttributeNS(self.TEST_NAMESPACE, newQname, 'eggs') attr3 = self.document.documentElement.getAttributeNodeNS( self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) # element attr value = self.document.documentElement.getAttributeNS( self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) self.assertEqual( value, 'eggs', "changing prefix and value on attr didn't change original attr") # orig attr checkAttribute(self.attr, 'nodeName', newQname) # attr gotten before set checkAttribute(attr2, 'nodeName', newQname) # attr gotten after set checkAttribute(attr3, 'nodeName', newQname) # --- Default attributes class DefaultAttrTestCase(TestCaseBase): def setUp(self): self.document = self.parse(""" ]> """ % TEST_NAMESPACE) def checkCreateElementNS(self): el = self.document.createElementNS(TEST_NAMESPACE, 'doc') self.assert_(el.hasAttribute('foo'), 'Newly created Element should have default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', " "found " + repr(el.getAttribute('foo'))) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkImportNode(self): attr = self.document.documentElement.getAttributeNode('foo') newDoc = self.implementation.createDocument(None, 'baz', None) importedAttr = newDoc.importNode(attr, 0) checkAttribute(importedAttr, 'specified', 1) def checkImportNodeFromDefault(self): newDoc = self.implementation.createDocument(None, 'baz', None) el = newDoc.importNode(self.document.documentElement, 0) self.failIf(el.hasAttribute('foo'), "Default attribute retained when importing into document" " that doesn't specify the default attribute.") def checkImportNodeToDefault(self): newDoc = self.implementation.createDocument(None, 'baz', None) newEl = newDoc.createElementNS(TEST_NAMESPACE, 'doc') el = self.document.importNode(newEl, 0) self.assert_( el.hasAttribute('foo'), 'Imported Element Node should have default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found " + repr(el.getAttribute('foo'))) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) class DefaultAttrWithPrefixTestCase(TestCaseBase): def setUp(self): self.document = self.parse(""" ]> """ % TEST_NAMESPACE) def checkHasAttributeNS(self): el = self.document.documentElement self.assert_(el.hasAttributeNS(TEST_NAMESPACE, 'foo'), 'Default attribute not found.') def checkGetAttributeNS(self): el = self.document.documentElement self.assertEqual( el.getAttributeNS(TEST_NAMESPACE, 'foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found " + repr(el.getAttributeNS(TEST_NAMESPACE, 'foo'))) def checkCreateElementNS(self): el = self.document.createElementNS(TEST_NAMESPACE, 'doc') self.assert_( el.hasAttributeNS(TEST_NAMESPACE, 'foo'), 'Newly created Element Node should have default attribute.') self.assertEqual( el.getAttributeNS(TEST_NAMESPACE, 'foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found " + repr(el.getAttributeNS(TEST_NAMESPACE, 'foo'))) checkAttribute(el.getAttributeNodeNS(TEST_NAMESPACE, 'foo'), 'specified', 0) def checkImportNodeToDefault(self): newDoc = self.implementation.createDocument(None, 'baz', None) newEl = newDoc.createElementNS(TEST_NAMESPACE, 'prefix:doc') el = self.document.importNode(newEl, 0) self.assert_( el.hasAttributeNS(TEST_NAMESPACE, 'foo'), 'Imported Element Node should have default attribute.') self.assertEqual( el.getAttributeNS(TEST_NAMESPACE, 'foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found " + repr(el.getAttributeNS(TEST_NAMESPACE, 'foo'))) checkAttribute(el.getAttributeNodeNS(TEST_NAMESPACE, 'foo'), 'specified', 0) def checkChangePrefixUnspecified(self): attr = self.document.documentElement.getAttributeNodeNS( TEST_NAMESPACE, 'foo') attr.prefix = 'test' # Changing the prefix of a default attribute shouldn't make a new # unspecified (default) attribute node appear. # TODO: It turns out this may be a hole in the spec. See PXML(60)[]: # http://www.zope.org/Members/karl/ParsedXML/ParsedXMLTracker/60 # Waiting for consensus from DOM WG. Changing the prefix *should* make # a new Attr node appear it seems. I am not convinced yet. self.assertEqual( attr.ownerElement.attributes.length, 1, "Changing the prefix of a default attribute caused a new default " "attribute node to be created.") # The specified flag shouldn't change; we didn't change the value checkAttribute(attr, 'specified', 0) def checkChangePrefixSpecified(self): self.document.documentElement.setAttributeNS( TEST_NAMESPACE, 'foo', 'newValue') attr = self.document.documentElement.getAttributeNodeNS( TEST_NAMESPACE, 'foo') attr.prefix = 'test' # Changing the prefix of a specified attribute shouldn't make a new # unspecified (default) attribute node appear. self.assertEqual( attr.ownerElement.attributes.length, 2, "Changing the prefix of a specified attribute caused a new " "default attribute node to be created.") def checkRemoveAttributeNS(self): el = self.document.documentElement # Replace default with specified attr el.setAttributeNS(TEST_NAMESPACE, 'foo', 'baz') el.removeAttributeNS(TEST_NAMESPACE, 'foo') self.assert_( el.hasAttributeNS(TEST_NAMESPACE, 'foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttributeNS(TEST_NAMESPACE, 'foo'), 'bar', "Wrong value of default attribute foud, expected 'bar', found " + repr(el.getAttributeNS(TEST_NAMESPACE, 'foo'))) checkAttribute(el.getAttributeNodeNS(TEST_NAMESPACE, 'foo'), 'specified', 0) def checkRemoveAttributeNode(self): el = self.document.documentElement newAttr = self.document.createAttributeNS(TEST_NAMESPACE, 'foo') newAttr.value = 'baz' # Replace default with specified attr el.setAttributeNodeNS(newAttr) el.removeAttributeNode(newAttr) self.assert_( el.hasAttributeNS(TEST_NAMESPACE, 'foo'), 'Removing specified attribute should restore default attribute.') self.assert_( el.getAttributeNS(TEST_NAMESPACE, 'foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found " + repr(el.getAttributeNS(TEST_NAMESPACE, 'foo'))) checkAttribute(el.getAttributeNodeNS(TEST_NAMESPACE, 'foo'), 'specified', 0) def checkRemoveNamedItemNS(self): el = self.document.documentElement # Replace default with specified attr el.setAttributeNS(TEST_NAMESPACE, 'foo', 'baz') el.attributes.removeNamedItemNS(TEST_NAMESPACE, 'foo') self.assert_( el.hasAttributeNS(TEST_NAMESPACE, 'foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttributeNS(TEST_NAMESPACE, 'foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found " + repr(el.getAttributeNS(TEST_NAMESPACE, 'foo'))) checkAttribute(el.getAttributeNodeNS(TEST_NAMESPACE, 'foo'), 'specified', 0) def checkSetAttributeNS(self): el = self.document.documentElement el.setAttributeNS(TEST_NAMESPACE, 'foo', 'baz') checkAttribute(el.getAttributeNodeNS(TEST_NAMESPACE, 'foo'), 'specified', 1) def checkSetAttributeNodeNS(self): el = self.document.documentElement newAttr = self.document.createAttributeNS(TEST_NAMESPACE, 'foo') newAttr.value = 'baz' el.setAttributeNode(newAttr) checkAttribute(el.getAttributeNodeNS(TEST_NAMESPACE, 'foo'), 'specified', 1) # --- DocumentFragment class DocumentFragmentReadTestCase(NodeReadTestCaseBase): def setUp(self): self.docfrag = self.createDocument().createDocumentFragment() self.node = self.docfrag def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) frag = self.docfrag frag.appendChild(self.document.createComment('foo')) frag.appendChild(self.document.createTextNode('bar')) clone = foreignDoc.importNode(frag, 0) deepClone = foreignDoc.importNode(frag, 1) self.failIf(isSameNode(frag, clone), "Clone is same Node as original.") self.failIf(isSameNode(frag, deepClone), "Clone is same Node as original.") checkAttributeSameNode(clone, 'ownerDocument', foreignDoc) checkAttributeSameNode(deepClone, 'ownerDocument', foreignDoc) checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, frag.childNodes.length) for i in range(deepClone.childNodes.length): checkAttribute(deepClone.childNodes.item(i), 'nodeType', frag.childNodes.item(i).nodeType) checkAttribute(deepClone.childNodes.item(i), 'data', frag.childNodes.item(i).data) checkAttributeSameNode(deepClone.childNodes.item(i), 'ownerDocument', foreignDoc) class DocumentFragmentWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.docfrag = self.createDocument().createDocumentFragment() self.node = self.docfrag # --- NamedNodeMap class NamedNodeMapWriteTestCase(TestCaseBase): TEST_NAMESPACE = NodeReadTestCaseBase.TEST_NAMESPACE TEST_PREFIX = NodeReadTestCaseBase.TEST_PREFIX TEST_LOCAL_NAME = NodeReadTestCaseBase.TEST_LOCAL_NAME TEST_QUALIFIED_NAME = NodeReadTestCaseBase.TEST_QUALIFIED_NAME def setUp(self): self.map = self.createDocument().createElement("foo")._get_attributes() self.attribute = self.document.createAttributeNS(self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) self.attribute.value = "attrValue" self.map.setNamedItemNS(self.attribute) def checkGetNamedItemNS(self): node = self.map.getNamedItemNS(self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) self.assert_(node is not None, "getNamedItemNS didn't retrieve attribute.") self.assert_(isSameNode(node, self.attribute), "getNamedItemNS retrieved incorrect attribute.") def checkGetNamedItemNSWrongNamespace(self): node = self.map.getNamedItemNS('uri:foo', self.TEST_LOCAL_NAME) self.assert_(node is None, "getNamedItemNS returned an attribute.") def checkGetNamedItemNSWrongLocalname(self): node = self.map.getNamedItemNS(self.TEST_NAMESPACE, 'bar') self.assert_(node is None, "getNamedItemNS returned an attribute.") def checkRemoveNamedItemNS(self): node = self.map.removeNamedItemNS(self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) self.assert_(node is not None, "removeNamedItemNS didn't return an attribute.") self.assert_(isSameNode(node, self.attribute), "removeNamedItemNS returned incorrect attribute.") n = self.map.getNamedItemNS(self.TEST_NAMESPACE, self.TEST_LOCAL_NAME) self.assert_(n is None, "Attribute was not removed.") checkLength(self.map, 0) def checkRemoveNamedItemNSNotFound(self): # Exceptions self.assertRaises(xml.dom.NotFoundErr, self.map.removeNamedItemNS, 'uri:foo', 'bar:baz') def checkSetNamedItemNS(self): newAttr = self.document.createAttributeNS(self.TEST_NAMESPACE, 'qname:someAttr') newAttr.value = 'spam' retVal = self.map.setNamedItemNS(newAttr) self.assert_(retVal is None, "setNamedItemNS returned " + repr(retVal)) checkLength(self.map, 2) n = self.map.getNamedItemNS(self.TEST_NAMESPACE, 'someAttr') self.assert_( isSameNode(n, newAttr), "setNamedItemNS store seems to have failed, can't retrieve.") def checkSetNamedItemNSReplaceExisting(self): newAttr = self.document.createAttributeNS(self.TEST_NAMESPACE, 'qname:someAttr') self.map.setNamedItemNS(newAttr) anotherAttr = self.document.createAttributeNS(self.TEST_NAMESPACE, 'anotherQN:someAttr') anotherAttr.value = 'eggs' retVal = self.map.setNamedItemNS(newAttr) self.failIf(retVal is None, "setNamedItemNS returned None") self.assert_(isSameNode(retVal, newAttr), "setNamedItemNS didn't return replaced Node.") checkLength(self.map, 2) def checkSetNamedItemNSWrongDocument(self): newDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = newDoc.createAttributeNS( self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) self.assertRaises(xml.dom.WrongDocumentErr, self.map.setNamedItem, foreignAttr) def checkSetNamedItemNSAlreadyInUse(self): el = self.document.createElement('someElement') attr = self.document.createAttributeNS( self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) el.setAttributeNode(attr) self.assertRaises(xml.dom.InuseAttributeErr, self.map.setNamedItem, attr) def checkSetNamedItemNSHierarchyRequestErr(self): # See DOM erratum core-4. element = self.document.createElementNS(TEST_NAMESPACE, 'foo:bar') self.assertRaises(xml.dom.HierarchyRequestErr, self.map.setNamedItemNS, element) cases = buildCases(__name__, 'Core', '2.0') PyXML-0.8.2/test/domapi/CoreLvl3.py0100644000076400001440000000253107534565153016161 0ustar martinusers"""Test cases for DOM Core Level 3.""" import xml.dom import Base class WhitespaceInElementContentTestCase(Base.TestCaseBase): def checkWhiteSpaceInElementContent(self): TEXT = """ ]> """ doc = self.parse(TEXT) for node in doc.documentElement.childNodes: if node.nodeType == xml.dom.Node.TEXT_NODE: if not node.isWhitespaceInElementContent: self.fail("founc whitespace node not identified" " as whitespace-in-element-contnet") def checkWhiteSpaceInUnknownContent(self, subset=""): TEXT = """ """ % subset doc = self.parse(TEXT) for node in doc.documentElement.childNodes: if node.nodeType == xml.dom.Node.TEXT_NODE: if node.isWhitespaceInElementContent: self.fail("founc whitespace node in mixed content marked" " as whitespace-in-element-contnet") def _checkWhiteSpaceInMixedContent(self): # XXX this test is confused self.checkWhiteSpaceInUnknownContent("""[ ]""") cases = Base.buildCases(__name__, 'Core', '3.0') PyXML-0.8.2/test/domapi/Load3.py0100644000076400001440000002470007534565153015474 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Tests for the 'Load' part of the Load/Save component from DOM Level 3. Note that the Load/Save component is a working draft and not a final recommendation. """ import xml.dom import Base # select the right StringIO try: unicode except NameError: try: from cStringIO import StringIO except: from StringIO import StringIO else: # cStringIO has no support for Unicode strings from StringIO import StringIO class BuilderTestCaseBase(Base.TestCaseBase): def createBuilder(self): return self.implementation.createDOMBuilder( self.implementation.MODE_SYNCHRONOUS, None) class BuilderFeatureConformanceTestCase(BuilderTestCaseBase): """Test that the DOMBuilder has the defaults and allows setting all features required by the W3C specification. The features are not exercised, but every value that is required to be supported is tested and set. """ FEATURES = { # feature-name: (default, must-support-true, must-support-false) "namespaces": (1, 1, 0), "namespace-declarations": (1, 1, 0), "validation": (0, 0, 1), "external-general-entities": (1, 1, 0), "external-parameter-entities": (1, 1, 0), "validate-if-schema": (0, 0, 1), "create-entity-ref-nodes": (1, 1, 0), "entities": (1, 1, 0), "whitespace-in-element-content": (1, 1, 0), "cdata-sections": (1, 1, 0), "comments": (1, 1, 1), "charset-overrides-xml-encoding": (1, 1, 1), } def checkFeatureDefaults(self): for item in self.FEATURES.items(): feature, (default, xxx, xxx) = item b = self.createBuilder() value = b.getFeature(feature) and 1 or 0 self.assert_(value == default, "default feature value not right") def checkRequiredFeatureSettings(self): for item in self.FEATURES.items(): feature, (xxx, require_true, require_false) = item b = self.createBuilder() if require_true: self.assert_(b.canSetFeature(feature, 1), "builder indicates feature cannot be enabled") b.setFeature(feature, 1) self.assert_(b.getFeature(feature), "enabling feature failed") if require_false: self.assert_(b.canSetFeature(feature, 0), "builder indicates feature cannot be disabled") b.setFeature(feature, 0) self.assert_(not b.getFeature(feature), "disabling feature failed") def checkSupportsFeatures(self): b = self.createBuilder() for feature in self.FEATURES.keys(): self.assert_(b.supportsFeature(feature), "builder reports non-support for required feature") def checkEntityNodesFeatureSideEffect(self): b = self.createBuilder() b.setFeature("entities", 0) self.assert_(not b.getFeature("create-entity-ref-nodes"), "setting entities to false should turn off" " create-entity-ref-nodes") def checkUnknownFeature(self): b = self.createBuilder() self.assertRaises(xml.dom.NotFoundErr, b.setFeature, "non-existant-feature", 0) self.assertRaises(xml.dom.NotFoundErr, b.getFeature, "non-existant-feature") self.assert_(not b.supportsFeature("non-existant-feature"), "expected non-existant-feature to raise" " xml.dom.NotFoundErr") self.assert_(not b.canSetFeature("non-existant-feature", 0), "builder allows setting of non-existant feature" " to false") self.assert_(not b.canSetFeature("non-existant-feature", 1), "builder allows setting of non-existant feature" " to true") def checkWhiteSpaceInElementContentDiscarded(self): TEXT = """ ]> """ doc = self._parse(TEXT, {"whitespace-in-element-content": 0}) for node in doc.documentElement.childNodes: if node.nodeType == xml.dom.Node.TEXT_NODE: self.fail("found whitespace-in-element-content node which" " should bave been excluded") def checkCommentsOmitted(self): doc = self._parse("", {"comments": 0}) self.assert_(doc.documentElement.childNodes.length == 0, "comment node was returned as part of the document") def checkCDATAAsText(self): doc = self._parse(">]]>", {"cdata-sections": 0}) self.assert_(doc.documentElement.childNodes[0].data == "<>") self.assert_(doc.documentElement.childNodes.length == 1) def checkWithoutNamespaces(self): doc = self._parse("" " " "", {"namespaces": 0}) docelem = doc.documentElement self.assert_(docelem.namespaceURI is None) self.assert_(docelem.prefix is None) self.assert_(docelem.getAttributeNode("xmlns").namespaceURI is None) self.assert_(docelem.getAttributeNode("xmlns").prefix is None) self.assert_(docelem.getAttributeNode("tal:attr").namespaceURI is None) self.assert_(docelem.getAttributeNode("tal:attr").prefix is None) elem = docelem.firstChild self.assert_(elem.namespaceURI is None) self.assert_(elem.prefix is None) def checkWithoutNamespaceDeclarations(self): doc = self._parse("" "" "", {"namespace-declarations": 0}) docelem = doc.documentElement self.failIf(docelem.hasAttribute("xmlns")) self.failIf(docelem.hasAttribute("xmlns:tal")) self.assert_(docelem.attributes.length == 1) # We can't just name this parse(), since the framework overwrites # that name on the actual instances. # def _parse(self, source, flags={}): b = self.createBuilder() for feature, value in flags.items(): b.setFeature(feature, value) fp = StringIO(source) inpsrc = self.implementation.createDOMInputSource() inpsrc.byteStream = fp return b.parse(inpsrc) cases = Base.buildCases(__name__, "LS-Load", "3.0") PyXML-0.8.2/test/domapi/TraversalLvl2.py0100644000076400001440000005642707534565153017250 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * import xml.dom from xml.dom import Node # --- NodeFilter interface. Should this be in xml.dom.__init__? class NodeFilter: # Constants returned by acceptNode FILTER_ACCEPT = 1 FILTER_REJECT = 2 FILTER_SKIP = 3 # Constants for whatToShow SHOW_ALL = 0xFFFFFFFF SHOW_ELEMENT = 0x00000001 SHOW_ATTRIBUTE = 0x00000002 SHOW_TEXT = 0x00000004 SHOW_CDATA_SECTION = 0x00000008 SHOW_ENTITY_REFERENCE = 0x00000010 SHOW_ENTITY = 0x00000020 SHOW_PROCESSING_INSTRUCTION = 0x00000040 SHOW_COMMENT = 0x00000080 SHOW_DOCUMENT = 0x00000100 SHOW_DOCUMENT_TYPE = 0x00000200 SHOW_DOCUMENT_FRAGMENT = 0x00000400 SHOW_NOTATION = 0x00000800 def acceptNode(self, node): # By default, accept return self.FILTER_ACCEPT # --- DocumentTraversal class DocumentTraversalReadTestCase(TestCaseBase): def setUp(self): self.createDocumentNS() def checkCreateNodeIterator(self): root = self.document whatToShow = NodeFilter.SHOW_ALL filter = NodeFilter() iterator = self.document.createNodeIterator( root, whatToShow, filter, 1) checkAttributeSameNode(iterator, 'root', root) checkAttribute(iterator, 'whatToShow', whatToShow) self.assert_( iterator.filter is filter, "Created iterator has got a different filter object. Expected %s," " found %s." % (repr(filter), repr(iterator.filter))) checkAttribute(iterator, 'expandEntityReferences', 1) def checkCreateNodeIteratorNoRoot(self): self.assertRaises(xml.dom.NotSupportedErr, self.document.createNodeIterator, None, NodeFilter.SHOW_ALL, None, 0) def checkCreateTreeWalker(self): root = self.document whatToShow = NodeFilter.SHOW_ALL filter = NodeFilter() walker = self.document.createTreeWalker(root, whatToShow, filter, 1) checkAttributeSameNode(walker, 'root', root) checkAttribute(walker, 'whatToShow', whatToShow) self.assert_( walker.filter is filter, "Created walker has got a different filter object. Expected %s," " found %s." % (repr(filter), repr(walker.filter))) checkAttribute(walker, 'expandEntityReferences', 1) def checkCreateTreeWalkerNoRoot(self): self.assertRaises(xml.dom.NotSupportedErr, self.document.createTreeWalker, None, NodeFilter.SHOW_ALL, None, 0) # --- NodeIterator class NodeIteratorTestCase(TestCaseBase): def setUp(self): # Create a tree of elements. Alphabetic order denotes document order. docType = self.implementation.createDocumentType('A', None, None) self.document = doc = self.implementation.createDocument( None, 'A', docType) self.A = a = doc.documentElement self.B = a.appendChild(doc.createTextNode('B')) self.C = c = a.appendChild(doc.createElement('C')) self.D = c.appendChild(doc.createCDATASection('D')) self.E = c.appendChild(doc.createProcessingInstruction('E', 'A PI')) self.F = a.appendChild(doc.createComment('F')) self.G = a.appendChild(doc.createTextNode('G')) self.all = (doc, docType, a, self.B, c, self.D, self.E, self.F, self.G) def iterate(self, iterator, expectedNodes): all = expectedNodes[:] while 1: nextNode = iterator.nextNode() if nextNode is None: self.failIf(all, "nextNode returned None before end, still expected" " to see %s." % `all`) self.assert_(all, "nextNode returned %s; expected None." % `nextNode`) expect = all.pop(0) self.assert_( isSameNode(expect, nextNode), "nextNode returned %s, expected %s." % (`nextNode`, `expect`)) all = expectedNodes[:] while 1: previousNode = iterator.previousNode() if previousNode is None: self.failIf(all, "previousNode returned None before end, still" " expected to see %s." % `all`) self.assert_(all, "previousNode returned %s; expected None." % `previousNode`) expect = all.pop() self.assert_(isSameNode(expect, previousNode), "previousNode returned %s, expected %s." % (repr(previousNode), repr(expect))) def checkIteratorNoFilter(self): iterator = self.document.createNodeIterator( self.document, NodeFilter.SHOW_ALL, None, 0) self.iterate(iterator, list(self.all)) def checkIteratorOnlyTextNodes(self): iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_TEXT, None, 0) self.iterate(iterator, [self.B, self.G]) def checkIteratorAllButTextNodes(self): iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_ALL ^ NodeFilter.SHOW_TEXT, None, 0) self.iterate(iterator, list(self.all[:3] + self.all[4:8])) def checkIteratorFilterSkipC(self): class SkipCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_SKIP else: return self.FILTER_ACCEPT iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_ALL, SkipCFilter(), 0) self.iterate(iterator, list(self.all[:4] + self.all[5:])) def checkIteratorFilterRejectC(self): class RejectCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_REJECT else: return self.FILTER_ACCEPT iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_ALL, RejectCFilter(), 0) self.iterate(iterator, list(self.all[:4] + self.all[5:])) def checkIteratorOnlyTextNodesFilterSkipG(self): class SkipGFilter(NodeFilter): def acceptNode(self, node): if node.nodeValue == 'G': return self.FILTER_SKIP else: return self.FILTER_ACCEPT iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_TEXT, SkipGFilter(), 0) self.iterate(iterator, [self.B]) def checkIteratorPreviousNode(self): iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_ALL, None, 0) self.assert_(iterator.previousNode() is None, "previousNode on a fresh iterator did not return None.") def checkIteratorNextNodeInvalidState(self): iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_ALL, None, 0) iterator.detach() self.assertRaises(xml.dom.InvalidStateErr, iterator.nextNode) def checkIteratorPreviousNodeInvalidState(self): iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_ALL, None, 0) iterator.detach() self.assertRaises(xml.dom.InvalidStateErr, iterator.previousNode) def checkIteratorFilterException(self): class ExceptionFilter(NodeFilter): def acceptNode(self, node): raise KeyError, ( "Test exception to see if it will propagate.") iterator = self.document.createNodeIterator(self.document, NodeFilter.SHOW_ALL, ExceptionFilter(), 0) self.assertRaises(KeyError, iterator.nextNode) # -- TreeWalker class TreeWalkerTestCase(TestCaseBase): def setUp(self): # Create a tree of elements. Alphabetic order denotes document order. docType = self.implementation.createDocumentType('A', None, None) self.document = doc = self.implementation.createDocument(None, 'A', docType) self.A = a = doc.documentElement self.B = a.appendChild(doc.createTextNode('B')) self.C = c = a.appendChild(doc.createElement('C')) self.D = c.appendChild(doc.createCDATASection('D')) self.E = c.appendChild(doc.createProcessingInstruction('E', 'A PI')) self.F = a.appendChild(doc.createComment('F')) self.G = a.appendChild(doc.createTextNode('G')) self.all = (doc, docType, a, self.B, c, self.D, self.E, self.F, self.G) def iterate(self, walker, advanceMethod, retreatMethod, expectedNodesNext, expectedNodesPrevious = None): "Exercise methods given in advanceMethod, retreatMethod" if not expectedNodesPrevious: expectedNodesPrevious = expectedNodesNext all = expectedNodesNext[:] current = walker.currentNode while 1: if current is None: self.failIf(all, "%s returned None before end, still expected to " "see %s. TreeWalker.currentNode is %s." % ( advanceMethod, `all`, `walker.currentNode`)) self.assert_(all, "%s returned %s when we should've gotten None. " "TreeWalker.currentNode is %s." % ( advanceMethod, `current`, `walker.currentNode`)) expect = all.pop(0) self.assert_( isSameNode(expect, current), "%s returned %s, expected %s. TreeWalker.currentNode is %s." % (advanceMethod, `current`, `expect`, `walker.currentNode`)) current = getattr(walker, advanceMethod)() all = expectedNodesPrevious[:] current = walker.currentNode while 1: if current is None: self.failIf(all, "%s returned None before end, still expected to " "see %s. TreeWalker.currentNode is %s." % ( retreatMethod, `all`, `walker.currentNode`)) self.assert_(all, "%s returned %s when we should've gotten None. " "TreeWalker.currentNode is %s." % ( retreatMethod, `current`, `walker.currentNode`)) expect = all.pop() self.assert_( isSameNode(expect, current), "%s returned %s, expected %s. TreeWalker.currentNode is %s." % (retreatMethod, `current`, `expect`, `walker.currentNode`)) current = getattr(walker, retreatMethod)() def checkWalkerNoFilterIterate(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) self.iterate(walker, "nextNode", "previousNode", list(self.all)) def checkWalkerOnlyTextNodesIterate(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_TEXT, None, 0) self.iterate(walker, "nextNode", "previousNode", [self.document, self.B, self.G], [self.B, self.G]) def checkWalkerAllButTextNodesIterate(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL ^ NodeFilter.SHOW_TEXT, None, 0) self.iterate(walker, "nextNode", "previousNode", list(self.all[:3] + self.all[4:8])) def checkWalkerFilterSkipCIterate(self): class SkipCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_SKIP else: return self.FILTER_ACCEPT walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, SkipCFilter(), 0) self.iterate(walker, "nextNode", "previousNode", list(self.all[:4] + self.all[5:])) def checkWalkerFilterRejectCIterate(self): class RejectCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_REJECT else: return self.FILTER_ACCEPT walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, RejectCFilter(), 0) self.iterate(walker, "nextNode", "previousNode", list(self.all[:4] + self.all[7:])) def checkWalkerOnlyTextNodesFilterSkipG(self): class SkipGFilter(NodeFilter): def acceptNode(self, node): if node.nodeValue == 'G': return self.FILTER_SKIP else: return self.FILTER_ACCEPT walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_TEXT, SkipGFilter(), 0) self.iterate(walker, "nextNode", "previousNode", [self.document, self.B], [self.B,]) def checkWalkerNoFilterParentNodeFirstChild(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) self.assert_(walker.parentNode() is None, "parentNode on a fresh walker did not return None.") walker.firstChild() # doctype walker.nextSibling() # A walker.firstChild() # B walker.nextSibling() # C walker.firstChild() # D self.iterate(walker, "parentNode", "firstChild", [self.D, self.C, self.A, self.document], [self.document.doctype, self.document],) def checkWalkerOnlyTextNodesParentNodeFirstChild(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_TEXT, None, 0) self.iterate(walker, "firstChild", "parentNode", [self.document]) def checkWalkerAllButTextNodesParentNodeFirstChild(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL ^ NodeFilter.SHOW_TEXT, None, 0) walker.firstChild() # doctype walker.nextSibling() # A self.iterate(walker, "firstChild", "parentNode", [self.A, self.C, self.D], [self.document, self.A, self.C, self.D],) # "first visible child" might be seen to imply "first child that # is visible", rather than "first visible descendent", but the # examples skip to descendents. def checkWalkerFilterSkipCFirstChild(self): class SkipCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_SKIP else: return self.FILTER_ACCEPT self.A.removeChild(self.B) walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, SkipCFilter(), 0) walker.firstChild() # doctype walker.nextSibling() # A self.iterate(walker, "firstChild", "parentNode", [self.A, self.D], [self.document, self.A, self.D]) # also checks parentNode robustness under currentNode move def checkWalkerFilterSkipCParentNode(self): class SkipCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_SKIP else: return self.FILTER_ACCEPT walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, SkipCFilter(), 0) walker.firstChild() # doctype walker.nextSibling() # A walker.firstChild() # B self.C.appendChild(self.B) self.iterate(walker, "parentNode", "firstChild", [self.B, self.A, self.document], [self.document.doctype, self.document]) def checkWalkerFilterRejectCFirstChild(self): class RejectCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_REJECT else: return self.FILTER_ACCEPT self.A.removeChild(self.B) walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, RejectCFilter(), 0) walker.firstChild() # doctype walker.nextSibling() # A self.iterate(walker, "firstChild", "parentNode", [self.A, self.F], [self.document, self.A, self.F]) # also tests parentNode robustness under currentNode move def checkWalkerFilterRejectCParentNode(self): class RejectCFilter(NodeFilter): def acceptNode(self, node): if node.nodeName == 'C': return self.FILTER_REJECT else: return self.FILTER_ACCEPT walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, RejectCFilter(), 0) walker.firstChild() # doctype walker.nextSibling() # A walker.firstChild() # B self.C.appendChild(self.B) self.iterate(walker, "parentNode", "firstChild", [self.B, self.A, self.document], [self.document.doctype, self.document]) def checkWalkerOnlyTextNodesParentNodeFirstChildFilterSkipB(self): class SkipBFilter(NodeFilter): def acceptNode(self, node): if node.nodeValue == 'B': return self.FILTER_SKIP else: return self.FILTER_ACCEPT walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_TEXT, SkipBFilter(), 0) self.iterate(walker, "firstChild", "parentNode", [self.document, self.G]) def checkWalkerNoFilterNextSiblingPreviousSibling(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) self.assert_(walker.previousSibling() is None, "previousSibling on a fresh walker did not return None.") # move to B to make more interesting walker.firstChild() # doctype walker.nextSibling() # A walker.firstChild() # B self.iterate(walker, "nextSibling", "previousSibling", [self.B, self.C, self.F, self.G]) def checkWalkerNoFilterLastChild(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) # move to A to make more interesting walker.firstChild() # doctype walker.nextSibling() # A retNode = walker.lastChild() self.assert_(isSameNode(retNode, walker.currentNode)) self.assert_(isSameNode(self.G, walker.currentNode)) def checkWalkerPreviousNode(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) self.assert_(walker.previousNode() is None, "previousNode on a fresh walker did not return None.") def checkCurrentNodeNoneNotSupported(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) try: walker.currentNode = None except xml.dom.NotSupportedErr: pass else: self.fail("Was allowed to set currentNode to None.") cases = buildCases(__name__, 'Traversal', '2.0') PyXML-0.8.2/test/domapi/XMLLvl1.py0100644000076400001440000003517007534565153015734 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * from CoreLvl1 import NodeReadTestCaseBase, NodeWriteTestCaseBase from CoreLvl1 import TextReadTestCase, TextWriteTestCase TextReadTestCaseBase = TextReadTestCase TextWriteTestCaseBase = TextWriteTestCase del TextReadTestCase del TextWriteTestCase import xml.dom from xml.dom import Node # --- DocumentType class DocumentTypeReadTestCase(NodeReadTestCaseBase): def setUp(self): self.doctype = self.node = self.implementation.createDocumentType( 'foo', None, None) self.expectedType = Node.DOCUMENT_TYPE_NODE doc = self.parse(""" ]> """) self.doctypeInternalSubset = doc.doctype def checkName(self): checkAttribute(self.doctype, 'name', 'foo') checkReadOnly(self.doctype, 'name') def checkEmptyEntities(self): self.assertEqual(self.doctype.entities.length, 0) self.assertEqual(len(self.doctype.entities), 0) def checkEntitiesInternalSubset(self): checkLength(self.doctypeInternalSubset.entities, 3) entity = self.doctypeInternalSubset.entities.getNamedItem( 'internalParsedE') def checkEntitiesRemoveReadOnly(self): self.assertRaises( xml.dom.NoModificationAllowedErr, self.doctypeInternalSubset.entities.removeNamedItem, 'internalParsedE') def checkEntitiesSetReadOnly(self): entity = self.doctypeInternalSubset.entities.item(0) self.assertRaises( xml.dom.NoModificationAllowedErr, self.doctypeInternalSubset.entities.setNamedItem, entity) def checkEmptyNotations(self): self.assertEqual(self.doctype.notations.length, 0) self.assertEqual(len(self.doctype.notations), 0) def checkNotationsInternalSubset(self): checkLength(self.doctypeInternalSubset.notations, 1) notation = self.doctypeInternalSubset.notations.getNamedItem( 'aNotation') def checkNotationsRemoveReadOnly(self): self.assertRaises( xml.dom.NoModificationAllowedErr, self.doctypeInternalSubset.notations.removeNamedItem, 'aNotation') def checkNotationsSetReadOnly(self): notation = self.doctypeInternalSubset.notations.item(0) self.assertRaises( xml.dom.NoModificationAllowedErr, self.doctypeInternalSubset.notations.setNamedItem, notation) def checkCloneNode(self): # TODO: Implementation dependent, what should we test? pass class DocumentTypeWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.createDocument() # Needed for Node tests self.doctype = self.node = self.implementation.createDocumentType( 'foo', None, None) # --- ProcessingInstruction class ProcessingInstructionReadTestCase(NodeReadTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi self.expectedType = Node.PROCESSING_INSTRUCTION_NODE def checkGetTarget(self): checkAttribute(self.pi, "target", "pit") def checkGetData(self): checkAttribute(self.pi, "data", "pid") def checkCloneNode(self): clone = self.pi.cloneNode(0) deepClone = self.pi.cloneNode(1) self.failIf(isSameNode(self.pi, clone), "Clone is same as original.") self.failIf(isSameNode(self.pi, deepClone), "Clone is same as original.") checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.pi.nodeType) checkAttribute(deepClone, 'nodeType', self.pi.nodeType) checkAttribute(clone, 'data', self.pi.data) checkAttribute(deepClone, 'data', self.pi.data) checkAttribute(clone, 'target', self.pi.target) checkAttribute(deepClone, 'target', self.pi.target) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, 0) class ProcessingInstructionWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi def checkSetData(self): self.pi._set_data("uggg") checkAttribute(self.pi, "data", "uggg") # --- CDATASection class CDATASectionReadTestCase(TextReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") self.expectedType = Node.CDATA_SECTION_NODE class CDATASectionWriteTestCase(TextWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") # --- EntityReference class EntityReferenceReadTestCase(NodeReadTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") self.expectedType = Node.ENTITY_REFERENCE_NODE self.expectedNodeName = 'eref' def checkCloneNode(self): pass # TODO: Fill in meaningful test here. class EntityReferenceWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") # TODO: An ENTITY_REFERENCE_NODE Node will have childNodes when the # entity it refers to has childNodes. We need entities first before we write # tests for that. # --- Entity class EntityReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = self.internalParsed = doc.doctype.entities.getNamedItem( 'internalParsedE') self.publicUnparsed = doc.doctype.entities.getNamedItem( 'publicUnparsedE') self.systemUnparsed = doc.doctype.entities.getNamedItem( 'systemUnparsedE') self.expectedNodeName = 'internalParsedE' self.expectedType = Node.ENTITY_NODE def checkPublicIdReadOnly(self): checkReadOnly(self.node, 'publicId') def checkPublicIdInternalParsed(self): checkAttribute(self.internalParsed, 'publicId', None) def checkPublicIdPublicUnparsed(self): checkAttribute(self.publicUnparsed, 'publicId', 'uri:public') def checkPublicIdSystemUnparsed(self): checkAttribute(self.systemUnparsed, 'publicId', None) def checkSystemIdReadOnly(self): checkReadOnly(self.node, 'systemId') def checkSystemIdInternalParsed(self): checkAttribute(self.internalParsed, 'systemId', None) def checkSystemIdPublicUnparsed(self): checkAttribute(self.publicUnparsed, 'systemId', 'uri:system') def checkSystemIdSystemUnparsed(self): checkAttribute(self.systemUnparsed, 'systemId', 'uri:system') def checkNotationNameReadOnly(self): checkReadOnly(self.node, 'notationName') def checkNotationNameInternalParsed(self): checkAttribute(self.internalParsed, 'notationName', None) def checkNotationNamePublicUnparsed(self): checkAttribute(self.publicUnparsed, 'notationName', 'aNotation') def checkNotationNameSystemUnparsed(self): checkAttribute(self.systemUnparsed, 'notationName', 'aNotation') def checkSubTreeInternalParsed(self): entity = self.internalParsed self.assert_( entity.hasChildNodes(), 'Internal Parsed Entity has no subtree representing the value.') checkAttribute(entity.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(entity.firstChild, 'data', 'Entity text') checkReadOnly(entity.firstChild, 'data') def checkSubTreePublicUnparsed(self): self.failIf(self.publicUnparsed.hasChildNodes(), 'An unparsed entity should not have a sub-tree.') def checkSubTreeSystemUnparsed(self): self.failIf(self.systemUnparsed.hasChildNodes(), 'An unparsed entity should not have a sub-tree.') class EntityWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.entities.getNamedItem('internalParsedE') # --- Notation class NotationReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = self.publicExternal = doc.doctype.notations.getNamedItem( 'publicExternalN') self.systemExternal = doc.doctype.notations.getNamedItem( 'systemExternalN') self.public = doc.doctype.notations.getNamedItem('publicN') self.expectedNodeName = 'publicExternalN' self.expectedType = Node.NOTATION_NODE def checkPublicIdReadOnly(self): checkReadOnly(self.node, 'publicId') def checkPublicIdPublicExternal(self): checkAttribute(self.publicExternal, 'publicId', 'uri:public') def checkPublicIdSystemExternal(self): checkAttribute(self.systemExternal, 'publicId', None) def checkPublicIdPublic(self): checkAttribute(self.public, 'publicId', 'uri:public') def checkSystemIdReadOnly(self): checkReadOnly(self.node, 'systemId') def checkSystemIdPublicExternal(self): checkAttribute(self.publicExternal, 'systemId', 'uri:system') def checkSystemIdSystemExternal(self): checkAttribute(self.systemExternal, 'systemId', 'uri:system') def checkSystemIdPublic(self): checkAttribute(self.public, 'systemId', None) class NotationWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.notations.getNamedItem('aNotation') cases = buildCases(__name__, 'XML', '1.0') PyXML-0.8.2/test/domapi/XMLLvl2.py0100644000076400001440000002211707534565153015732 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * import CoreLvl2 TextReadTestCaseBase = CoreLvl2.TextReadTestCase TextWriteTestCaseBase = CoreLvl2.TextWriteTestCase NodeReadTestCaseBase = CoreLvl2.NodeReadTestCaseBase NodeWriteTestCaseBase = CoreLvl2.NodeWriteTestCaseBase del CoreLvl2 import xml.dom from xml.dom import Node # --- DocumentType class DocumentTypeReadTestCase(NodeReadTestCaseBase): def setUp(self): self.doctype = self.node = self.implementation.createDocumentType( 'foo:bar', 'uri:foo', 'uri:bar') def checkInternalSubset(self): # The DOM Level 2 recommendation is not clear on the value of the # internalSubset attribute when there isn't one; this test relies # on a clarification from Joe Kesselman: # # http://lists.w3.org/Archives/Public/www-dom/2001AprJun/0009.html # checkAttribute(self.doctype, 'internalSubset', None) checkReadOnly(self.doctype, 'internalSubset') def checkPublicId(self): checkAttribute(self.doctype, 'publicId', 'uri:foo') checkReadOnly(self.doctype, 'publicId') def checkSystemId(self): checkAttribute(self.doctype, 'systemId', 'uri:bar') checkReadOnly(self.doctype, 'systemId') def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) self.assertRaises(xml.dom.NotSupportedErr, foreignDoc.importNode, self.doctype, 0) class DocumentTypeWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.doctype = self.node = self.implementation.createDocumentType( 'foo:bar', 'uri:foo', 'uri:bar') # --- ProcessingInstruction class ProcessingInstructionReadTestCase(NodeReadTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) clone = foreignDoc.importNode(self.pi, 0) deepClone = foreignDoc.importNode(self.pi, 1) self.failIf(isSameNode(self.pi, clone), "Clone is same as original.") self.failIf(isSameNode(self.pi, deepClone), "Clone is same as original.") checkAttributeSameNode(clone, 'ownerDocument', foreignDoc) checkAttributeSameNode(deepClone, 'ownerDocument', foreignDoc) checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.pi.nodeType) checkAttribute(deepClone, 'nodeType', self.pi.nodeType) checkAttribute(clone, 'data', self.pi.data) checkAttribute(deepClone, 'data', self.pi.data) checkAttribute(clone, 'target', self.pi.target) checkAttribute(deepClone, 'target', self.pi.target) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, 0) class ProcessingInstructionWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi # --- CDATASection class CDATASectionReadTestCase(TextReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") class CDATASectionWriteTestCase(TextWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") # --- EntityReference class EntityReferenceReadTestCase(NodeReadTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") def checkImportNode(self): pass # TODO: Fill in meaningful test here. class EntityReferenceWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") # --- Entity class EntityReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.entities.getNamedItem('internalParsedE') class EntityWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.entities.getNamedItem('internalParsedE') # --- Notation class NotationReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.notations.getNamedItem('aNotation') class NotationWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.notations.getNamedItem('aNotation') cases = buildCases(__name__, 'XML', '2.0') PyXML-0.8.2/test/domapi/__init__.py0100644000076400001440000001533007534565153016270 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """A suite of unit tests for the Python DOM API. This suite will test a DOM API for compliance with the DOM API, level 2. It assumes that the DOM tested supports at least both the Core and XML features. It requires PyUnit; see http://pyunit.sourceforge.net/. Example for the python minidom (which is an incomplete implementation): from xml.dom.minidom import DOMImplementation, parseString from domapi import DOMImplementationTestSuite def MiniDomParseString(self, xml): return parseString(xml) def test_suite(): '''Return a test suite for the Zope testing framework.''' return DOMImplementationTestSuite(DOMImplementation(), MiniDomParseString) if __name__ == '__main__': import unittest unittest.TextTestRunner().run(test_suite()) """ import unittest import CoreLvl1, CoreLvl2, CoreLvl3, XMLLvl1, XMLLvl2, TraversalLvl2, Load3 cases = ( CoreLvl1.cases + CoreLvl2.cases + CoreLvl3.cases + XMLLvl1.cases + XMLLvl2.cases + # TraversalLvl2.cases + Load3.cases ) def DOMImplementationTestSuite(implementation, parseMethod, verbose=0): """ Create a testsuite for DOM lvl 2 compliance, given a DOM Implementation. To test a DOM implementation, hand in a DOMImplementation object, and a method that will take a string holding an XML document and returns a Document Node created from the XML. Then run the returned unittest testsuite. Note that the signature of the parse method is (self, xmlString) and should parse the xml string with namespaces turned on. It will be used to create Nodes which normally cannot be created using the DOM API, like Notations and Entities. """ # First test for minimal feature support # XXX Why??? assert (implementation.hasFeature('Core', '2.0') and implementation.hasFeature('XML', '2.0')), ( "This DOMImplementation doesn't feature the level 2 Core and XML API.") suite = unittest.TestSuite() # The minimal set of features that should return 1 on hasFeature. # ('Core', '1.0') was never defined for DOM level 1, it was implicit. Most # DOM level 2 implementations return true, but this is a courtesy. supportedFeatures = { ('Core', None): 1, ('Core', '2.0'): 1, ('XML', None): 1, ('XML', '1.0'): 1, ('XML', '2.0'): 1, } for case, feature, version in cases: if implementation.hasFeature(feature, version): case.implementation = implementation case.parse = parseMethod suite.addTest(unittest.makeSuite(case, 'check')) supportedFeatures[(feature, version)] = 1 supportedFeatures[(feature, None)] = 1 else: if verbose: print ("Test %s skipped: DOM feature not supported.\n" % case.__name__) # Record supported features. CoreLvl1.DOMImplementationReadTestCase.supportedFeatures = ( supportedFeatures.keys()) CoreLvl2.NodeReadTestCaseBase.supportedFeatures = ( supportedFeatures.keys()) return suite PyXML-0.8.2/test/output/0040755000076400001440000000000007614726123014242 5ustar martinusersPyXML-0.8.2/test/output/test_c14n0100644000076400001440000000052207406413634015764 0ustar martinuserstest_c14n Doing 1, \n\n\n \n ... Ok Doing 3, This is a test

    Don't panic

    Maybe it will work.

    We can handle it

    Yes we can

    Or maybe not

    End of test.
    Output of docstring example Title goes here Running detailed test suite Test suite completed PyXML-0.8.2/test/output/test_domreg0100644000076400001440000000001407557321763016500 0ustar martinuserstest_domreg PyXML-0.8.2/test/output/test_encodings0100644000076400001440000000026107221215151017155 0ustar martinuserstest_encodings < u'tag' > attr name: attr value: (\"e): PyXML-0.8.2/test/output/test_filter0100644000076400001440000000144307534565153016515 0ustar martinuserstest_filter textmoreabcxyz Text. Nested text. Nested text in skipthis element. More nested text. Outer text. Text. Nested text. Nested text in skipthis element. More nested text. More text. Outer text. text text and text PyXML-0.8.2/test/output/test_howto0100644000076400001440000000104307534565153016364 0ustar martinuserstest_howto SAX tests: Sandman #62 found Titles by Peter Milligan: Shade, the Changing Man 7 DOM tests: No description XML bookmarks SIG for XML Processing in Python DOM creation tests The body text goes here. PyXML-0.8.2/test/output/test_htmlb0100644000076400001440000000115707255234714016334 0ustar martinuserstest_htmlb Good document

    I prefer (all things being equal) regularity/orthogonality and logical syntax/semantics in a language because there is less to have to remember. (Of course I know all things are NEVER really equal!)

    Guido van Rossum, 6 Dec 91

    The details of that silly code are irrelevant.

    Tim Peters, 4 Mar 92 & < >

    PyXML-0.8.2/test/output/test_javadom0100644000076400001440000000001507406327236016637 0ustar martinuserstest_javadom PyXML-0.8.2/test/output/test_marshal0100644000076400001440000001034607555273164016662 0ustar martinuserstest_marshal Testing XML marshalling... 1 10633823966279326983230456482242756608 19.72 1.0 5.0 here is a string & a <fake tag> 123 alphabetagamma 12keyvalue selfsubobjectlist11063382396627932698323045648224275660819.721.0 5.0here is a string & a <fake tag> 1103010514608775374539735472678431spam2eggs<fake tag>1.0 5.0 Testing WDDX marshalling...
    1
    10633823966279326983230456482242756608
    19.72
    here is a string & a <fake tag>
    123foo
    John DoeJane Doe3431
    rhode island redbantam18139
    10second element-12.456-12.456a stringa string
    13five742 PyXML-0.8.2/test/output/test_marshal.orig0100644000076400001440000001416707333241720017611 0ustar martinuserstest_marshal Testing XML marshalling... None 1 1 10633823966279326983230456482242756608 10633823966279326983230456482242756608 19.72 19.72 (1+5j) 1.0 5.0 here is a string & a here is a string & a <fake tag> (1, 2, 3) 123 ['alpha', 'beta', 'gamma'] alphabetagamma {(1, 2), ('key', 'value')} keyvalue12 selfsubobjectlist11063382396627932698323045648224275660819.721.0 5.0here is a string & a <fake tag> [None, 1, 10301051460877537453973547267843L, {2: 'eggs', 1: 'spam'}, '', (1+5j), [...]] 1103010514608775374539735472678432eggs1spam<fake tag>1.0 5.0 Testing WDDX marshalling...
    1
    1 10633823966279326983230456482242756608
    10633823966279326983230456482242756608 19.72
    19.72 here is a string & a
    here is a string & a <fake tag> [1, 2, 3, 'foo']
    123foo {'AGE': [34, 31], 'NAME': ['John Doe', 'Jane Doe']}
    John DoeJane Doe3431 {('eggs', ['rhode island red', 'bantam']), ('lowerBound', 18), ('upperBound', 139)}
    13918rhode island redbantam {('a', [10, 'second element']), ('b', ), ('n', -12.456), ('obj', {'n': -12.456, 's': 'a string'}), ('s', 'a string')}
    -12.456-12.456a stringa string10second element (1, 3, 'five', 7, None, 42)
    13five742 Testing XML-RPC marshalling... 1 0 1 1 19.72 19.72 here is a string & a here is a string & a <fake tag> [12, 'Egypt', , -31] 12Egypt0-31 {('eggs', ['rhode island red', 'bantam']), ('lowerBound', 18), ('upperBound', 139)} upperBound139lowerBound18eggsrhode island redbantam ['upperBound', 139, 'lowerBound', 18, 'eggs', ['rhode island red', 'bantam']] ['upperBound', 139, 'lowerBound', 18, 'eggs', ['rhode island red', 'bantam']] PyXML-0.8.2/test/output/test_marshal.rej0100644000076400001440000002455607333242034017433 0ustar martinusers*************** *** 8,16 **** here is a string & a here is a string & a <fake tag> (1, 2, 3) 123 ['alpha', 'beta', 'gamma'] alphabetagamma - {'key': 'value', 1: 2} keyvalue12 - selfsubobjectlist11063382396627932698323045648224275660819.721.0 5.0here is a string & a <fake tag> - [None, 1, 10301051460877537453973547267843L, {2: 'eggs', 1: 'spam'}, '', (1+5j), [...]] 1103010514608775374539735472678432eggs1spam<fake tag>1.0 5.0 Testing WDDX marshalling...
    --- 8,16 ---- here is a string & a here is a string & a <fake tag> (1, 2, 3) 123 ['alpha', 'beta', 'gamma'] alphabetagamma + {(1, 2), ('key', 'value')} 12keyvalue + subobjectlist11063382396627932698323045648224275660819.721.0 5.0here is a string & a <fake tag>self + [None, 1, 10301051460877537453973547267843L, {1: 'spam', 2: 'eggs'}, '', (1+5j), [...]] 1103010514608775374539735472678431spam2eggs<fake tag>1.0 5.0 Testing WDDX marshalling...
    *************** *** 20,27 **** here is a string & a
    here is a string & a <fake tag> [1, 2, 3, 'foo']
    123foo {'AGE': [34, 31], 'NAME': ['John Doe', 'Jane Doe']}
    John DoeJane Doe3431 - {'lowerBound': 18, 'upperBound': 139, 'eggs': ['rhode island red', 'bantam']}
    18139rhode island redbantam - {'n': -12.456, 'obj': {'n': -12.456, 's': 'a string'}, 'b': , 's': 'a string', 'a': [10, 'second element']}
    -12.456-12.456a stringa string10second element (1, 3, 'five', 7, None, 42)
    13five742 Testing XML-RPC marshalling... 1 --- 20,27 ---- here is a string & a
    here is a string & a <fake tag> [1, 2, 3, 'foo']
    123foo {'AGE': [34, 31], 'NAME': ['John Doe', 'Jane Doe']}
    John DoeJane Doe3431 + {('eggs', ['rhode island red', 'bantam']), ('lowerBound', 18), ('upperBound', 139)}
    rhode island redbantam18139 + {('a', [10, 'second element']), ('b', ), ('n', -12.456), ('obj', {'s': 'a string', 'n': -12.456}), ('s', 'a string')}
    10second elementa stringa string-12.456-12.456 (1, 3, 'five', 7, None, 42)
    13five742 Testing XML-RPC marshalling... 1 *************** *** 30,35 **** 19.72 19.72 here is a string & a here is a string & a <fake tag> [12, 'Egypt', , -31] 12Egypt0-31 - {'lowerBound': 18, 'upperBound': 139, 'eggs': ['rhode island red', 'bantam']} lowerBound18upperBound139eggsrhode island redbantam - ['lowerBound', 18, 'upperBound', 139, 'eggs', ['rhode island red', 'bantam']] - ['lowerBound', 18, 'upperBound', 139, 'eggs', ['rhode island red', 'bantam']] --- 30,35 ---- 19.72 19.72 here is a string & a here is a string & a <fake tag> [12, 'Egypt', , -31] 12Egypt0-31 + {('eggs', ['rhode island red', 'bantam']), ('lowerBound', 18), ('upperBound', 139)} eggsrhode island redbantamlowerBound18upperBound139 + ['eggs', ['rhode island red', 'bantam'], 'lowerBound', 18, 'upperBound', 139] + ['eggs', ['rhode island red', 'bantam'], 'lowerBound', 18, 'upperBound', 139] PyXML-0.8.2/test/output/test_minidom0100644000076400001440000000001507517567472016665 0ustar martinuserstest_minidom PyXML-0.8.2/test/output/test_parsers0100644000076400001440000000001506560503144016667 0ustar martinuserstest_parsers PyXML-0.8.2/test/output/test_pyexpat0100644000076400001440000000466007433726662016730 0ustar martinuserstest_pyexpat OK. OK. OK. OK. OK. OK. OK. OK. OK. OK. OK. OK. PI: 'xml-stylesheet' 'href="stylesheet.css"' Comment: ' comment data ' Notation declared: ('notation', None, 'notation.jpeg', None) Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation') Start element: 'root' { 'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80', } NS decl: 'myns' 'http://www.python.org/namespace' Start element: 'http://www.python.org/namespace!subelement' { } Character data: 'Contents of subelements' End element: 'http://www.python.org/namespace!subelement' End of NS decl: 'myns' Start element: 'sub2' { } Start of CDATA section Character data: 'contents of CDATA section' End of CDATA section End element: 'sub2' External entity ref: (None, 'entity.file', None) End element: 'root' PI: u'xml-stylesheet' u'href="stylesheet.css"' Comment: u' comment data ' Notation declared: (u'notation', None, u'notation.jpeg', None) Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation') Start element: u'root' { u'attr1': u'value1', u'attr2': u'value2\\u1f40', } NS decl: u'myns' u'http://www.python.org/namespace' Start element: u'http://www.python.org/namespace!subelement' { } Character data: u'Contents of subelements' End element: u'http://www.python.org/namespace!subelement' End of NS decl: u'myns' Start element: u'sub2' { } Start of CDATA section Character data: u'contents of CDATA section' End of CDATA section End element: u'sub2' External entity ref: (None, u'entity.file', None) End element: u'root' PI: u'xml-stylesheet' u'href="stylesheet.css"' Comment: u' comment data ' Notation declared: (u'notation', None, u'notation.jpeg', None) Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation') Start element: u'root' { u'attr1': u'value1', u'attr2': u'value2\\u1f40', } NS decl: u'myns' u'http://www.python.org/namespace' Start element: u'http://www.python.org/namespace!subelement' { } Character data: u'Contents of subelements' End element: u'http://www.python.org/namespace!subelement' End of NS decl: u'myns' Start element: u'sub2' { } Start of CDATA section Character data: u'contents of CDATA section' End of CDATA section End element: u'sub2' External entity ref: (None, u'entity.file', None) End element: u'root' Testing constructor for proper handling of namespace_separator values: Legal values tested o.k. Caught expected TypeError. Caught expected ValueError. PyXML-0.8.2/test/output/test_sax0100644000076400001440000000001107611541422015776 0ustar martinuserstest_sax PyXML-0.8.2/test/output/test_sax20100644000076400001440000000001207537736442016100 0ustar martinuserstest_sax2 PyXML-0.8.2/test/output/test_sax2_xmlproc0100644000076400001440000000002207406330067017631 0ustar martinuserstest_sax2_xmlproc PyXML-0.8.2/test/output/test_sax_xmlproc0100644000076400001440000000034307253575750017567 0ustar martinuserstest_sax_xmlproc Passed test_ignorable PASS: doc2.xml:3:1: Premature document end, no root element Passed test_illformed PASS: doc1.xml:2:50: Couldn't open resource 'NONEXISTENT.dtd' Passed test_nonexistent 3 tests, 0 failures PyXML-0.8.2/test/output/test_saxdrivers0100644000076400001440000000065607406413203017411 0ustar martinuserstest_saxdrivers xml.sax.drivers2.drv_pyexpat PASS xml.sax.drivers2.drv_xmlproc PASS xml.sax.drivers.drv_pyexpat PASS xml.sax.drivers.drv_xmltok NOT SUPPORTED xml.sax.drivers.drv_xmlproc PASS xml.sax.drivers.drv_xmltoolkit NOT SUPPORTED xml.sax.drivers.drv_xmllib XFAIL xml.sax.drivers.drv_xmldc NOT SUPPORTED xml.sax.drivers.drv_sgmlop XFAIL xml.sax.drivers2.drv_pyexpat PASS xml.sax.drivers2.drv_xmlproc PASS 8 tests, 0 failures PyXML-0.8.2/test/output/test_utils0100644000076400001440000000057706740770320016367 0ustar martinuserstest_utils Testing utils.escape These pairs of strings should all be identical 1 '&<>' '&<>' 1 'foo&amp;bar' 'foo&amp;bar' 1 '< &myentity; > &' '< &myentity; > &' 1 '&'"<>' '&'"<>' 1998-01-01T00:00Z 1998-06-01T00:00Z 1998-06-13T00:00Z 1998-06-13T14:12Z 1998-06-13T14:12:30Z 1998-06-13T14:12:30Z PyXML-0.8.2/test/output/test_xmlbuilder0100644000076400001440000000002007516030560017352 0ustar martinuserstest_xmlbuilder PyXML-0.8.2/test/output/test_xmlproc0100644000076400001440000000020307463731116016700 0ustar martinuserstest_xmlproc ERROR: Element 'notallowed' not allowed here at doc.xml:3:29 ERROR: Element 'notallowed' not declared at doc.xml:3:29 PyXML-0.8.2/test/chkdom_4dom.py0100644000076400001440000001044107520267172015441 0ustar martinusers############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import unittest from domapi import DOMImplementationTestSuite from xml.dom import ext, implementation from xml.dom.ext.reader import PyExpat def DOMParseString(self, xml): reader = PyExpat.Reader() return reader.fromString(xml) def test_suite(): """Return a test suite for the Zope testing framework.""" return DOMImplementationTestSuite(implementation, DOMParseString) def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() else: import sys print >>sys.__stderr__, \ "The", __name__, "tests are not run under regrtest." PyXML-0.8.2/test/chkdom_minidom.py0100644000076400001440000000100007522030264016211 0ustar martinusersimport unittest import xml.dom.expatbuilder import xml.dom.minidom from domapi import DOMImplementationTestSuite def DOMParseString(self, text): return xml.dom.expatbuilder.parseString(text) def test_suite(): """Return a test suite for the Zope testing framework.""" return DOMImplementationTestSuite(xml.dom.minidom.getDOMImplementation(), DOMParseString) def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() PyXML-0.8.2/test/enc_test.xml0100644000076400001440000000027007221213652015214 0ustar martinusers (\"e): PyXML-0.8.2/test/perf_expatbuilder.py0100644000076400001440000000551307611541421016752 0ustar martinusers"""\ Performance comparison for the xml.dom.expatbuilder DOM loader. Usage: %(program)s [-f file] [-p] [file] -f file Read the document to use from `file'. -p Enable profiling support. file Read the document to use from `file'. Use this or the `-f' option; not both. """ import getopt import os import sys import time from xml.dom import minidom, expatbuilder # XXX What's the right mix of markup items to text? What type of # XXX markup items? ## FRAGMENT = '''\ ## ## ## ## ''' FRAGMENT = '''\ This is < sample > text. ''' CHUNKS = 12000 LOGFILE = "hotshot.log" first = 1 chunks = CHUNKS if sys.argv[1:]: try: chunks = int(sys.argv[-1]) except ValueError: pass else: del sys.argv[-1] def timeit(parsefunc, src): global first if first: print "Document source contains", len(src), "bytes." first = 0 modname = parsefunc.func_globals["__name__"] t1 = time.time() doc = parsefunc(src) t2 = time.time() doc.unlink() print ("using %s.parseString():" % modname), t2 - t1 return t2 - t1 def usage(err=None, rc=0): program = os.path.basename(sys.argv[0]) if rc: f = sys.stderr else: f = sys.stdout if err: print >>f, "%s: %s" % (program, err) print >>f print >>f, __doc__ % {"program": program} sys.exit(rc) do_profile = 0 filename = None opts, args = getopt.getopt(sys.argv[1:], "f:hp", ["file=", "help", "profile="]) for opt, arg in opts: if opt in ('-f', '--file'): if filename is not None: usage("`-f' argument may only be given once", rc=2) if args: usage("`-f' and additional file argument are not compatible", rc=2) filename = arg elif opt in ('-h', '--help'): usage() elif opt == '-p': do_profile = 1 elif opt == '--profile': do_profile = 1 LOGFILE = arg if len(args) > 1: usage("at most on file argument can be used", rc=2) if args: filename = args[0] if filename is not None: src = open(filename, 'rb') else: src = "%s" % (FRAGMENT * chunks) timeit(minidom.parseString, src) timeit(expatbuilder.parseString, src) if sys.argv[1:] == ["-p"]: if os.path.exists(LOGFILE): os.unlink(LOGFILE) import hotshot import hotshot.stats def profile(*args, **kw): profiler = hotshot.Profile(LOGFILE) src = "%s" % (FRAGMENT * chunks) profiler.runcall(expatbuilder.parseString, src, *args, **kw) profiler.close() stats = hotshot.stats.load(LOGFILE) stats.strip_dirs() stats.sort_stats('calls', 'time') stats.print_stats(20) profile() PyXML-0.8.2/test/quotes.xml0100644000076400001440000000164706700302346014741 0ustar martinusers ]> We will perhaps eventually be writing only small modules which are identified by name as they are used to build larger ones, so that devices like indentation, rather than delimiters, might become feasible for expressing local structure in the source language. Donald E. Knuth, "Structured Programming with goto Statements", Computing Surveys, Vol 6 No 4, Dec. 1974 The infinities aren't contagious except in that they often appear that way due to to their large size. Tim Peters on the IEEE 754 floating point standard, 27 Apr 2025 PyXML-0.8.2/test/regrtest.py0100755000076400001440000001511607536326574015130 0ustar martinusers#! /usr/bin/env python # Slightly modified copy of Lib/test/regrtest.py from Python 1.5.1 """Regression test. This will find all modules whose name is "test_*" in the test directory, and run them. Various command line options provide additional facilities. Command line options: -v: verbose -- run tests in verbose mode with output to stdout -q: quiet -- don't print anything except if a test fails -g: generate -- write the output file for a test instead of comparing it -x: exclude -- arguments are tests to *exclude* If non-option arguments are present, they are names for tests to run, unless -x is given, in which case they are names for tests not to run. If no test names are given, all tests are run. -v is incompatible with -g and does not compare test output files. """ import sys import string import os import getopt import traceback from test import test_support def main( tests = None, testdir = None ): """Execute a test suite. This also parses command-line options and modifies its behaviour accordingly. tests -- a list of strings containing test names (optional) testdir -- the directory in which to look for tests (optional) Users other than the Python test suite will certainly want to specify testdir; if it's omitted, the directory containing the Python test suite is searched for. If the tests argument is omitted, the tests listed on the command-line will be used. If that's empty, too, then all *.py files beginning with test_ will be used. """ try: opts, args = getopt.getopt(sys.argv[1:], 'vgqx') except getopt.error, msg: print msg print __doc__ return 2 verbose = 0 quiet = 0 generate = 0 exclude = 0 for o, a in opts: if o == '-v': verbose = verbose+1 if o == '-q': quiet = 1; verbose = 0 if o == '-g': generate = 1 if o == '-x': exclude = 1 if generate and verbose: print "-g and -v don't go together!" return 2 good = [] bad = [] skipped = [] for i in range(len(args)): # Strip trailing ".py" from arguments if args[i][-3:] == '.py': args[i] = args[i][:-3] if exclude: NOTTESTS[:0] = args args = [] tests = tests or args or findtests() test_support.verbose = verbose # Tell tests to be moderately quiet for test in tests: if not quiet: print test ok = runtest(test, generate, verbose, testdir) if ok > 0: good.append(test) elif ok == 0: bad.append(test) else: if not quiet: print "test", test, print "skipped -- an optional feature could not be imported" skipped.append(test) if good and not quiet: if not bad and not skipped and len(good) > 1: print "All", print count(len(good), "test"), "OK." if bad: print count(len(bad), "test"), "failed:", print string.join(bad) if skipped and not quiet: print count(len(skipped), "test"), "skipped:", print string.join(skipped) return len(bad) > 0 # Not in PyXML... STDTESTS = [ # 'test_grammar', # 'test_opcodes', # 'test_operations', # 'test_builtin', # 'test_exceptions', # 'test_types', ] NOTTESTS = [ 'test_support', 'test_b1', 'test_b2', ] def findtests(testdir = None, stdtests = STDTESTS, nottests = NOTTESTS): """Return a list of all applicable test modules.""" if not testdir: testdir = findtestdir() names = os.listdir(testdir) tests = [] for name in names: if name[:5] == "test_" and name[-3:] == ".py": modname = name[:-3] if modname not in stdtests and modname not in nottests: tests.append(modname) tests.sort() return stdtests + tests def runtest(test, generate, verbose, testdir = None): """Run a single test. test -- the name of the test generate -- if true, generate output, instead of running the test and comparing it to a previously created output file verbose -- if true, print more messages testdir -- test directory """ test_support.unload(test) if not testdir: testdir = findtestdir() outputdir = os.path.join(testdir, "output") outputfile = os.path.join(outputdir, test) try: if generate: cfp = open(outputfile, "w") elif verbose: cfp = sys.stdout else: cfp = Compare(outputfile) except IOError: cfp = None print "Warning: can't open", outputfile try: save_stdout = sys.stdout try: if cfp: sys.stdout = cfp print test # Output file starts with test name the_module = __import__(test, globals(), locals(), []) # Most tests run to completion simply as a side-effect of # being imported. For the benefit of tests that can't run # that way (like test_threaded_import), explicitly invoke # their test_main() function (if it exists). indirect_test = getattr(the_module, "test_main", None) if indirect_test is not None: indirect_test() finally: sys.stdout = save_stdout except ImportError, msg: return -1 except KeyboardInterrupt, v: raise KeyboardInterrupt, v, sys.exc_info()[2] except test_support.TestFailed, msg: print "test", test, "failed --", msg return 0 except: type, value = sys.exc_info()[:2] print "test", test, "crashed --", type, ":", value if verbose: traceback.print_exc(file=sys.stdout) return 0 else: return 1 def findtestdir(): if __name__ == '__main__': file = sys.argv[0] else: file = __file__ testdir = os.path.dirname(file) or os.curdir return testdir def count(n, word): if n == 1: return "%d %s" % (n, word) else: return "%d %ss" % (n, word) class Compare: def __init__(self, filename): self.fp = open(filename, 'r') def write(self, data): expected = self.fp.read(len(data)) if data <> expected: raise test_support.TestFailed, \ 'Writing: '+`data`+', expected: '+`expected` def flush(self): pass def close(self): leftover = self.fp.read() if leftover: raise test_support.TestFailed, 'Unread: '+`leftover` self.fp.close() def isatty(self): return 0 if __name__ == '__main__': sys.exit(main()) PyXML-0.8.2/test/test.xml0100644000076400001440000000252507165435670014411 0ustar martinusers Introduction to XSL

    Introduction to XSL


    Overview

    • 1.Intro
    • 2.History
    • 3.XSL Basics
    • Lunch
    • 4.An XML Data Model
    • 5.XSL Patterns
    • 6.XSL Templates
    • 7.XSL Formatting Model

    Intro

    • Who am I?
    • Who are you?
    • Why are we here?

    History: XML and SGML

    • XML is a subset of SGML.
    • SGML allows the separation of abstract content from formatting.
    • Also one of XML's primary virtues (in the doc publishing domain).

    History: What are stylesheets?

    • Stylesheets specify the formatting of SGML/XML documents.
    • Stylesheets put the "style" back into documents.
    • New York Times content+NYT Stylesheet = NYT paper

    History: FOSI

    • FOSI: "Formatted Output Specification Instance"
      • MIL-STD-28001
      • FOSI's are SGML documents
      • A stylesheet for another document
    • Obsolete but implemented...
    PyXML-0.8.2/test/test.xml.out0100644000076400001440000000255207165435670015217 0ustar martinusers Introduction to XSL

    Introduction to XSL


    Overview

    • 1.Intro
    • 2.History
    • 3.XSL Basics
    • Lunch
    • 4.An XML Data Model
    • 5.XSL Patterns
    • 6.XSL Templates
    • 7.XSL Formatting Model

    Intro

    • Who am I?
    • Who are you?
    • Why are we here?

    History: XML and SGML

    • XML is a subset of SGML.
    • SGML allows the separation of abstract content from formatting.
    • Also one of XML's primary virtues (in the doc publishing domain).

    History: What are stylesheets?

    • Stylesheets specify the formatting of SGML/XML documents.
    • Stylesheets put the "style" back into documents.
    • New York Times content+NYT Stylesheet = NYT paper

    History: FOSI

    • FOSI: "Formatted Output Specification Instance"
      • MIL-STD-28001
      • FOSI's are SGML documents
      • A stylesheet for another document
    • Obsolete but implemented...
    PyXML-0.8.2/test/test_c14n.py0100755000076400001440000002550607507520267015072 0ustar martinusers#! /usr/bin/env python # The seven examples from the Canonical XML spec. # http://www.w3.org/TR/2001/REC-xml-c14n-20010315 try: u = unicode except NameError: def u(x):return x eg1 = """ Hello, world! """ eg2 = """ A B A B A B C """ eg3 = """]> """ eg3 = """]> """ eg4 = """ ]> First line Second line 2 "0" && value<"10" ?"valid":"error"]]> valid """ eg5 = """ ]> &ent1;, &ent2;! """ eg6 = """ ©""" eg7 = """ ]> """ examples = [ eg1, eg2, eg3, eg4, eg5, eg6, eg7] test_results = { eg1: '''PD94bWwtc3R5bGVzaGVldCBocmVmPSJkb2MueHNsIgogICB0eXBlPSJ0ZXh0L3hz bCIgICA/Pgo8ZG9jPkhlbGxvLCB3b3JsZCE8IS0tIENvbW1lbnQgMQotLT48L2Rv Yz4KPD9waS13aXRob3V0LWRhdGE/Pgo8IS0tIENvbW1lbnQgMiAtLT4KPCEtLSBD b21tZW50IDMgLS0+''', eg2: '''PGRvYz4KICAgPGNsZWFuPiAgIDwvY2xlYW4+CiAgIDxkaXJ0eT4gICBBICAgQiAg IDwvZGlydHk+CiAgIDxtaXhlZD4KICAgICAgQQogICAgICA8Y2xlYW4+ICAgPC9j bGVhbj4KICAgICAgQgogICAgICA8ZGlydHk+ICAgQSAgIEIgICA8L2RpcnR5Pgog ICAgICBDCiAgIDwvbWl4ZWQ+CjwvZG9jPg==''', eg3: '''PGRvYyB4bWxuczpmb289Imh0dHA6Ly93d3cuYmFyLm9yZyI+CiAgIDxlMT48L2Ux PgogICA8ZTI+PC9lMj4KICAgPGUzIGlkPSJlbGVtMyIgbmFtZT0iZWxlbTMiPjwv ZTM+CiAgIDxlNCBpZD0iZWxlbTQiIG5hbWU9ImVsZW00Ij48L2U0PgogICA8ZTUg eG1sbnM9Imh0dHA6Ly9leGFtcGxlLm9yZyIgeG1sbnM6YT0iaHR0cDovL3d3dy53 My5vcmciIHhtbG5zOmI9Imh0dHA6Ly93d3cuaWV0Zi5vcmciIGF0dHI9IkknbSIg YXR0cjI9ImFsbCIgYjphdHRyPSJzb3J0ZWQiIGE6YXR0cj0ib3V0Ij48L2U1Pgog ICA8ZTYgeG1sbnM6YT0iaHR0cDovL3d3dy53My5vcmciPgogICAgICAgPGU3IHht bG5zPSJodHRwOi8vd3d3LmlldGYub3JnIj4KICAgICAgICAgICA8ZTggeG1sbnM9 IiIgYTpmb289ImJhciI+CiAgICAgICAgICAgICAgIDxlOSB4bWxuczphPSJodHRw Oi8vd3d3LmlldGYub3JnIiBhdHRyPSJkZWZhdWx0Ij48L2U5PgogICAgICAgICAg IDwvZTg+CiAgICAgICA8L2U3PgogICA8L2U2Pgo8L2RvYz4=''', eg4: '''PGRvYz4KICAgPHRleHQ+Rmlyc3QgbGluZSYjeEQ7ClNlY29uZCBsaW5lPC90ZXh0 PgogICA8dmFsdWU+MjwvdmFsdWU+CiAgIDxjb21wdXRlPnZhbHVlJmd0OyIwIiAm YW1wOyZhbXA7IHZhbHVlJmx0OyIxMCIgPyJ2YWxpZCI6ImVycm9yIjwvY29tcHV0 ZT4KICAgPGNvbXB1dGUgZXhwcj0idmFsdWU+JnF1b3Q7MCZxdW90OyAmYW1wOyZh bXA7IHZhbHVlJmx0OyZxdW90OzEwJnF1b3Q7ID8mcXVvdDt2YWxpZCZxdW90Ozom cXVvdDtlcnJvciZxdW90OyI+dmFsaWQ8L2NvbXB1dGU+CiAgIDxub3JtIGF0dHI9 IiAnICAgICYjeEQmI3hBJiN4OSAgICcgIj48L25vcm0+CiAgIDxub3JtTmFtZXMg YXR0cj0iQSAmI3hEJiN4QSYjeDkgQiI+PC9ub3JtTmFtZXM+CiAgIDxub3JtSWQg aWQ9IicgJiN4RCYjeEEmI3g5ICciPjwvbm9ybUlkPgo8L2RvYz4=''', eg5: '''PGRvYyBhdHRyRXh0RW50PSJlbnRFeHQiPgogICBIZWxsbywgd29ybGQhCjwvZG9j Pg==''', eg6: '''PGRvYz7CqTwvZG9jPg==''', eg7: '''PGRvYyB4bWxucz0iaHR0cDovL3d3dy5pZXRmLm9yZyIgeG1sbnM6dzNjPSJodHRw Oi8vd3d3LnczLm9yZyI+CiAgIDxlMT4KICAgICAgPGUyIHhtbG5zPSIiIHhtbDpz cGFjZT0icHJlc2VydmUiPgogICAgICAgICA8ZTMgaWQ9IkUzIj48L2UzPgogICAg ICA8L2UyPgogICA8L2UxPgo8L2RvYz4=''', } # Load XPath and Parser import sys, types, traceback, StringIO, base64, string from xml import xpath from xml.xpath.Context import Context from xml.dom.ext.reader import PyExpat #from c14n import Canonicalize from xml.dom.ext import Canonicalize # My special reader. PYE = PyExpat.Reader class ReaderforC14NExamples(PYE): '''A special reader to handle resolution of the C14N examples. ''' def initParser(self): PYE.initParser(self) self.parser.ExternalEntityRefHandler = self.entity_ref def entity_ref(self, *args): if args != (u('ent2'), None, u('world.txt'), None): return 0 self.parser.CharacterDataHandler('world') return 1 # Override some methods from PyExpat.Reader def unparsedEntityDecl(self, *args): pass def notationDecl(self, *args): pass try: import codecs utf8_writer = codecs.lookup('utf-8')[3] except ImportError: def utf8_writer(s): return s def builtin(): '''Run the builtin tests from the C14N spec.''' for i in range(len(examples)): num = i+1 eg = examples[i] filename = 'out%d.xml' % num try: os.unlink(filename) except: pass print 'Doing %d, %s...' % (num, string.replace(eg[0:30], '\n', '\\n')), r = ReaderforC14NExamples() try: dom = r.fromString(eg) except Exception, e: print '\nException', repr(e) traceback.print_exc() continue # Get the nodeset; the tests have some special cases. pattern = '(//. | //@* | //namespace::*)' con = Context(dom) if eg == eg5: pattern = '(//. | //@* | //namespace::*)[not (self::comment())]' elif eg == eg7: con = Context(dom, processorNss={'ietf': 'http://www.ietf.org'}) nodelist = xpath.Evaluate(pattern, context=con) s = StringIO.StringIO() outf = utf8_writer(s) #Get the unsuppressedPrefixes for exc-c14n; the tests have special casese pfxlist = [] # Canonicalize a DOM with a document subset list according to XML-C14N if eg == eg1: Canonicalize(dom, outf, subset=nodelist, comments=1) else: Canonicalize(dom, outf, subset=nodelist) expected = base64.decodestring(test_results[eg]) if s.getvalue() == expected: print 'Ok' else: print 'Error!' print 'Got:\n', s.getvalue() print 'Expected:\n', expected def usage(): print '''Options accepted: -b, --builtin Run the C14N builtin tests -e Exclusive C14N -p Exclusive C14N inclusive prefixes -n string, Additional NSPrefixes (whitespace delimited) --namespaces=string -i file, --in=file Read specified file* (default is stdin) -o file, --out=file Write to specified file* (default is stdout) -h, --help Print this text -x query, --xpath=query Specify an XPATH nodelist If file (for input/output) is like xxx,name then xxx is used as an encoding (e.g., "utf-8,foo.txt"). ''' if __name__ != "__main__": builtin() else: if len(sys.argv) == 1: sys.argv.append('-b') import getopt try: opts, args = getopt.getopt(sys.argv[1:], "cehbi:o:n:p:x:", [ "comments", "exclusive", "help", "builtin", "in=", "out=", "namespaces=", "prefixes=", "xpath=" ]) except getopt.GetoptError, e: print sys.argv[0] + ':', e, '\nTry --help for help.\n' sys.exit(1) if len(args): print 'No arguments, only flags. Try --help for help.' sys.exit(1) IN, OUT = sys.stdin, sys.stdout query = '(//. | //@* | //namespace::*)' comments = 0 exclusive, pfxlist = None, [] nsdict = {} for opt,arg in opts: if opt in ('-h', '--help'): usage() sys.exit(0) if opt in ('-b', '--builtin'): builtin() sys.exit(0) elif opt in ('-c', '--comments'): comments = 1 elif opt in ('-n', '--namespaces'): # convert every pair of whitespace delimited values to dictionary nsl = arg.split() for i in range(0, len(nsl), 2): nsdict[nsl[i]] = nsl[i+1] # print "Namespace prefix arguments is not supported yet." elif opt in ('-e', '--exclusive'): exclusive = 1 elif opt in ( '-p', '--prefixes'): pfxlist = arg.split(',') elif opt in ('-i', '--in'): if arg.find(',') == -1: IN = open(arg, 'r') else: import codecs encoding, filename = arg.split(',') reader = codecs.lookup(encoding)[2] IN = reader(open(filename, 'r')) elif opt in ('-o', '--out'): if arg.find(',') == -1: OUT = open(arg, 'w') else: import codecs encoding, filename = arg.split(',') writer = codecs.lookup(encoding)[3] OUT = writer(open(filename, 'w')) elif opt in ('-x', '--xpath'): query = arg r = PYE() dom = r.fromStream(IN) context = Context(dom, processorNss=nsdict) nodelist = xpath.Evaluate(query, context=context) if exclusive: Canonicalize(dom, OUT, subset=nodelist, comments=comments, unsuppressedPrefixes=pfxlist) else: Canonicalize(dom, OUT, subset=nodelist, comments=comments) # nsdict=nsdict OUT.close() PyXML-0.8.2/test/test_dom.py0100644000076400001440000003365207413603010015062 0ustar martinusersimport StringIO, sys from xml.dom import Node # MUST be first from xml.dom import implementation, DOMException from xml.dom import HIERARCHY_REQUEST_ERR, NOT_FOUND_ERR from xml.dom import INDEX_SIZE_ERR, INVALID_CHARACTER_ERR, SYNTAX_ERR from xml.dom.ext.reader.Sax2 import FromXml from xml.dom.ext import PrettyPrint # Internal test function: traverse a DOM tree, then verify that all # the parent pointers are correct. Do NOT take this function as an # example of using the Python DOM interface; it knows about the hidden # details of the DOM implementation in order to check them. def _check_dom_tree(t): "Verify that all the parent pointers in a DOM tree are correct" parent = {} # Dict mapping _nodeData instances to their parent nodes = [] # Cumulative list of all the _nodeDatas encountered Queue = [t] # Queue for breadth-first traversal of tree # Do a breadth-first traversal of the DOM tree t while Queue: node = Queue[0] children = node.childNodes for c in children: # Store this node as the parent of each child parent[c] = node # Add each child to the cumulative list nodes.append(c) # Append each child to the queue Queue.append(c) # Remove the node we've just processed Queue = Queue[1:] # OK, now walk over all the children, checking that .parentNode # is correct. count = 0 for n in nodes: p = n.parentNode if p is None: assert not parent.has_key(n) else: assert p == parent[n] count = count + 1 test_text = """ This is a test

    Don't panic

    Maybe it will work.

    We can handle it

    Yes we can

    Or maybe not

    End of test.
    """ doc = FromXml(test_text) _check_dom_tree(doc) print 'Simple document' PrettyPrint(doc, sys.stdout) print # Example from the docstring at the top of xml.dom.core.py doc = implementation.createDocument(None,None,None) html = doc.createElement('html') html.setAttribute('attr', 'value') head = doc.createElement('head') title = doc.createElement('title') text = doc.createTextNode("Title goes here") title.appendChild(text) head.appendChild(title) html.appendChild(head) doc.appendChild (html) _check_dom_tree(doc) print '\nOutput of docstring example' PrettyPrint(doc, sys.stdout) print # Detailed test suite for the DOM from xml.dom import Document print '\nRunning detailed test suite' def check(cond, explanation, expected=0): truth = eval(cond) if not truth: if expected: print "XFAIL:", else: print ' *** Failed:', print explanation, '\n\t', cond doc = implementation.createDocument(None,None,None) check('isinstance(doc, Document.Document)', 'createDocument returns a Document') check('doc.parentNode == None', 'Documents have no parent') # Check that documents can only have one child n1 = doc.createElement('n1') ; n2 = doc.createElement('n2') pi = doc.createProcessingInstruction("Processing", "Instruction") doc.appendChild(pi) doc.appendChild(n1) try: doc.appendChild(n1) # n1 should be removed, and then added again except DOMException: print "XFAIL: 4DOM does not support multiple insertion of same node" try: doc.appendChild(n2) except DOMException,e: assert e.code==HIERARCHY_REQUEST_ERR else: print " *** Failed: Document.insertBefore didn't raise HierarchyRequestException" doc.replaceChild(n2, n1) # Should work try: doc.replaceChild(n1, pi) except DOMException,e: assert e.code==HIERARCHY_REQUEST_ERR else: print " *** Failed: Document.replaceChild didn't raise HierarchyRequestException" doc.replaceChild(n2, pi) # Should also work check('pi.parentNode == None', 'Document.replaceChild: PI should have no parent') try: doc.removeChild(n2) except DOMException: print "XFAIL" check('n2.parentNode == None', 'Document.removeChild: n2 should have no parent') # Check adding and deletion with DocumentFragments fragment = doc.createDocumentFragment() ; fragment.appendChild( n1 ) doc.appendChild( fragment ) check('fragment.parentNode == None', 'Doc.appendChild: fragment has no parent') check('n1.parentNode.nodeType == Node.DOCUMENT_NODE', 'Doc.appendChild: n1 now has document as parent') fragment = doc.createDocumentFragment() ; fragment.appendChild( n1 ) n2 = doc.createElement('n2') ; fragment.appendChild( n2 ) try: doc.appendChild( fragment ) except DOMException,e: assert e.code == HIERARCHY_REQUEST_ERR else: print " *** Failed: Document.fragment.appendChild didn't raise HierarchyRequestException" fragment = doc.createDocumentFragment() ; fragment.appendChild( n1 ) n2 = doc.createElement('n2') ; fragment.appendChild( n2 ) doc.appendChild( pi ) try: doc.replaceChild(fragment, pi) except DOMException: assert e.code==HIERARCHY_REQUEST_ERR else: print " *** Failed: Document.fragment.replaceChild didn't raise HierarchyRequestException" #FIXME - fragment.removeChild(n2) fragment.appendChild(pi) doc.appendChild( fragment) check('n1.parentNode == doc', "Document.fragment.replaceChild parent node is correct") _check_dom_tree(doc) # Check adding and deleting children for ordinary nodes n1 = doc.createElement('n1') ; n2 = doc.createElement('n2') check( 'n1.parentNode == None', 'newly created Element has no parent') e1 = doc.createTextNode('e1') ; e2 = doc.createTextNode('e2') e3 = doc.createTextNode('e3') n1.appendChild( e1 ) ; n1.appendChild( e2 ) ; n2.appendChild(e3) # Test .insertBefore with refChild set to a node n2.insertBefore(e1, e3) check('len(n1.childNodes) == 1', "insertBefore: node1 has 1 child") check('len(n2.childNodes) == 2', "insertBefore: node2 has 2 children") check('n1.firstChild.data=="e2"', "insertBefore: node1's child is e2") check('n2.firstChild.data=="e1"', "insertBefore: node2's first child is e1") check('n2.lastChild.data=="e3"', "insertBefore: node2's last child is e3") check('e1.parentNode.tagName == "n2"', "insertBefore: e1's parent is n2") check('e2.parentNode.tagName == "n1"', "insertBefore: e2's parent is n1") check('e3.parentNode.tagName == "n2"', "insertBefore: e3's parent is n3") try: n2.insertBefore(e1, e2) except DOMException,e: assert e.code==NOT_FOUND_ERR else: print " *** Failed: insertBefore didn't raise NotFoundException" # Test .insertBefore with refChild==None n2.insertBefore(e1, None) check('len(n2.childNodes) == 2', "None insertBefore: node1 has 2 children") check('n2.firstChild.data=="e3"', "None insertBefore: node2's first child is e3") check('n2.lastChild.data=="e1"', "None insertBefore: node2's last child is e1") # Test replaceChild ret = n1.replaceChild(e1, e2) check('e2.parentNode == None', "replaceChild: e2 has no parent") check('len(n1.childNodes) == 1', "replaceChild: node1 has 1 child") check('n1.firstChild.data=="e1"', "replaceChild: node1's only child is e1") check('ret.data == "e2"', "replaceChild: returned value node1's only child is e1") try: n1.replaceChild(e2, e2) except DOMException,e: assert e.code==NOT_FOUND_ERR else: print " *** Failed: insertBefore didn't raise NotFoundException" # Test removeChild ret = n1.removeChild( e1 ) check('e1.parentNode == None', "removeChild: e1 has no parent") check('ret.data == "e1"', "removeChild: e1 is the returned value") try: n1.removeChild(e2) except DOMException,e: assert e.code==NOT_FOUND_ERR else: print " *** Failed: removeChild didn't raise NotFoundException" # XXX two more cases for adding stuff: normal, Document, DocumentFragment # Test the functions in the CharacterData interface text = doc.createTextNode('Hello world') #FIXME - check('text[0:5].value == "Hello"', 'text: slicing a node') try: text.substringData(-5, 5) except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: substringData didn't raise IndexSizeException (negative)" try: text.substringData(200, 5) except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: substringData didn't raise IndexSizeException (larger)" try: text.substringData(5, -5) except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: substringData didn't raise IndexSizeException (negcount)" text.appendData('!') check('text.data == "Hello world!"', 'text: appendData') try: text.insertData(-5, 'string') except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: insertData didn't raise IndexSizeException (negative)" try: text.insertData(200, 'string') except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: insertData didn't raise IndexSizeException (larger)" text.insertData(5, ',') check('text.data == "Hello, world!"', 'text: insertData of ","') try: text.deleteData(-5, 5) except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: deleteData didn't raise IndexSizeException (negative)" try: text.deleteData(200, 5) except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: deleteData didn't raise IndexSizeException (larger)" text.deleteData(0, 5) check('text.data == ", world!"', 'text: deleteData of first 5 chars') try: text.replaceData(-5, 5, 'Top of the') except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: replaceData didn't raise IndexSizeException (negative)" try: text.replaceData(200, 5, 'Top of the') except DOMException,e: assert e.code==INDEX_SIZE_ERR else: print " *** Failed: replaceData didn't raise IndexSizeException (larger)" text.replaceData(0, 1, 'Top of the') check('text.data == "Top of the world!"', 'text: deleteData of first 5 chars') # Test the Element class e = doc.createElement('elem') attr = doc.createAttribute('attr2') attr.value = "v2" #check('e.toxml() == ""', 'Element: empty element') check('e.tagName == "elem"', 'Element: tag name') check('len(e.attributes) == 0', 'Element: empty get_attributes') check('e.getAttribute("dummy") == ""', 'Element: empty getAttribute') check('e.getAttributeNode("dummy") == None', 'Element: empty getAttributeNode') try: e.setAttribute('dummy', attr) except DOMException,x: assert x.code == SYNTAX_ERR # Spec says invalid character for name not value # assert x.code==INVALID_CHARACTER_ERR else: print " *** Failed: setAttribute didn't raise InvalidCharacterException" e.setAttribute('dummy', 'value') #check('e.toxml() == ""', 'Element with 1 attribute') check('e.getAttribute("dummy") == "value"', 'Element: getAttribute w/ value') check('e.getAttributeNode("dummy").value == "value"', 'Element: getAttributeNode w/ value') a2 = e.getAttributeNode( 'dummy' ) check('a2.parentNode == None', 'Attribute: should have no parent') check('a2.value == "value"', 'Attribute: value is correct') e.removeAttribute('dummy') check('len(e.attributes) == 0', 'Element: attribute removed') e.setAttributeNode(attr) check('e.attributes[0].value == "v2"', 'Element: attribute node added') a2 = doc.createAttribute('attr2') a2.value = 'v3' ret = e.setAttributeNode(a2) check('e.attributes[0].value == "v3"', 'Element: attribute node replaced') check('ret.value == "v2"', 'Element: deleted attribute node returned') e.removeAttributeNode(a2) check('len(e.attributes) == 0', 'Element: attribute node removed') # Check handling of namespace prefixes #FIXME (start) #e.setAttribute('xmlns', 'http://defaulturi') #e.setAttribute('xmlns:html', 'http://htmluri') #check('e.ns_prefix[""] == "http://defaulturi"', # 'Default namespace with setAttribute') #check('e.ns_prefix["html"] == "http://htmluri"', # 'Prefixed namespace with setAttribute') #e.removeAttribute('xmlns:html') #check('not e.ns_prefix.has_key("html")', # 'Prefixed namespace with removeAttribute') #e.removeAttribute('xmlns') #check('len(e.ns_prefix) == 0', 'Default namespace with removeAttribute') #default = doc.createAttribute('xmlns') ; default.value = "http://defaulturi" #html = doc.createAttribute('xmlns:html') ; html.value = "http://htmluri" #e.setAttributeNode(default) ; e.setAttributeNode(html) #check('e.ns_prefix[""] == "http://defaulturi"', # 'Default namespace with setAttributeNode') #check('e.ns_prefix["html"] == "http://htmluri"', # 'Prefixed namespace with setAttributeNode') #e.removeAttributeNode(html) #check('not e.ns_prefix.has_key("html")', # 'Prefixed namespace with removeAttribute') #e.removeAttributeNode(default) #FIXME (end) # # Check getElementsByTagName # check('len(e.getElementsByTagName("elem")) == 0', "getElementsByTagName doesn't return element") check('len(e.getElementsByTagName("*")) == 0', "getElementsByTagName doesn't return element") # Check CharacterData interfaces using Text nodes t1 = doc.createTextNode('first') ; e.appendChild( t1 ) t2 = doc.createTextNode('second') ; e.appendChild( t2 ) t3 = doc.createTextNode('third') ; e.appendChild( t3 ) #check('e.toxml() == "firstsecondthird"', # "Element: content of three Text nodes as children") check('len(e.childNodes) == 3', 'Element: three Text nodes as children') e.normalize() check('e.firstChild.data == "firstsecondthird"', "Element: normalized Text nodes") check('len(e.childNodes) == 1', 'Element: should be one normalized Text node') check('t2.parentNode == None', 'Element: normalized t2 should have no parent') check('t3.parentNode == None', 'Element: normalized t3 should have no parent') # Text node t1.splitText(5) check('e.firstChild.data == "first"', "Element: newly split Text nodes") check('len(e.childNodes) == 2', 'Text: should be two split Text nodes') check('e.lastChild.data == "secondthird"', "Element: newly split Text nodes") # Check comparisons; e1 and e2 are different proxies for the same underlying # node n1 = doc.createElement('n1') ; n2 = doc.createElement('n2') n1.appendChild(n2) e1 = n1 ; e2 = n2.parentNode check('e1 is e2', 'Two proxies are different according to "is" operator') check('e1 == e2', 'Two proxies are different according to "==" operator') # Done at last! print 'Test suite completed' PyXML-0.8.2/test/test_domreg.py0100644000076400001440000000566407557321762015606 0ustar martinusers"""Test DOM registration framework.""" import unittest import test_support from xml.dom import domreg def parse_feature_string(s): # helper to make sure the results are always plain lists return list(domreg._parse_feature_string(s)) class DomregTestCase(unittest.TestCase): def setUp(self): domreg.registerDOMImplementation("its-a-fake", self.getDOMImplementation) def getDOMImplementation(self): self.fake = FakeDOM(self.my_features) return self.fake def test_simple(self): self.assertEqual(parse_feature_string("simple"), [("simple", None)]) self.assertEqual(parse_feature_string("simple 1.0"), [("simple", "1.0")]) self.assertEqual(parse_feature_string("simple complex"), [("simple", None), ("complex", None)]) self.assertEqual(parse_feature_string("simple 2 complex 3.1.4.2"), [("simple", "2"), ("complex", "3.1.4.2")]) def test_extra_version(self): self.assertRaises(ValueError, domreg._parse_feature_string, "1.0") self.assertRaises(ValueError, domreg._parse_feature_string, "1 simple") self.assertRaises(ValueError, domreg._parse_feature_string, "simple 1 2") def test_find_myself(self): self.my_features = [("splat", "1"), ("splat", "2"), ("splat", None)] self.failUnless(domreg.getDOMImplementation(features="splat") is self.fake) self.failUnless(domreg.getDOMImplementation(features="splat 1") is self.fake) self.failUnless(domreg.getDOMImplementation(features="splat 2") is self.fake) self.failUnless(domreg.getDOMImplementation(features="splat 1 splat 2") is self.fake) self.failUnless(domreg.getDOMImplementation(features="splat 2 splat 1") is self.fake) def _test_cant_find(self): # This test is disabled since we need to determine what the # right thing to do is. ;-( The DOM Level 3 draft says # getDOMImplementation() should return null when there isn't a # match, but the existing Python API raises ImportError. self.my_features = [] self.failUnless(domreg.getDOMImplementation(features="splat") is None) self.failUnless(domreg.getDOMImplementation(features="splat 1") is None) class FakeDOM: def __init__(self, features): self.__features = features def hasFeature(self, feature, version): return (feature, version) in self.__features def test_suite(): return unittest.makeSuite(DomregTestCase) def test_main(): test_support.run_suite(test_suite()) if __name__ == "__main__": test_support.verbose = 1 test_main() PyXML-0.8.2/test/test_encodings.py0100644000076400001440000000241407225623150016254 0ustar martinusers#!/usr/bin/env python """ This will show russian text in koi8-r encoding. """ from xml.parsers import expat import string # Produces ImportError in 1.5, since this test can't possibly pass there import codecs class XMLTree: def __init__(self): pass # Define a handler for start element events def StartElement(self, name, attrs ): #name = name.encode() print "<", repr(name), ">" print "attr name:", attrs.get("name",unicode("")).encode("koi8-r") print "attr value:", attrs.get("value",unicode("")).encode("koi8-r") def EndElement(self, name ): print "" def CharacterData(self, data ): if string.strip(data): data = data.encode("koi8-r") print data def LoadTree(self, filename): # Create a parser Parser = expat.ParserCreate() # Tell the parser what the start element handler is Parser.StartElementHandler = self.StartElement Parser.EndElementHandler = self.EndElement Parser.CharacterDataHandler = self.CharacterData # Parse the XML File ParserStatus = Parser.Parse(open(filename,'r').read(), 1) def runTest(): win = XMLTree() win.LoadTree("enc_test.xml") return win runTest() PyXML-0.8.2/test/test_filter.py0100644000076400001440000001277107550506757015615 0ustar martinusersimport pprint import sys from xml.dom import xmlbuilder, expatbuilder, Node from xml.dom.NodeFilter import NodeFilter class Filter(xmlbuilder.DOMBuilderFilter): whatToShow = NodeFilter.SHOW_ELEMENT def startContainer(self, node): assert node.nodeType == Node.ELEMENT_NODE if node.tagName == "skipthis": return self.FILTER_SKIP elif node.tagName == "rejectbefore": return self.FILTER_REJECT elif node.tagName == "stopbefore": return self.FILTER_INTERRUPT else: return self.FILTER_ACCEPT def acceptNode(self, node): assert node.nodeType == Node.ELEMENT_NODE if node.tagName == "skipafter": return self.FILTER_SKIP elif node.tagName == "rejectafter": return self.FILTER_REJECT elif node.tagName == "stopafter": return self.FILTER_INTERRUPT else: return self.FILTER_ACCEPT class RecordingFilter: # Inheriting from xml.dom.xmlbuilder.DOMBuilderFilter is not # required, so we won't inherit from it this time to make sure it # isn't a problem. We have to implement the entire interface # directly. whatToShow = NodeFilter.SHOW_ALL def __init__(self): self.events = [] def startContainer(self, node): self.events.append(("start", node.nodeType, str(node.nodeName))) return xmlbuilder.DOMBuilderFilter.FILTER_ACCEPT def acceptNode(self, node): self.events.append(("accept", node.nodeType, str(node.nodeName))) return xmlbuilder.DOMBuilderFilter.FILTER_ACCEPT simple_options = xmlbuilder.Options() simple_options.filter = Filter() simple_options.namespaces = 0 record_options = xmlbuilder.Options() record_options.namespaces = 0 def checkResult(src): print dom = expatbuilder.makeBuilder(simple_options).parseString(src) print dom.toxml() dom.unlink() def checkFilterEvents(src, record, what=NodeFilter.SHOW_ALL): record_options.filter = RecordingFilter() record_options.filter.whatToShow = what dom = expatbuilder.makeBuilder(record_options).parseString(src) if record != record_options.filter.events: print print "Received filter events:" pprint.pprint(record_options.filter.events) print print "Expected filter events:" pprint.pprint(record) dom.unlink() # a simple case of skipping an element checkResult("textmoreabcxyz") # skip an element nested indirectly within another skipped element checkResult('''\ Text. Nested text. Nested text in skipthis element. More nested text. Outer text. ''') # skip an element nested indirectly within another skipped element checkResult('''\ Text. Nested text. Nested text in skipthis element. More nested text. More text. Outer text. ''') checkResult("") checkResult("") checkResult('''\ Text. ''') checkResult('''\ Text. ''') # Make sure the document element is not passed to the filter: checkResult("") checkResult("") checkResult("") checkResult("text and more") checkResult("text and more") checkResult("text") checkFilterEvents("", []) checkFilterEvents("", []) checkFilterEvents("", [ ("start", Node.ELEMENT_NODE, "e"), ("accept", Node.ELEMENT_NODE, "e"), ]) src = """\ ]> """ checkFilterEvents(src, [ ("accept", Node.DOCUMENT_TYPE_NODE, "doc"), ("accept", Node.ENTITY_NODE, "e"), ("accept", Node.NOTATION_NODE, "n"), ("accept", Node.COMMENT_NODE, "#comment"), ("accept", Node.PROCESSING_INSTRUCTION_NODE, "sample"), ("start", Node.ELEMENT_NODE, "e"), ("accept", Node.PROCESSING_INSTRUCTION_NODE, "pi"), ("accept", Node.COMMENT_NODE, "#comment"), ("accept", Node.ELEMENT_NODE, "e"), ]) # Show everything except a couple of things to the filter, to check # that whatToShow is implemented. This isn't sufficient to be a # black-box test, but will get us started. checkFilterEvents(src, [ ("accept", Node.DOCUMENT_TYPE_NODE, "doc"), ("accept", Node.ENTITY_NODE, "e"), ("accept", Node.NOTATION_NODE, "n"), ("accept", Node.PROCESSING_INSTRUCTION_NODE, "sample"), ("start", Node.ELEMENT_NODE, "e"), ("accept", Node.PROCESSING_INSTRUCTION_NODE, "pi"), ("accept", Node.ELEMENT_NODE, "e"), ], what=NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_COMMENT) checkFilterEvents(src, [ ("accept", Node.DOCUMENT_TYPE_NODE, "doc"), ("accept", Node.ENTITY_NODE, "e"), ("accept", Node.NOTATION_NODE, "n"), ("accept", Node.COMMENT_NODE, "#comment"), ("start", Node.ELEMENT_NODE, "e"), ("accept", Node.COMMENT_NODE, "#comment"), ("accept", Node.ELEMENT_NODE, "e"), ], what=NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_PROCESSING_INSTRUCTION) PyXML-0.8.2/test/test_howto.py0100644000076400001440000001110407507520267015447 0ustar martinusers# Test suite containing code from the XML HOWTO # SAX testing code print "SAX tests:\n" from xml.sax import saxutils, make_parser, ContentHandler from xml.sax.handler import feature_namespaces import StringIO import string comic_xml = StringIO.StringIO(""" Neil Gaiman Glyn Dillon Charles Vess Peter Milligan Chris Bachalo """) class FindIssue(saxutils.DefaultHandler): def __init__(self, title, number): self.search_title, self.search_number = title, number def startElement(self, name, attrs): # If it's not a comic element, ignore it if name != 'comic': return # Look for the title and number attributes (see text) title = attrs.get('title', None) number = attrs.get('number', None) if title == self.search_title and number == self.search_number: print title, '#'+str(number), 'found' def error(self, exception): import sys sys.stderr.write("%s\n" % exception) if 1: # Create a parser parser = make_parser() # Disable namespace processing parser.setFeature(feature_namespaces, 0) # Create the handler dh = FindIssue('Sandman', '62') # Tell the parser to use our handler parser.setContentHandler(dh) parser.setErrorHandler(dh) # Parse the input parser.parse(comic_xml) def normalize_whitespace(text): "Remove redundant whitespace from a string" return string.join(string.split(text), ' ') class FindWriter(ContentHandler): def __init__(self, search_name): # Save the name we're looking for self.search_name = normalize_whitespace(search_name) # Initialize the flag to false self.inWriterContent = 0 def startElement(self, name, attrs): # If it's a comic element, save the title and issue if name == 'comic': title = normalize_whitespace(attrs.get('title', "")) number = normalize_whitespace(attrs.get('number', "")) self.this_title = title self.this_number = number # If it's the start of a writer element, set flag elif name == 'writer': self.inWriterContent = 1 self.writerName = "" def characters(self, ch): if self.inWriterContent: self.writerName = self.writerName + ch def endElement(self, name): if name == 'writer': self.inWriterContent = 0 self.writerName = normalize_whitespace(self.writerName) if self.writerName == self.search_name: print self.this_title, self.this_number if 1: # Create a parser parser = make_parser() # Disable namespace processing parser.setFeature(feature_namespaces, 0) # Create the handler dh = FindWriter('Peter Milligan') # Tell the parser to use our handler parser.setContentHandler(dh) # Print a title print '\nTitles by Peter Milligan:' # Parse the input comic_xml.seek(0) parser.parse(comic_xml) # DOM tests print "DOM tests:\n" import sys from xml.dom.ext.reader import Sax2 from xml.dom.ext import PrettyPrint dom_xml = """ No description XML bookmarks SIG for XML Processing in Python """ # Parse the input into a DOM tree reader = Sax2.Reader() doc = reader.fromStream( StringIO.StringIO(dom_xml) ) # Print it # for testing, we must explicitly pass sys.stdout, as regrtest will # bind this to a different object PrettyPrint(doc, sys.stdout) # whitespace-removal currently not supported # utils.strip_whitespace(doc) # print ' With whitespace removed:' # print doc.toxml() # Builder code print 'DOM creation tests' from xml.dom.DOMImplementation import implementation d = implementation.createDocument(None, None, None) # Create the root element r = d.createElement("html") d.appendChild(r) # Create an empty 'head' element r.appendChild(d.createElement("head")) # Start the 'body' element, giving it an attribute b = d.createElement("body") b.setAttribute('background','#ffffff') r.appendChild(b) # Add a text node b.appendChild(d.createTextNode("The body text goes here.")) # Print the document PrettyPrint(d, sys.stdout) PyXML-0.8.2/test/test_htmlb.py0100644000076400001440000000244507413603010015405 0ustar martinusers# dom.html_builder tests from xml.dom.ext.reader import HtmlLib from xml.dom.ext import XHtmlPrettyPrint import sys good_html = """

    I prefer (all things being equal) regularity/orthogonality and logical syntax/semantics in a language because there is less to have to remember. (Of course I know all things are NEVER really equal!)

    Guido van Rossum, 6 Dec 91

    The details of that silly code are irrelevant.

    Tim Peters, 4 Mar 92 & < > é ö   """ bad_html = """ Interdigitated bold and italic tags.& < > é ö   """ # Try the good output with both settings of ignore_mismatched_end_tags # At the moment, don't; HtmlLib does not have these two modes of # operation. print "Good document" b = HtmlLib.FromHtml(good_html) #b.expand_entities = b.expand_entities + ('eacute',) XHtmlPrettyPrint(b, stream=sys.stdout, encoding = "ISO-8859-1") # Sgmlop currently does not complain about mismatched or misplaced tags # or other aspects of invalidity. # print "Bad document" # try: # HtmlLib.FromHtml(bad_html) # except html_builder.BadHTMLError: # print "Exception raised for bad HTML" # else: # print "*** ERROR: no exception raised for bad HTML" PyXML-0.8.2/test/test_javadom.py0100644000076400001440000003606207413603010015722 0ustar martinusers""" A suite of unit tests for javadom.py. Hopefully this can also be used with 4DOM. """ import sys import unittest from xml.dom import javadom # --- Document class DocumentTestCase(unittest.TestCase): def setUp(self): self.document = self.createDocument() def checkNodeType(self): assert self.document._get_nodeType() == javadom.DOCUMENT_NODE def checkNodeName(self): assert self.document._get_nodeName() == "#document" def checkNodeValue(self): assert self.document._get_nodeValue() == None def checkAttributes(self): assert self.document._get_attributes() == None def checkChildNodes(self): assert len(self.document._get_childNodes()) == 0 def checkParentNode(self): assert self.document._get_parentNode() == None def checkFirstChild(self): assert self.document._get_firstChild() == None def checkLastChild(self): assert self.document._get_lastChild() == None def checkPreviousSibling(self): assert self.document._get_previousSibling() == None def checkNextSibling(self): assert self.document._get_nextSibling() == None def checkOwnerDocument(self): assert self.document._get_ownerDocument() == None def checkGetDoctype(self): assert self.document._get_doctype() == None def checkGetImplementation(self): assert self.document._get_implementation() != None def checkGetDocumentElement(self): assert self.document._get_documentElement() == None # --- Element class ElementTestCase(unittest.TestCase): def setUp(self): self.element = self.createDocument().createElement("per") def checkNodeType(self): assert self.element._get_nodeType() == javadom.ELEMENT_NODE def checkNodeName(self): assert self.element._get_nodeName() == "per" def checkNodeValue(self): assert self.element._get_nodeValue() == None def checkAttributes(self): assert self.element._get_attributes()._get_length() == 0 def checkChildNodes(self): assert len(self.element._get_childNodes()) == 0 def checkParentNode(self): assert self.element._get_parentNode() == None def checkFirstChild(self): assert self.element._get_firstChild() == None def checkLastChild(self): assert self.element._get_lastChild() == None def checkPreviousSibling(self): assert self.element._get_previousSibling() == None def checkNextSibling(self): assert self.element._get_nextSibling() == None def checkOwnerDocument(self): assert self.element._get_ownerDocument() != None def checkTagName(self): assert self.element._get_tagName() == "per" def checkGetAttribute(self): assert self.element.getAttribute("ugga") == "" def checkGetAttributeNode(self): assert self.element.getAttributeNode("ugga") == None def checkNormalize(self): self.element.normalize() def checkRemoveAttribute(self): self.element.removeAttribute("ugga") # def checkRemoveAttributeNode(self): # try: # self.element.removeAttributeNode("ugga") # must have a node # result = 0 # except javadom.DOMException, e: # result = 1 # except: # result = 2 # assert result == 1 # missing: normalize, setAttribute, setAttributeNode, getElementsByTagName # --- CharacterData class CharacterDataTestCase(unittest.TestCase): def checkChildNodes(self): assert len(self.chardata._get_childNodes()) == 0 def checkParentNode(self): assert self.chardata._get_parentNode() == None def checkFirstChild(self): assert self.chardata._get_firstChild() == None def checkLastChild(self): assert self.chardata._get_lastChild() == None def checkPreviousSibling(self): assert self.chardata._get_previousSibling() == None def checkNextSibling(self): assert self.chardata._get_nextSibling() == None def checkOwnerDocument(self): assert self.chardata._get_ownerDocument() != None def checkGetData(self): assert self.chardata._get_data() == "com" def checkSetData(self): self.chardata._set_data("data") assert self.chardata._get_data() == "data" def checkGetLength(self): assert self.chardata._get_length() == 3 def checkSubstringData(self): assert self.chardata.substringData(0, 2) == "co" def checkAppendData(self): self.chardata.appendData("com") assert self.chardata._get_data() == "comcom" def checkInsertData(self): self.chardata.insertData(2, "com") assert self.chardata._get_data() == "cocomm" def checkDeleteData(self): self.chardata.deleteData(1, 1) assert self.chardata._get_data() == "cm" def checkReplaceData(self): self.chardata.replaceData(1, 3, "uuuu") assert self.chardata._get_data() == "cuuuu" # --- Comment class CommentTestCase(CharacterDataTestCase): def setUp(self): self.chardata = self.createDocument().createComment("com") def checkNodeType(self): assert self.chardata._get_nodeType() == javadom.COMMENT_NODE def checkNodeName(self): assert self.chardata._get_nodeName() == "#comment" def checkNodeValue(self): assert self.chardata._get_nodeValue() == "com" def checkAttributes(self): assert self.chardata._get_attributes() == None # --- ProcessingInstruction class ProcessingInstructionTestCase(unittest.TestCase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") def checkNodeType(self): assert self.pi._get_nodeType() == javadom.PROCESSING_INSTRUCTION_NODE def checkNodeName(self): assert self.pi._get_nodeName() == "pit" def checkNodeValue(self): assert self.pi._get_nodeValue() == "pid" def checkAttributes(self): assert self.pi._get_attributes() == None def checkChildNodes(self): assert len(self.pi._get_childNodes()) == 0 def checkParentNode(self): assert self.pi._get_parentNode() == None def checkFirstChild(self): assert self.pi._get_firstChild() == None def checkLastChild(self): assert self.pi._get_lastChild() == None def checkPreviousSibling(self): assert self.pi._get_previousSibling() == None def checkNextSibling(self): assert self.pi._get_nextSibling() == None def checkOwnerDocument(self): assert self.pi._get_ownerDocument() != None def checkGetTarget(self): assert self.pi._get_target() == "pit" def checkGetData(self): assert self.pi._get_data() == "pid" def checkSetData(self): self.pi._set_data("uggg") assert self.pi._get_data() == "uggg" # --- Text class TextTestCase(CharacterDataTestCase): def setUp(self): self.chardata = self.createDocument().createTextNode("com") def checkNodeType(self): assert self.chardata._get_nodeType() == javadom.TEXT_NODE def checkNodeName(self): assert self.chardata._get_nodeName() == "#text" def checkNodeValue(self): assert self.chardata._get_nodeValue() == "com" def checkAttributes(self): assert self.chardata._get_attributes() == None # --- CDATASection class CDATASectionTestCase(TextTestCase): def setUp(self): self.chardata = self.createDocument().createCDATASection("com") def checkNodeType(self): assert self.chardata._get_nodeType() == javadom.CDATA_SECTION_NODE def checkNodeName(self): assert self.chardata._get_nodeName() == "#cdata-section" def checkNodeValue(self): assert self.chardata._get_nodeValue() == "com" def checkAttributes(self): assert self.chardata._get_attributes() == None # --- Attr class AttrTestCase(unittest.TestCase): def setUp(self): self.attr = self.createDocument().createAttribute("name") def checkNodeType(self): assert self.attr._get_nodeType() == javadom.ATTRIBUTE_NODE def checkNodeName(self): assert self.attr._get_nodeName() == "name" def checkNodeValue(self): assert self.attr._get_nodeValue() == None def checkAttributes(self): assert self.attr._get_attributes() == None def checkChildNodes(self): assert len(self.attr._get_childNodes()) == 0 def checkParentNode(self): assert self.attr._get_parentNode() == None def checkFirstChild(self): assert self.attr._get_firstChild() == None def checkLastChild(self): assert self.attr._get_lastChild() == None def checkPreviousSibling(self): assert self.attr._get_previousSibling() == None def checkNextSibling(self): assert self.attr._get_nextSibling() == None def checkOwnerDocument(self): assert self.attr._get_ownerDocument() != None def checkGetName(self): assert self.attr._get_name() == "name" def checkGetSpecified(self): assert self.attr._get_specified() def checkGetValue(self): assert self.attr._get_value() == None def checkSetValue(self): self.attr._set_value("14") assert self.attr._get_value() == "14" # --- EntityReference class EntityReferenceTestCase(unittest.TestCase): def setUp(self): self.entref = self.createDocument().createEntityReference("eref") def checkNodeType(self): assert self.entref._get_nodeType() == javadom.ENTITY_REFERENCE_NODE def checkNodeName(self): assert self.entref._get_nodeName() == "eref" def checkNodeValue(self): assert self.entref._get_nodeValue() == None def checkAttributes(self): assert self.entref._get_attributes() == None def checkChildNodes(self): assert len(self.entref._get_childNodes()) == 0 def checkParentNode(self): assert self.entref._get_parentNode() == None def checkFirstChild(self): assert self.entref._get_firstChild() == None def checkLastChild(self): assert self.entref._get_lastChild() == None def checkPreviousSibling(self): assert self.entref._get_previousSibling() == None def checkNextSibling(self): assert self.entref._get_nextSibling() == None def checkOwnerDocument(self): assert self.entref._get_ownerDocument() != None # --- DocumentFragment class DocumentFragmentTestCase(unittest.TestCase): def setUp(self): self.docfrag = self.createDocument().createDocumentFragment() def checkNodeType(self): assert self.docfrag._get_nodeType() == javadom.DOCUMENT_FRAGMENT_NODE def checkNodeName(self): assert self.docfrag._get_nodeName() == "#document-fragment" def checkNodeValue(self): assert self.docfrag._get_nodeValue() == None def checkAttributes(self): assert self.docfrag._get_attributes() == None def checkChildNodes(self): assert len(self.docfrag._get_childNodes()) == 0 def checkParentNode(self): assert self.docfrag._get_parentNode() == None def checkFirstChild(self): assert self.docfrag._get_firstChild() == None def checkLastChild(self): assert self.docfrag._get_lastChild() == None def checkPreviousSibling(self): assert self.docfrag._get_previousSibling() == None def checkNextSibling(self): assert self.docfrag._get_nextSibling() == None def checkOwnerDocument(self): assert self.docfrag._get_ownerDocument() != None # --- NodeList class NodeListTestCase(unittest.TestCase): def setUp(self): self.list = self.createDocument().createElement("foo")._get_childNodes() def checkLen(self): assert len(self.list) == 0 def checkGetLength(self): assert self.list._get_length() == 0 def checkItem(self): assert self.list.item(0) == None def checkGetItem(self): try: self.list[0] case = 0 except IndexError: case = 1 except: case = 2 assert case == 1 def checkGetSlice(self): assert self.list[2 : 5] == [] # --- NamedNodeMap class NamedNodeMapTestCase(unittest.TestCase): def setUp(self): self.map = self.createDocument().createElement("foo")._get_attributes() def checkLen(self): assert len(self.map) == 0 def checkGetLength(self): assert self.map._get_length() == 0 def checkGetNamedItem(self): assert self.map.getNamedItem("uuu") == None # setNamedItem def checkRemoveNamedItem(self): try: self.map.removeNamedItem("uuu") case = 0 except javadom.DOMException: case = 1 except: case = 2 assert case == 1 def checkItem(self): assert self.map.item(0) == None def checkGetItem(self): try: self.map["uuu"] case = 0 except KeyError: case = 1 except: case = 2 assert case == 1 def checkGet(self): assert self.map.get("uuu", 5) == 5 def checkHasKey(self): assert not self.map.has_key("uuu") def checkItems(self): assert self.map.items() == [] def checkKeys(self): assert self.map.keys() == [] def checkValues(self): assert self.map.values() == [] # --- Implementation versions class XercesBase: def createDocument(self): return javadom.XercesDomImplementation().createDocument() class BrownellBase: def createDocument(self): return javadom.BrownellDomImplementation().createDocument() class SunBase: def createDocument(self): return javadom.SunDomImplementation().createDocument() class FourthoughtBase: def createDocument(self): return Document(None) class IndelvBase: def createDocument(self): return javadom.IndelvDomImplementation().createDocument() class SxpBase: def createDocument(self): return javadom.SxpDomImplementation().createDocument() class OpenXmlBase: def createDocument(self): return javadom.OpenXmlDomImplementation().createDocument() # --- Create test suite and run it cases = [DocumentTestCase, ElementTestCase, CommentTestCase, ProcessingInstructionTestCase, CDATASectionTestCase, TextTestCase, AttrTestCase, EntityReferenceTestCase, DocumentFragmentTestCase, NodeListTestCase, NamedNodeMapTestCase] impls = [XercesBase, BrownellBase, SunBase,# FourthoughtBase, IndelvBase, SxpBase, OpenXmlBase] outf = open("out.txt", "w") for impl in impls: suite = unittest.TestSuite() implname = impl.__name__[ : -4] outf.write("===== %s =====\n" % implname) for case in cases: casename = case.__name__[ : -8] exec ("class %s%sTestCase(%sBase, %sTestCase): pass" % (implname, casename, implname, casename)) tc = locals()["%s%sTestCase" % (implname, casename)] suite.addTests(unittest.makeSuite(tc, 'check')._tests) runner = unittest.TextTestRunner(outf) runner.run(suite) outf.write("\n\n") outf.close() PyXML-0.8.2/test/test_marshal.py0100644000076400001440000000104107534565153015740 0ustar martinusers# built-in tests from xml.marshal import generic, wddx generic.runtests() wddx.runtests() # additional tests try: from test.test_support import verify except ImportError: from test.test_support import TestFailed def verify(condition, reason="test failed"): if not condition: raise TestFailed(reason) # test for correct processing of ignorable whitespace data = """ 1 2 """ verify(generic.loads(data) == [1, 2]) PyXML-0.8.2/test/test_minidom.py0100644000076400001440000013516007614616347015760 0ustar martinusers# test for xml.dom.minidom import os import sys import pickle import traceback from StringIO import StringIO from test.test_support import verbose import xml.dom import xml.dom.minidom import xml.parsers.expat from xml.dom.minidom import parse, Node, Document, parseString from xml.dom.minidom import getDOMImplementation try: from os import extsep except ImportError: extsep = '.' if __name__ == "__main__": base = sys.argv[0] else: base = __file__ tstfile = os.path.join(os.path.dirname(base), "test"+extsep+"xml") del base # Python 2.1 and earlier does not fully support the NodeList interface testlist = xml.dom.minidom.NodeList() try: testlist.length except AttributeError: def t_length(list, length): return len(list) == length def t_item(list, index, item): if item is None: # .item can go past the end, indexing cannot return 1 return list[index] is item else: def t_length(list, length): return len(list) == length and list.length == length def t_item(list, index, item): if item is None: return list.item(index) is item return list[index] is item and list.item(index) is item del testlist def confirm(test, testname = "Test"): if not test: print "Failed " + testname raise Exception def testParseFromFile(): dom = parse(StringIO(open(tstfile).read())) dom.unlink() confirm(isinstance(dom,Document)) def testGetElementsByTagName(): dom = parse(tstfile) confirm(dom.getElementsByTagName("LI") == \ dom.documentElement.getElementsByTagName("LI")) dom.unlink() def testInsertBefore(): dom = parseString("") root = dom.documentElement elem = root.childNodes[0] nelem = dom.createElement("element") root.insertBefore(nelem, elem) confirm(t_length(root.childNodes, 2) and t_item(root.childNodes, 0, nelem) and t_item(root.childNodes, 1, elem) and root.firstChild is nelem and root.lastChild is elem and root.toxml() == "" , "testInsertBefore -- node properly placed in tree") nelem = dom.createElement("element") root.insertBefore(nelem, None) confirm(t_length(root.childNodes, 3) and t_item(root.childNodes, 1, elem) and t_item(root.childNodes, 2, nelem) and root.lastChild is nelem and nelem.previousSibling is elem and root.toxml() == "" , "testInsertBefore -- node properly placed in tree") nelem2 = dom.createElement("bar") root.insertBefore(nelem2, nelem) confirm(t_length(root.childNodes, 4) and t_item(root.childNodes, 2, nelem2) and t_item(root.childNodes, 3, nelem) and nelem2.nextSibling is nelem and nelem.previousSibling is nelem2 and root.toxml() == "" , "testInsertBefore -- node properly placed in tree") dom.unlink() def _create_fragment_test_nodes(): dom = parseString("") orig = dom.createTextNode("original") c1 = dom.createTextNode("foo") c2 = dom.createTextNode("bar") c3 = dom.createTextNode("bat") dom.documentElement.appendChild(orig) frag = dom.createDocumentFragment() frag.appendChild(c1) frag.appendChild(c2) frag.appendChild(c3) return dom, orig, c1, c2, c3, frag def testInsertBeforeFragment(): dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom.documentElement.insertBefore(frag, None) confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), "insertBefore(, None)") frag.unlink() dom.unlink() # dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom.documentElement.insertBefore(frag, orig) confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig), "insertBefore(, orig)") frag.unlink() dom.unlink() def testAppendChild(): dom = parse(tstfile) dom.documentElement.appendChild(dom.createComment(u"Hello")) confirm(dom.documentElement.childNodes[-1].nodeName == "#comment") confirm(dom.documentElement.childNodes[-1].data == "Hello") dom.unlink() def testAppendChildFragment(): dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom.documentElement.appendChild(frag) confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), "appendChild()") frag.unlink() dom.unlink() def testReplaceChildFragment(): dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom.documentElement.replaceChild(frag, orig) orig.unlink() confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3), "replaceChild()") frag.unlink() dom.unlink() def testLegalChildren(): dom = Document() elem = dom.createElement('element') text = dom.createTextNode('text') try: dom.appendChild(text) except xml.dom.HierarchyRequestErr: pass else: print "dom.appendChild didn't raise HierarchyRequestErr" dom.appendChild(elem) try: dom.insertBefore(text, elem) except xml.dom.HierarchyRequestErr: pass else: print "dom.appendChild didn't raise HierarchyRequestErr" try: dom.replaceChild(text, elem) except xml.dom.HierarchyRequestErr: pass else: print "dom.appendChild didn't raise HierarchyRequestErr" nodemap = elem.attributes try: nodemap.setNamedItem(text) except xml.dom.HierarchyRequestErr: pass else: print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr" try: nodemap.setNamedItemNS(text) except xml.dom.HierarchyRequestErr: pass else: print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr" elem.appendChild(text) dom.unlink() def testNamedNodeMapSetItem(): dom = Document() elem = dom.createElement('element') attrs = elem.attributes attrs["foo"] = "bar" a = attrs.item(0) confirm(a.ownerDocument is dom, "NamedNodeMap.__setitem__() sets ownerDocument") confirm(a.ownerElement is elem, "NamedNodeMap.__setitem__() sets ownerElement") confirm(a.value == "bar", "NamedNodeMap.__setitem__() sets value") confirm(a.nodeValue == "bar", "NamedNodeMap.__setitem__() sets nodeValue") elem.unlink() dom.unlink() def testNonZero(): dom = parse(tstfile) confirm(dom)# should not be zero dom.appendChild(dom.createComment("foo")) confirm(not dom.childNodes[-1].childNodes) dom.unlink() def testUnlink(): dom = parse(tstfile) dom.unlink() def testElement(): dom = Document() dom.appendChild(dom.createElement("abc")) confirm(dom.documentElement) dom.unlink() def testAAA(): dom = parseString("") el = dom.documentElement el.setAttribute("spam", "jam2") confirm(el.toxml() == '', "testAAA") a = el.getAttributeNode("spam") confirm(a.ownerDocument is dom, "setAttribute() sets ownerDocument") confirm(a.ownerElement is dom.documentElement, "setAttribute() sets ownerElement") dom.unlink() def testAAB(): dom = parseString("") el = dom.documentElement el.setAttribute("spam", "jam") el.setAttribute("spam", "jam2") confirm(el.toxml() == '', "testAAB") dom.unlink() def testAddAttr(): dom = Document() child = dom.appendChild(dom.createElement("abc")) child.setAttribute("def", "ghi") confirm(child.getAttribute("def") == "ghi") confirm(child.attributes["def"].value == "ghi") child.setAttribute("jkl", "mno") confirm(child.getAttribute("jkl") == "mno") confirm(child.attributes["jkl"].value == "mno") confirm(len(child.attributes) == 2) child.setAttribute("def", "newval") confirm(child.getAttribute("def") == "newval") confirm(child.attributes["def"].value == "newval") confirm(len(child.attributes) == 2) dom.unlink() def testDeleteAttr(): dom = Document() child = dom.appendChild(dom.createElement("abc")) confirm(len(child.attributes) == 0) child.setAttribute("def", "ghi") confirm(len(child.attributes) == 1) del child.attributes["def"] confirm(len(child.attributes) == 0) dom.unlink() def testRemoveAttr(): dom = Document() child = dom.appendChild(dom.createElement("abc")) child.setAttribute("def", "ghi") confirm(len(child.attributes) == 1) child.removeAttribute("def") confirm(len(child.attributes) == 0) dom.unlink() def testRemoveAttrNS(): dom = Document() child = dom.appendChild( dom.createElementNS("http://www.python.org", "python:abc")) child.setAttributeNS("http://www.w3.org", "xmlns:python", "http://www.python.org") child.setAttributeNS("http://www.python.org", "python:abcattr", "foo") confirm(len(child.attributes) == 2) child.removeAttributeNS("http://www.python.org", "abcattr") confirm(len(child.attributes) == 1) dom.unlink() def testRemoveAttributeNode(): dom = Document() child = dom.appendChild(dom.createElement("foo")) child.setAttribute("spam", "jam") confirm(len(child.attributes) == 1) node = child.getAttributeNode("spam") child.removeAttributeNode(node) confirm(len(child.attributes) == 0 and child.getAttributeNode("spam") is None) dom.unlink() def testChangeAttr(): dom = parseString("") el = dom.documentElement el.setAttribute("spam", "jam") confirm(len(el.attributes) == 1) el.setAttribute("spam", "bam") # Set this attribute to be an ID and make sure that doesn't change # when changing the value: el.setIdAttribute("spam") confirm(len(el.attributes) == 1 and el.attributes["spam"].value == "bam" and el.attributes["spam"].nodeValue == "bam" and el.getAttribute("spam") == "bam" and el.getAttributeNode("spam").isId) el.attributes["spam"] = "ham" confirm(len(el.attributes) == 1 and el.attributes["spam"].value == "ham" and el.attributes["spam"].nodeValue == "ham" and el.getAttribute("spam") == "ham" and el.attributes["spam"].isId) el.setAttribute("spam2", "bam") confirm(len(el.attributes) == 2 and el.attributes["spam"].value == "ham" and el.attributes["spam"].nodeValue == "ham" and el.getAttribute("spam") == "ham" and el.attributes["spam2"].value == "bam" and el.attributes["spam2"].nodeValue == "bam" and el.getAttribute("spam2") == "bam") el.attributes["spam2"] = "bam2" confirm(len(el.attributes) == 2 and el.attributes["spam"].value == "ham" and el.attributes["spam"].nodeValue == "ham" and el.getAttribute("spam") == "ham" and el.attributes["spam2"].value == "bam2" and el.attributes["spam2"].nodeValue == "bam2" and el.getAttribute("spam2") == "bam2") dom.unlink() def testGetAttrList(): pass def testGetAttrValues(): pass def testGetAttrLength(): pass def testGetAttribute(): pass def testGetAttributeNS(): pass def testGetAttributeNode(): pass def testGetElementsByTagNameNS(): d=""" """ dom = parseString(d) elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem") confirm(len(elems) == 1 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom" and elems[0].localName == "myelem" and elems[0].prefix == "minidom" and elems[0].tagName == "minidom:myelem" and elems[0].nodeName == "minidom:myelem") dom.unlink() def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname): nodelist = doc.getElementsByTagNameNS(nsuri, lname) confirm(len(nodelist) == 0) def testGetEmptyNodeListFromElementsByTagNameNS(): doc = parseString('') get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, 'http://xml.python.org/namespaces/a', 'localname') get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, '*', 'splat') get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, 'http://xml.python.org/namespaces/a', '*') doc = parseString('') get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, "http://xml.python.org/splat", "not-there") get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, "*", "not-there") get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, "http://somewhere.else.net/not-there", "e") def testElementReprAndStr(): dom = Document() el = dom.appendChild(dom.createElement("abc")) string1 = repr(el) string2 = str(el) confirm(string1 == string2) dom.unlink() # commented out until Fredrick's fix is checked in def _testElementReprAndStrUnicode(): dom = Document() el = dom.appendChild(dom.createElement(u"abc")) string1 = repr(el) string2 = str(el) confirm(string1 == string2) dom.unlink() # commented out until Fredrick's fix is checked in def _testElementReprAndStrUnicodeNS(): dom = Document() el = dom.appendChild( dom.createElementNS(u"http://www.slashdot.org", u"slash:abc")) string1 = repr(el) string2 = str(el) confirm(string1 == string2) confirm(string1.find("slash:abc") != -1) dom.unlink() def testAttributeRepr(): dom = Document() el = dom.appendChild(dom.createElement(u"abc")) node = el.setAttribute("abc", "def") confirm(str(node) == repr(node)) dom.unlink() def testTextNodeRepr(): pass def testWriteXML(): str = '\n' dom = parseString(str) domstr = dom.toxml() dom.unlink() confirm(str == domstr) def testProcessingInstruction(): dom = parseString('') pi = dom.documentElement.firstChild confirm(pi.target == "mypi" and pi.data == "data \t\n " and pi.nodeName == "mypi" and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE and pi.attributes is None and not pi.hasChildNodes() and len(pi.childNodes) == 0 and pi.firstChild is None and pi.lastChild is None and pi.localName is None and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE) def testProcessingInstructionRepr(): pass def testTextRepr(): pass def testWriteText(): pass def testDocumentElement(): pass def testTooManyDocumentElements(): doc = parseString("") elem = doc.createElement("extra") try: doc.appendChild(elem) except xml.dom.HierarchyRequestErr: pass else: print "Failed to catch expected exception when" \ " adding extra document element." elem.unlink() doc.unlink() def testCreateElementNS(): pass def testCreateAttributeNS(): pass def testParse(): pass def testParseString(): pass def testComment(): pass def testAttrListItem(): pass def testAttrListItems(): pass def testAttrListItemNS(): pass def testAttrListKeys(): pass def testAttrListKeysNS(): pass def testRemoveNamedItem(): doc = parseString("") e = doc.documentElement attrs = e.attributes a1 = e.getAttributeNode("a") a2 = attrs.removeNamedItem("a") confirm(a1.isSameNode(a2)) try: attrs.removeNamedItem("a") except xml.dom.NotFoundErr: pass def testRemoveNamedItemNS(): doc = parseString("") e = doc.documentElement attrs = e.attributes a1 = e.getAttributeNodeNS("http://xml.python.org/", "b") a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b") confirm(a1.isSameNode(a2)) try: attrs.removeNamedItemNS("http://xml.python.org/", "b") except xml.dom.NotFoundErr: pass def testAttrListValues(): pass def testAttrListLength(): pass def testAttrList__getitem__(): pass def testAttrList__setitem__(): pass def testSetAttrValueandNodeValue(): pass def testParseElement(): pass def testParseAttributes(): pass def testParseElementNamespaces(): pass def testParseAttributeNamespaces(): pass def testParseProcessingInstructions(): pass def testChildNodes(): pass def testFirstChild(): pass def testHasChildNodes(): pass def testCloneElementShallow(): dom, clone = _setupCloneElement(0) confirm(t_length(clone.childNodes, 0) and clone.parentNode is None and clone.toxml() == '' , "testCloneElementShallow") dom.unlink() def testCloneElementDeep(): dom, clone = _setupCloneElement(1) confirm(t_length(clone.childNodes, 1) and clone.parentNode is None and clone.toxml() == '' , "testCloneElementDeep") dom.unlink() def _setupCloneElement(deep): dom = parseString("") root = dom.documentElement clone = root.cloneNode(deep) _testCloneElementCopiesAttributes( root, clone, "testCloneElement" + (deep and "Deep" or "Shallow")) # mutilate the original so shared data is detected root.tagName = root.nodeName = "MODIFIED" root.setAttribute("attr", "NEW VALUE") root.setAttribute("added", "VALUE") return dom, clone def _testCloneElementCopiesAttributes(e1, e2, test): attrs1 = e1.attributes attrs2 = e2.attributes keys1 = attrs1.keys() keys2 = attrs2.keys() keys1.sort() keys2.sort() confirm(keys1 == keys2, "clone of element has same attribute keys") for i in range(len(keys1)): a1 = attrs1.item(i) a2 = attrs2.item(i) confirm(a1 is not a2 and a1.value == a2.value and a1.nodeValue == a2.nodeValue and a1.namespaceURI == a2.namespaceURI and a1.localName == a2.localName , "clone of attribute node has proper attribute values") confirm(a2.ownerElement is e2, "clone of attribute node correctly owned") def testCloneDocumentShallow(): doc = parseString("\n" "" "\n" "]>\n" "") doc2 = doc.cloneNode(0) confirm(doc2 is None, "testCloneDocumentShallow:" " shallow cloning of documents makes no sense!") def testCloneDocumentDeep(): doc = parseString("\n" "" "\n" "]>\n" "") doc2 = doc.cloneNode(1) confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)), "testCloneDocumentDeep: document objects not distinct") confirm(len(doc.childNodes) == len(doc2.childNodes), "testCloneDocumentDeep: wrong number of Document children") confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE, "testCloneDocumentDeep: documentElement not an ELEMENT_NODE") confirm(doc2.documentElement.ownerDocument.isSameNode(doc2), "testCloneDocumentDeep: documentElement owner is not new document") confirm(not doc.documentElement.isSameNode(doc2.documentElement), "testCloneDocumentDeep: documentElement should not be shared") if doc.doctype is not None: # check the doctype iff the original DOM maintained it confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE, "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE") confirm(doc2.doctype.ownerDocument.isSameNode(doc2)) confirm(not doc.doctype.isSameNode(doc2.doctype)) def testCloneDocumentTypeDeepOk(): doctype = create_nonempty_doctype() clone = doctype.cloneNode(1) confirm(clone is not None and clone.nodeName == doctype.nodeName and clone.name == doctype.name and clone.publicId == doctype.publicId and clone.systemId == doctype.systemId and len(clone.entities) == len(doctype.entities) and clone.entities.item(len(clone.entities)) is None and len(clone.notations) == len(doctype.notations) and clone.notations.item(len(clone.notations)) is None and len(clone.childNodes) == 0) for i in range(len(doctype.entities)): se = doctype.entities.item(i) ce = clone.entities.item(i) confirm((not se.isSameNode(ce)) and (not ce.isSameNode(se)) and ce.nodeName == se.nodeName and ce.notationName == se.notationName and ce.publicId == se.publicId and ce.systemId == se.systemId and ce.encoding == se.encoding and ce.actualEncoding == se.actualEncoding and ce.version == se.version) for i in range(len(doctype.notations)): sn = doctype.notations.item(i) cn = clone.notations.item(i) confirm((not sn.isSameNode(cn)) and (not cn.isSameNode(sn)) and cn.nodeName == sn.nodeName and cn.publicId == sn.publicId and cn.systemId == sn.systemId) def testCloneDocumentTypeDeepNotOk(): doc = create_doc_with_doctype() clone = doc.doctype.cloneNode(1) confirm(clone is None, "testCloneDocumentTypeDeepNotOk") def testCloneDocumentTypeShallowOk(): doctype = create_nonempty_doctype() clone = doctype.cloneNode(0) confirm(clone is not None and clone.nodeName == doctype.nodeName and clone.name == doctype.name and clone.publicId == doctype.publicId and clone.systemId == doctype.systemId and len(clone.entities) == 0 and clone.entities.item(0) is None and len(clone.notations) == 0 and clone.notations.item(0) is None and len(clone.childNodes) == 0) def testCloneDocumentTypeShallowNotOk(): doc = create_doc_with_doctype() clone = doc.doctype.cloneNode(0) confirm(clone is None, "testCloneDocumentTypeShallowNotOk") def check_import_document(deep, testName): doc1 = parseString("") doc2 = parseString("") try: doc1.importNode(doc2, deep) except xml.dom.NotSupportedErr: pass else: raise Exception(testName + ": expected NotSupportedErr when importing a document") def testImportDocumentShallow(): check_import_document(0, "testImportDocumentShallow") def testImportDocumentDeep(): check_import_document(1, "testImportDocumentDeep") # The tests of DocumentType importing use these helpers to construct # the documents to work with, since not all DOM builders actually # create the DocumentType nodes. def create_doc_without_doctype(doctype=None): return getDOMImplementation().createDocument(None, "doc", doctype) def create_nonempty_doctype(): doctype = getDOMImplementation().createDocumentType("doc", None, None) doctype.entities._seq = [] doctype.notations._seq = [] notation = xml.dom.minidom.Notation("my-notation", None, "http://xml.python.org/notations/my") doctype.notations._seq.append(notation) entity = xml.dom.minidom.Entity("my-entity", None, "http://xml.python.org/entities/my", "my-notation") entity.version = "1.0" entity.encoding = "utf-8" entity.actualEncoding = "us-ascii" doctype.entities._seq.append(entity) return doctype def create_doc_with_doctype(): doctype = create_nonempty_doctype() doc = create_doc_without_doctype(doctype) doctype.entities.item(0).ownerDocument = doc doctype.notations.item(0).ownerDocument = doc return doc def testImportDocumentTypeShallow(): src = create_doc_with_doctype() target = create_doc_without_doctype() try: imported = target.importNode(src.doctype, 0) except xml.dom.NotSupportedErr: pass else: raise Exception( "testImportDocumentTypeShallow: expected NotSupportedErr") def testImportDocumentTypeDeep(): src = create_doc_with_doctype() target = create_doc_without_doctype() try: imported = target.importNode(src.doctype, 1) except xml.dom.NotSupportedErr: pass else: raise Exception( "testImportDocumentTypeDeep: expected NotSupportedErr") # Testing attribute clones uses a helper, and should always be deep, # even if the argument to cloneNode is false. def check_clone_attribute(deep, testName): doc = parseString("") attr = doc.documentElement.getAttributeNode("attr") assert attr is not None clone = attr.cloneNode(deep) confirm(not clone.isSameNode(attr)) confirm(not attr.isSameNode(clone)) confirm(clone.ownerElement is None, testName + ": ownerElement should be None") confirm(clone.ownerDocument.isSameNode(attr.ownerDocument), testName + ": ownerDocument does not match") confirm(clone.specified, testName + ": cloned attribute must have specified == True") def testCloneAttributeShallow(): check_clone_attribute(0, "testCloneAttributeShallow") def testCloneAttributeDeep(): check_clone_attribute(1, "testCloneAttributeDeep") def check_clone_pi(deep, testName): doc = parseString("") pi = doc.firstChild assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE clone = pi.cloneNode(deep) confirm(clone.target == pi.target and clone.data == pi.data) def testClonePIShallow(): check_clone_pi(0, "testClonePIShallow") def testClonePIDeep(): check_clone_pi(1, "testClonePIDeep") def testNormalize(): doc = parseString("") root = doc.documentElement root.appendChild(doc.createTextNode("first")) root.appendChild(doc.createTextNode("second")) confirm(t_length(root.childNodes, 2), "testNormalize -- preparation") doc.normalize() confirm(t_length(root.childNodes, 1) and root.firstChild is root.lastChild and root.firstChild.data == "firstsecond" , "testNormalize -- result") doc.unlink() doc = parseString("") root = doc.documentElement root.appendChild(doc.createTextNode("")) doc.normalize() confirm(t_length(root.childNodes, 0), "testNormalize -- single empty node removed") doc.unlink() def testSiblings(): doc = parseString("text?") root = doc.documentElement (pi, text, elm) = root.childNodes confirm(pi.nextSibling is text and pi.previousSibling is None and text.nextSibling is elm and text.previousSibling is pi and elm.nextSibling is None and elm.previousSibling is text, "testSiblings") doc.unlink() def testParents(): doc = parseString("") root = doc.documentElement elm1 = root.childNodes[0] (elm2a, elm2b) = elm1.childNodes elm3 = elm2b.childNodes[0] confirm(root.parentNode is doc and elm1.parentNode is root and elm2a.parentNode is elm1 and elm2b.parentNode is elm1 and elm3.parentNode is elm2b, "testParents") doc.unlink() def testNodeListItem(): doc = parseString("") children = doc.childNodes docelem = children[0] confirm(t_item(children, 0, children[0]) and t_item(children, 1, None) and t_item(docelem.childNodes, 0, docelem.childNodes[0]) and t_item(docelem.childNodes, 1, docelem.childNodes[1]) and t_item(docelem.childNodes[0].childNodes, 0, None), "test NodeList.item()") doc.unlink() def testSAX2DOM(): from xml.dom import pulldom sax2dom = pulldom.SAX2DOM() sax2dom.startDocument() sax2dom.startElement("doc", {}) sax2dom.characters("text") sax2dom.startElement("subelm", {}) sax2dom.characters("text") sax2dom.endElement("subelm") sax2dom.characters("text") sax2dom.endElement("doc") sax2dom.endDocument() doc = sax2dom.document root = doc.documentElement (text1, elm1, text2) = root.childNodes text3 = elm1.childNodes[0] confirm(text1.previousSibling is None and text1.nextSibling is elm1 and elm1.previousSibling is text1 and elm1.nextSibling is text2 and text2.previousSibling is elm1 and text2.nextSibling is None and text3.previousSibling is None and text3.nextSibling is None, "testSAX2DOM - siblings") confirm(root.parentNode is doc and text1.parentNode is root and elm1.parentNode is root and text2.parentNode is root and text3.parentNode is elm1, "testSAX2DOM - parents") doc.unlink() def testEncodings(): doc = parseString('') confirm(doc.toxml() == u'\n\u20ac' and doc.toxml('utf-8') == '\n\xe2\x82\xac' and doc.toxml('iso-8859-15') == '\n\xa4', "testEncodings - encoding EURO SIGN") doc.unlink() class UserDataHandler: called = 0 def handle(self, operation, key, data, src, dst): dst.setUserData(key, data + 1, self) src.setUserData(key, None, None) self.called = 1 def testUserData(): dom = Document() n = dom.createElement('e') confirm(n.getUserData("foo") is None) n.setUserData("foo", None, None) confirm(n.getUserData("foo") is None) n.setUserData("foo", 12, 12) n.setUserData("bar", 13, 13) confirm(n.getUserData("foo") == 12) confirm(n.getUserData("bar") == 13) n.setUserData("foo", None, None) confirm(n.getUserData("foo") is None) confirm(n.getUserData("bar") == 13) handler = UserDataHandler() n.setUserData("bar", 12, handler) c = n.cloneNode(1) confirm(handler.called and n.getUserData("bar") is None and c.getUserData("bar") == 13) n.unlink() c.unlink() dom.unlink() def testRenameAttribute(): doc = parseString("") elem = doc.documentElement attrmap = elem.attributes attr = elem.attributes['a'] # Simple renaming attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b") confirm(attr.name == "b" and attr.nodeName == "b" and attr.localName is None and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE and attr.prefix is None and attr.value == "v" and elem.getAttributeNode("a") is None and elem.getAttributeNode("b").isSameNode(attr) and attrmap["b"].isSameNode(attr) and attr.ownerDocument.isSameNode(doc) and attr.ownerElement.isSameNode(elem)) # Rename to have a namespace, no prefix attr = doc.renameNode(attr, "http://xml.python.org/ns", "c") confirm(attr.name == "c" and attr.nodeName == "c" and attr.localName == "c" and attr.namespaceURI == "http://xml.python.org/ns" and attr.prefix is None and attr.value == "v" and elem.getAttributeNode("a") is None and elem.getAttributeNode("b") is None and elem.getAttributeNode("c").isSameNode(attr) and elem.getAttributeNodeNS( "http://xml.python.org/ns", "c").isSameNode(attr) and attrmap["c"].isSameNode(attr) and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr)) # Rename to have a namespace, with prefix attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d") confirm(attr.name == "p:d" and attr.nodeName == "p:d" and attr.localName == "d" and attr.namespaceURI == "http://xml.python.org/ns2" and attr.prefix == "p" and attr.value == "v" and elem.getAttributeNode("a") is None and elem.getAttributeNode("b") is None and elem.getAttributeNode("c") is None and elem.getAttributeNodeNS( "http://xml.python.org/ns", "c") is None and elem.getAttributeNode("p:d").isSameNode(attr) and elem.getAttributeNodeNS( "http://xml.python.org/ns2", "d").isSameNode(attr) and attrmap["p:d"].isSameNode(attr) and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr)) # Rename back to a simple non-NS node attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e") confirm(attr.name == "e" and attr.nodeName == "e" and attr.localName is None and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE and attr.prefix is None and attr.value == "v" and elem.getAttributeNode("a") is None and elem.getAttributeNode("b") is None and elem.getAttributeNode("c") is None and elem.getAttributeNode("p:d") is None and elem.getAttributeNodeNS( "http://xml.python.org/ns", "c") is None and elem.getAttributeNode("e").isSameNode(attr) and attrmap["e"].isSameNode(attr)) try: doc.renameNode(attr, "http://xml.python.org/ns", "xmlns") except xml.dom.NamespaceErr: pass else: print "expected NamespaceErr" checkRenameNodeSharedConstraints(doc, attr) doc.unlink() def testRenameElement(): doc = parseString("") elem = doc.documentElement # Simple renaming elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a") confirm(elem.tagName == "a" and elem.nodeName == "a" and elem.localName is None and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE and elem.prefix is None and elem.ownerDocument.isSameNode(doc)) # Rename to have a namespace, no prefix elem = doc.renameNode(elem, "http://xml.python.org/ns", "b") confirm(elem.tagName == "b" and elem.nodeName == "b" and elem.localName == "b" and elem.namespaceURI == "http://xml.python.org/ns" and elem.prefix is None and elem.ownerDocument.isSameNode(doc)) # Rename to have a namespace, with prefix elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c") confirm(elem.tagName == "p:c" and elem.nodeName == "p:c" and elem.localName == "c" and elem.namespaceURI == "http://xml.python.org/ns2" and elem.prefix == "p" and elem.ownerDocument.isSameNode(doc)) # Rename back to a simple non-NS node elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d") confirm(elem.tagName == "d" and elem.nodeName == "d" and elem.localName is None and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE and elem.prefix is None and elem.ownerDocument.isSameNode(doc)) checkRenameNodeSharedConstraints(doc, elem) doc.unlink() def checkRenameNodeSharedConstraints(doc, node): # Make sure illegal NS usage is detected: try: doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo") except xml.dom.NamespaceErr: pass else: print "expected NamespaceErr" doc2 = parseString("") try: doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo") except xml.dom.WrongDocumentErr: pass else: print "expected WrongDocumentErr" def testRenameOther(): # We have to create a comment node explicitly since not all DOM # builders used with minidom add comments to the DOM. doc = xml.dom.minidom.getDOMImplementation().createDocument( xml.dom.EMPTY_NAMESPACE, "e", None) node = doc.createComment("comment") try: doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo") except xml.dom.NotSupportedErr: pass else: print "expected NotSupportedErr when renaming comment node" doc.unlink() def checkWholeText(node, s): t = node.wholeText confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t))) def testWholeText(): doc = parseString("a") elem = doc.documentElement text = elem.childNodes[0] assert text.nodeType == Node.TEXT_NODE checkWholeText(text, "a") elem.appendChild(doc.createTextNode("b")) checkWholeText(text, "ab") elem.insertBefore(doc.createCDATASection("c"), text) checkWholeText(text, "cab") # make sure we don't cross other nodes splitter = doc.createComment("comment") elem.appendChild(splitter) text2 = doc.createTextNode("d") elem.appendChild(text2) checkWholeText(text, "cab") checkWholeText(text2, "d") x = doc.createElement("x") elem.replaceChild(x, splitter) splitter = x checkWholeText(text, "cab") checkWholeText(text2, "d") x = doc.createProcessingInstruction("y", "z") elem.replaceChild(x, splitter) splitter = x checkWholeText(text, "cab") checkWholeText(text2, "d") elem.removeChild(splitter) checkWholeText(text, "cabd") checkWholeText(text2, "cabd") def testReplaceWholeText(): def setup(): doc = parseString("ad") elem = doc.documentElement text1 = elem.firstChild text2 = elem.lastChild splitter = text1.nextSibling elem.insertBefore(doc.createTextNode("b"), splitter) elem.insertBefore(doc.createCDATASection("c"), text1) return doc, elem, text1, splitter, text2 doc, elem, text1, splitter, text2 = setup() text = text1.replaceWholeText("new content") checkWholeText(text, "new content") checkWholeText(text2, "d") confirm(len(elem.childNodes) == 3) doc, elem, text1, splitter, text2 = setup() text = text2.replaceWholeText("new content") checkWholeText(text, "new content") checkWholeText(text1, "cab") confirm(len(elem.childNodes) == 5) doc, elem, text1, splitter, text2 = setup() text = text1.replaceWholeText("") checkWholeText(text2, "d") confirm(text is None and len(elem.childNodes) == 2) def testSchemaType(): doc = parseString( "\n" " \n" " \n" "]>") elem = doc.documentElement # We don't want to rely on any specific loader at this point, so # just make sure we can get to all the names, and that the # DTD-based namespace is right. The names can vary by loader # since each supports a different level of DTD information. t = elem.schemaType confirm(t.name is None and t.namespace == xml.dom.EMPTY_NAMESPACE) names = "id notid text enum ref refs ent ents nm nms".split() for name in names: a = elem.getAttributeNode(name) t = a.schemaType confirm(hasattr(t, "name") and t.namespace == xml.dom.EMPTY_NAMESPACE) def testSetIdAttribute(): doc = parseString("") e = doc.documentElement a1 = e.getAttributeNode("a1") a2 = e.getAttributeNode("a2") confirm(doc.getElementById("v") is None and not a1.isId and not a2.isId) e.setIdAttribute("a1") confirm(e.isSameNode(doc.getElementById("v")) and a1.isId and not a2.isId) e.setIdAttribute("a2") confirm(e.isSameNode(doc.getElementById("v")) and e.isSameNode(doc.getElementById("w")) and a1.isId and a2.isId) # replace the a1 node; the new node should *not* be an ID a3 = doc.createAttribute("a1") a3.value = "v" e.setAttributeNode(a3) confirm(doc.getElementById("v") is None and e.isSameNode(doc.getElementById("w")) and not a1.isId and a2.isId and not a3.isId) # renaming an attribute should not affect it's ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) def testSetIdAttributeNS(): NS1 = "http://xml.python.org/ns1" NS2 = "http://xml.python.org/ns2" doc = parseString("") e = doc.documentElement a1 = e.getAttributeNodeNS(NS1, "a1") a2 = e.getAttributeNodeNS(NS2, "a2") confirm(doc.getElementById("v") is None and not a1.isId and not a2.isId) e.setIdAttributeNS(NS1, "a1") confirm(e.isSameNode(doc.getElementById("v")) and a1.isId and not a2.isId) e.setIdAttributeNS(NS2, "a2") confirm(e.isSameNode(doc.getElementById("v")) and e.isSameNode(doc.getElementById("w")) and a1.isId and a2.isId) # replace the a1 node; the new node should *not* be an ID a3 = doc.createAttributeNS(NS1, "a1") a3.value = "v" e.setAttributeNode(a3) confirm(e.isSameNode(doc.getElementById("w"))) confirm(not a1.isId) confirm(a2.isId) confirm(not a3.isId) confirm(doc.getElementById("v") is None) # renaming an attribute should not affect it's ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) def testSetIdAttributeNode(): NS1 = "http://xml.python.org/ns1" NS2 = "http://xml.python.org/ns2" doc = parseString("") e = doc.documentElement a1 = e.getAttributeNodeNS(NS1, "a1") a2 = e.getAttributeNodeNS(NS2, "a2") confirm(doc.getElementById("v") is None and not a1.isId and not a2.isId) e.setIdAttributeNode(a1) confirm(e.isSameNode(doc.getElementById("v")) and a1.isId and not a2.isId) e.setIdAttributeNode(a2) confirm(e.isSameNode(doc.getElementById("v")) and e.isSameNode(doc.getElementById("w")) and a1.isId and a2.isId) # replace the a1 node; the new node should *not* be an ID a3 = doc.createAttributeNS(NS1, "a1") a3.value = "v" e.setAttributeNode(a3) confirm(e.isSameNode(doc.getElementById("w"))) confirm(not a1.isId) confirm(a2.isId) confirm(not a3.isId) confirm(doc.getElementById("v") is None) # renaming an attribute should not affect it's ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) def testPickledDocument(): doc = parseString("\n" "\n" " \n" "]> text\n" " ") s = pickle.dumps(doc) doc2 = pickle.loads(s) stack = [(doc, doc2)] while stack: n1, n2 = stack.pop() confirm(n1.nodeType == n2.nodeType and len(n1.childNodes) == len(n2.childNodes) and n1.nodeName == n2.nodeName and not n1.isSameNode(n2) and not n2.isSameNode(n1)) if n1.nodeType == Node.DOCUMENT_TYPE_NODE: len(n1.entities) len(n2.entities) len(n1.notations) len(n2.notations) confirm(len(n1.entities) == len(n2.entities) and len(n1.notations) == len(n2.notations)) for i in range(len(n1.notations)): no1 = n1.notations.item(i) no2 = n1.notations.item(i) confirm(no1.name == no2.name and no1.publicId == no2.publicId and no1.systemId == no2.systemId) statck.append((no1, no2)) for i in range(len(n1.entities)): e1 = n1.entities.item(i) e2 = n2.entities.item(i) confirm(e1.notationName == e2.notationName and e1.publicId == e2.publicId and e1.systemId == e2.systemId) stack.append((e1, e2)) if n1.nodeType != Node.DOCUMENT_NODE: confirm(n1.ownerDocument.isSameNode(doc) and n2.ownerDocument.isSameNode(doc2)) for i in range(len(n1.childNodes)): stack.append((n1.childNodes[i], n2.childNodes[i])) # --- MAIN PROGRAM names = globals().keys() names.sort() failed = [] try: Node.allnodes except AttributeError: # We don't actually have the minidom from the standard library, # but are picking up the PyXML version from site-packages. def check_allnodes(): pass else: def check_allnodes(): confirm(len(Node.allnodes) == 0, "assertion: len(Node.allnodes) == 0") if len(Node.allnodes): print "Garbage left over:" if verbose: print Node.allnodes.items()[0:10] else: # Don't print specific nodes if repeatable results # are needed print len(Node.allnodes) Node.allnodes = {} for name in names: if name.startswith("test"): func = globals()[name] try: func() check_allnodes() except: failed.append(name) print "Test Failed: ", name sys.stdout.flush() traceback.print_exception(*sys.exc_info()) print `sys.exc_info()[1]` Node.allnodes = {} if failed: print "\n\n\n**** Check for failures in these tests:" for name in failed: print " " + name PyXML-0.8.2/test/test_pyexpat.py0100644000076400001440000003132007517567471016014 0ustar martinusers# Very simple test - Parse a file and print what happens # XXX TypeErrors on calling handlers, or on bad return values from a # handler, are obscure and unhelpful. try: import xml.parsers.expat except ImportError: import pyexpat from xml.parsers import expat class Outputter: def StartElementHandler(self, name, attrs): print 'Start element:\n\t', repr(name), "{", # attrs may contain characters >127, which are printed hex in Python # 2.1, but octal in earlier versions keys = attrs.keys() keys.sort() for k in keys: v = attrs[k] value = "" for c in v: if ord(c)>=256: value = "%s\\u%.4x" % (value, ord(c)) elif ord(c)>=128: value = "%s\\x%.2x" % (value, ord(c)) else: value = value + c print "%s: %s," % (repr(k),repr(value)), print "}" def EndElementHandler(self, name): print 'End element:\n\t', repr(name) def CharacterDataHandler(self, data): data = data.strip() if data: print 'Character data:' print '\t', repr(data) def ProcessingInstructionHandler(self, target, data): print 'PI:\n\t', repr(target), repr(data) def StartNamespaceDeclHandler(self, prefix, uri): print 'NS decl:\n\t', repr(prefix), repr(uri) def EndNamespaceDeclHandler(self, prefix): print 'End of NS decl:\n\t', repr(prefix) def StartCdataSectionHandler(self): print 'Start of CDATA section' def EndCdataSectionHandler(self): print 'End of CDATA section' def CommentHandler(self, text): print 'Comment:\n\t', repr(text) def NotationDeclHandler(self, *args): name, base, sysid, pubid = args print 'Notation declared:', args def UnparsedEntityDeclHandler(self, *args): entityName, base, systemId, publicId, notationName = args print 'Unparsed entity decl:\n\t', args def NotStandaloneHandler(self, userData): print 'Not standalone' return 1 def ExternalEntityRefHandler(self, *args): context, base, sysId, pubId = args print 'External entity ref:', args[1:] return 1 def SkippedEntityHandler(self, *args): print 'Skipped entity ref:', args def DefaultHandler(self, userData): pass def DefaultHandlerExpand(self, userData): pass def confirm(ok): if ok: print "OK." else: print "Not OK." out = Outputter() parser = expat.ParserCreate(namespace_separator='!') # Test getting/setting returns_unicode parser.returns_unicode = 0; confirm(parser.returns_unicode == 0) parser.returns_unicode = 1; confirm(parser.returns_unicode == 1) parser.returns_unicode = 2; confirm(parser.returns_unicode == 1) parser.returns_unicode = 0; confirm(parser.returns_unicode == 0) # Test getting/setting ordered_attributes parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0) parser.ordered_attributes = 1; confirm(parser.ordered_attributes == 1) parser.ordered_attributes = 2; confirm(parser.ordered_attributes == 1) parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0) # Test getting/setting specified_attributes parser.specified_attributes = 0; confirm(parser.specified_attributes == 0) parser.specified_attributes = 1; confirm(parser.specified_attributes == 1) parser.specified_attributes = 2; confirm(parser.specified_attributes == 1) parser.specified_attributes = 0; confirm(parser.specified_attributes == 0) HANDLER_NAMES = [ 'StartElementHandler', 'EndElementHandler', 'CharacterDataHandler', 'ProcessingInstructionHandler', 'UnparsedEntityDeclHandler', 'NotationDeclHandler', 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', 'CommentHandler', 'StartCdataSectionHandler', 'EndCdataSectionHandler', 'DefaultHandler', 'DefaultHandlerExpand', #'NotStandaloneHandler', 'ExternalEntityRefHandler', 'SkippedEntityHandler', ] for name in HANDLER_NAMES: setattr(parser, name, getattr(out, name)) data = '''\ %unparsed_entity; ]> Contents of subelements &external_entity; ''' # Produce UTF-8 output parser.returns_unicode = 0 try: parser.Parse(data, 1) except expat.error: print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode) print '** Line', parser.ErrorLineNumber print '** Column', parser.ErrorColumnNumber print '** Byte', parser.ErrorByteIndex # Try the parse again, this time producing Unicode output parser = expat.ParserCreate(namespace_separator='!') parser.returns_unicode = 1 for name in HANDLER_NAMES: setattr(parser, name, getattr(out, name)) try: parser.Parse(data, 1) except expat.error: print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode) print '** Line', parser.ErrorLineNumber print '** Column', parser.ErrorColumnNumber print '** Byte', parser.ErrorByteIndex # Try parsing a file parser = expat.ParserCreate(namespace_separator='!') parser.returns_unicode = 1 for name in HANDLER_NAMES: setattr(parser, name, getattr(out, name)) import StringIO file = StringIO.StringIO(data) try: parser.ParseFile(file) except expat.error: print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode) print '** Line', parser.ErrorLineNumber print '** Column', parser.ErrorColumnNumber print '** Byte', parser.ErrorByteIndex # Tests that make sure we get errors when the namespace_separator value # is illegal, and that we don't for good values: print print "Testing constructor for proper handling of namespace_separator values:" expat.ParserCreate() expat.ParserCreate(namespace_separator=None) expat.ParserCreate(namespace_separator=' ') print "Legal values tested o.k." try: expat.ParserCreate(namespace_separator=42) except TypeError, e: print "Caught expected TypeError." else: print "Failed to catch expected TypeError." try: expat.ParserCreate(namespace_separator='too long') except ValueError, e: print "Caught expected ValueError." else: print "Failed to catch expected ValueError." # ParserCreate() needs to accept a namespace_separator of zero length # to satisfy the requirements of RDF applications that are required # to simply glue together the namespace URI and the localname. Though # considered a wart of the RDF specifications, it needs to be supported. # # See XML-SIG mailing list thread starting with # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html # expat.ParserCreate(namespace_separator='') # too short # Test the interning machinery. p = expat.ParserCreate() L = [] def collector(name, *args): L.append(name) p.StartElementHandler = collector p.EndElementHandler = collector p.Parse(" ", 1) tag = L[0] if len(L) != 6: print "L should only contain 6 entries; found", len(L) for entry in L: if tag is not entry: print "expected L to contain many references to the same string", print "(it didn't)" print "L =", `L` break # Weird public ID bug reported by Martijn Faassen; he was only able to # tickle this under Zope with ParsedXML and PyXML 0.7 installed. text = '''\ Test ''' def start_doctype_decl_handler(doctypeName, systemId, publicId, has_internal_subset): if publicId is not None: print "Unexpect publicId: " + `publicId` if systemId != "foo": print "Unexpect systemId: " + `systemId` p = expat.ParserCreate() p.StartDoctypeDeclHandler = start_doctype_decl_handler p.Parse(text, 1) # Tests of the buffer_text attribute. import sys class TextCollector: def __init__(self, parser): self.stuff = [] def check(self, expected, label): require(self.stuff == expected, "%s\nstuff = %s\nexpected = %s" % (label, `self.stuff`, `map(unicode, expected)`)) def CharacterDataHandler(self, text): self.stuff.append(text) def StartElementHandler(self, name, attrs): self.stuff.append("<%s>" % name) bt = attrs.get("buffer-text") if bt == "yes": parser.buffer_text = 1 elif bt == "no": parser.buffer_text = 0 def EndElementHandler(self, name): self.stuff.append("" % name) def CommentHandler(self, data): self.stuff.append("" % data) def require(cond, label): # similar to confirm(), but no extraneous output if not cond: raise TestFailed(label) def setup(handlers=[]): parser = expat.ParserCreate() require(not parser.buffer_text, "buffer_text not disabled by default") parser.buffer_text = 1 handler = TextCollector(parser) parser.CharacterDataHandler = handler.CharacterDataHandler for name in handlers: setattr(parser, name, getattr(handler, name)) return parser, handler parser, handler = setup() require(parser.buffer_text, "text buffering either not acknowledged or not enabled") parser.Parse("123", 1) handler.check(["123"], "buffered text not properly collapsed") # XXX This test exposes more detail of Expat's text chunking than we # XXX like, but it tests what we need to concisely. parser, handler = setup(["StartElementHandler"]) parser.Parse("12\n34\n5", 1) handler.check(["", "1", "", "2", "\n", "3", "", "4\n5"], "buffering control not reacting as expected") parser, handler = setup() parser.Parse("1<2> \n 3", 1) handler.check(["1<2> \n 3"], "buffered text not properly collapsed") parser, handler = setup(["StartElementHandler"]) parser.Parse("123", 1) handler.check(["", "1", "", "2", "", "3"], "buffered text not properly split") parser, handler = setup(["StartElementHandler", "EndElementHandler"]) parser.CharacterDataHandler = None parser.Parse("123", 1) handler.check(["", "", "", "", "", ""], "huh?") parser, handler = setup(["StartElementHandler", "EndElementHandler"]) parser.Parse("123", 1) handler.check(["", "1", "", "", "2", "", "", "3", ""], "huh?") parser, handler = setup(["CommentHandler", "EndElementHandler", "StartElementHandler"]) parser.Parse("12345 ", 1) handler.check(["", "1", "", "", "2", "", "", "345", ""], "buffered text not properly split") parser, handler = setup(["CommentHandler", "EndElementHandler", "StartElementHandler"]) parser.Parse("12345 ", 1) handler.check(["", "1", "", "", "2", "", "", "3", "", "4", "", "5", ""], "buffered text not properly split") # Tests of namespace_triplets support. text = '''\ ''' expected_info = [ ("doc", {}), ("http://xml.python.org/x e foo", {"http://xml.python.org/x a1 foo": "a1", "http://xml.python.org/x a2 bar": "a2"}), "http://xml.python.org/x e foo", ("http://xml.python.org/x e bar", {"http://xml.python.org/x a1 foo": "a1", "http://xml.python.org/x a2 bar": "a2"}), "http://xml.python.org/x e bar", ("http://xml.python.org/e e", {"ugh:a1": "a1", "a2": "a2"}), "http://xml.python.org/e e", "doc" ] class Handler: def __init__(self, parser): self.info = [] parser.StartElementHandler = self.StartElementHandler parser.EndElementHandler = self.EndElementHandler def StartElementHandler(self, name, attrs): self.info.append((name, attrs)) def EndElementHandler(self, name): self.info.append(name) p = expat.ParserCreate(namespace_separator=" ") p.namespace_prefixes = 1 h = Handler(p) p.Parse(text, 1) if h.info != expected_info: raise ValueError, ("got bad element information:\n " + `h.info`) PyXML-0.8.2/test/test_sax.py0100644000076400001440000004550307611541422015104 0ustar martinusers# -*- coding: iso-8859-1 -*- # regression test for SAX 2.0 # $Id: test_sax.py,v 1.12 2025/10/28 18:19:26 fdrake Exp $ from xml.sax import make_parser, ContentHandler, \ SAXException, SAXReaderNotAvailable, SAXParseException try: make_parser() except SAXReaderNotAvailable: # don't try to test this module if we cannot create a parser raise ImportError("no XML parsers available") from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \ XMLFilterBase from xml.sax.expatreader import create_parser from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from cStringIO import StringIO from test.test_support import verbose, TestFailed, findfile # ===== Utilities tests = 0 failures = [] def confirm(outcome, name): global tests tests = tests + 1 if outcome: if verbose: print "Passed", name else: print "Failed", name failures.append(name) def test_make_parser2(): try: # Creating parsers several times in a row should succeed. # Testing this because there have been failures of this kind # before. from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() except: return 0 else: return p # =========================================================================== # # saxutils tests # # =========================================================================== # ===== escape def test_escape_basic(): return escape("Donald Duck & Co") == "Donald Duck & Co" def test_escape_all(): return escape("") == "<Donald Duck & Co>" def test_escape_extra(): return escape("Hei p deg", {"" : "å"}) == "Hei på deg" # ===== unescape def test_unescape_basic(): return unescape("Donald Duck & Co") == "Donald Duck & Co" def test_unescape_all(): return unescape("<Donald Duck & Co>") == "" def test_unescape_extra(): return unescape("Hei p deg", {"" : "å"}) == "Hei på deg" def test_unescape_amp_extra(): return unescape("&foo;", {"&foo;": "splat"}) == "&foo;" # ===== quoteattr def test_quoteattr_basic(): return quoteattr("Donald Duck & Co") == '"Donald Duck & Co"' def test_single_quoteattr(): return (quoteattr('Includes "double" quotes') == '\'Includes "double" quotes\'') def test_double_quoteattr(): return (quoteattr("Includes 'single' quotes") == "\"Includes 'single' quotes\"") def test_single_double_quoteattr(): return (quoteattr("Includes 'single' and \"double\" quotes") == "\"Includes 'single' and "double" quotes\"") # ===== make_parser def test_make_parser(): try: # Creating a parser should succeed - it should fall back # to the expatreader p = make_parser(['xml.parsers.no_such_parser']) except: return 0 else: return p # ===== XMLGenerator start = '\n' def test_xmlgen_basic(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "" def test_xmlgen_content(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.characters("huhei") gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "huhei" def test_xmlgen_escaped_content(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.characters(unicode("\xa0\\u3042", "unicode-escape")) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "\xa0あ" def test_xmlgen_escaped_attr(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {"x": unicode("\\u3042", "unicode-escape")}) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + '' def test_xmlgen_pi(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.processingInstruction("test", "data") gen.startElement("doc", {}) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "" def test_xmlgen_content_escape(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.characters("<huhei&" def test_xmlgen_attr_escape(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {"a": '"'}) gen.startElement("e", {"a": "'"}) gen.endElement("e") gen.startElement("e", {"a": "'\""}) gen.endElement("e") gen.endElement("doc") gen.endDocument() return result.getvalue() == start \ + "" def test_xmlgen_attr_escape_manydouble(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {"a": '"\'"'}) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "" def test_xmlgen_attr_escape_manysingle(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {"a": "'\"'"}) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + '' def test_xmlgen_ignorable(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.ignorableWhitespace(" ") gen.endElement("doc") gen.endDocument() return result.getvalue() == start + " " ns_uri = "http://www.python.org/xml-ns/saxtest/" def test_xmlgen_ns(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startPrefixMapping("ns1", ns_uri) gen.startElementNS((ns_uri, "doc"), "ns1:doc", {}) # add an unqualified name gen.startElementNS((None, "udoc"), None, {}) gen.endElementNS((None, "udoc"), None) gen.endElementNS((ns_uri, "doc"), "ns1:doc") gen.endPrefixMapping("ns1") gen.endDocument() return result.getvalue() == start + \ ('' % ns_uri) # ===== XMLFilterBase def test_filter_basic(): result = StringIO() gen = XMLGenerator(result) filter = XMLFilterBase() filter.setContentHandler(gen) filter.startDocument() filter.startElement("doc", {}) filter.characters("content") filter.ignorableWhitespace(" ") filter.endElement("doc") filter.endDocument() return result.getvalue() == start + "content " # =========================================================================== # # expatreader tests # # =========================================================================== # ===== XMLReader support def test_expat_file(): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(open(findfile("test.xml"))) return result.getvalue() == xml_test_out # ===== DTDHandler support class TestDTDHandler: def __init__(self): self._notations = [] self._entities = [] def notationDecl(self, name, publicId, systemId): self._notations.append((name, publicId, systemId)) def unparsedEntityDecl(self, name, publicId, systemId, ndata): self._entities.append((name, publicId, systemId, ndata)) def test_expat_dtdhandler(): parser = create_parser() handler = TestDTDHandler() parser.setDTDHandler(handler) parser.feed('\n') parser.feed(' \n') parser.feed(']>\n') parser.feed('') parser.close() return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \ handler._entities == [("img", None, "expat.gif", "GIF")] # ===== EntityResolver support class TestEntityResolver: def resolveEntity(self, publicId, systemId): inpsrc = InputSource() inpsrc.setByteStream(StringIO("")) return inpsrc def test_expat_entityresolver(): parser = create_parser() parser.setEntityResolver(TestEntityResolver()) result = StringIO() parser.setContentHandler(XMLGenerator(result)) parser.feed('\n') parser.feed(']>\n') parser.feed('&test;') parser.close() return result.getvalue() == start + "" # ===== Attributes support class AttrGatherer(ContentHandler): def startElement(self, name, attrs): self._attrs = attrs def startElementNS(self, name, qname, attrs): self._attrs = attrs def test_expat_attrs_empty(): parser = create_parser() gather = AttrGatherer() parser.setContentHandler(gather) parser.feed("") parser.close() return verify_empty_attrs(gather._attrs) def test_expat_attrs_wattr(): parser = create_parser() gather = AttrGatherer() parser.setContentHandler(gather) parser.feed("") parser.close() return verify_attrs_wattr(gather._attrs) def test_expat_nsattrs_empty(): parser = create_parser(1) gather = AttrGatherer() parser.setContentHandler(gather) parser.feed("") parser.close() return verify_empty_nsattrs(gather._attrs) def test_expat_nsattrs_wattr(): parser = create_parser(1) gather = AttrGatherer() parser.setContentHandler(gather) parser.feed("" % ns_uri) parser.close() attrs = gather._attrs return attrs.getLength() == 1 and \ attrs.getNames() == [(ns_uri, "attr")] and \ attrs.getQNames() == ["ns:attr"] and \ len(attrs) == 1 and \ attrs.has_key((ns_uri, "attr")) and \ attrs.keys() == [(ns_uri, "attr")] and \ attrs.get((ns_uri, "attr")) == "val" and \ attrs.get((ns_uri, "attr"), 25) == "val" and \ attrs.items() == [((ns_uri, "attr"), "val")] and \ attrs.values() == ["val"] and \ attrs.getValue((ns_uri, "attr")) == "val" and \ attrs[(ns_uri, "attr")] == "val" # ===== InputSource support xml_test_out = open(findfile("test.xml.out")).read() def test_expat_inpsource_filename(): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(findfile("test.xml")) return result.getvalue() == xml_test_out def test_expat_inpsource_sysid(): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(InputSource(findfile("test.xml"))) return result.getvalue() == xml_test_out def test_expat_inpsource_stream(): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) inpsrc = InputSource() inpsrc.setByteStream(open(findfile("test.xml"))) parser.parse(inpsrc) return result.getvalue() == xml_test_out # ===== IncrementalParser support def test_expat_incremental(): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) parser.feed("") parser.feed("") parser.close() return result.getvalue() == start + "" def test_expat_incremental_reset(): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) parser.feed("") parser.feed("text") result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.reset() parser.feed("") parser.feed("text") parser.feed("") parser.close() return result.getvalue() == start + "text" # ===== Locator support def test_expat_locator_noinfo(): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) parser.feed("") parser.feed("") parser.close() return parser.getSystemId() is None and \ parser.getPublicId() is None and \ parser.getLineNumber() == 1 def test_expat_locator_withinfo(): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) parser.parse(findfile("test.xml")) return parser.getSystemId() == findfile("test.xml") and \ parser.getPublicId() is None # =========================================================================== # # error reporting # # =========================================================================== def test_expat_inpsource_location(): parser = create_parser() parser.setContentHandler(ContentHandler()) # do nothing source = InputSource() source.setByteStream(StringIO("")) #ill-formed name = "a file name" source.setSystemId(name) try: parser.parse(source) except SAXException, e: return e.getSystemId() == name def test_expat_incomplete(): parser = create_parser() parser.setContentHandler(ContentHandler()) # do nothing try: parser.parse(StringIO("")) except SAXParseException: return 1 # ok, error found else: return 0 # =========================================================================== # # xmlreader tests # # =========================================================================== # ===== AttributesImpl def verify_empty_attrs(attrs): try: attrs.getValue("attr") gvk = 0 except KeyError: gvk = 1 try: attrs.getValueByQName("attr") gvqk = 0 except KeyError: gvqk = 1 try: attrs.getNameByQName("attr") gnqk = 0 except KeyError: gnqk = 1 try: attrs.getQNameByName("attr") gqnk = 0 except KeyError: gqnk = 1 try: attrs["attr"] gik = 0 except KeyError: gik = 1 return attrs.getLength() == 0 and \ attrs.getNames() == [] and \ attrs.getQNames() == [] and \ len(attrs) == 0 and \ not attrs.has_key("attr") and \ attrs.keys() == [] and \ attrs.get("attrs") is None and \ attrs.get("attrs", 25) == 25 and \ attrs.items() == [] and \ attrs.values() == [] and \ gvk and gvqk and gnqk and gik and gqnk def verify_attrs_wattr(attrs): return attrs.getLength() == 1 and \ attrs.getNames() == ["attr"] and \ attrs.getQNames() == ["attr"] and \ len(attrs) == 1 and \ attrs.has_key("attr") and \ attrs.keys() == ["attr"] and \ attrs.get("attr") == "val" and \ attrs.get("attr", 25) == "val" and \ attrs.items() == [("attr", "val")] and \ attrs.values() == ["val"] and \ attrs.getValue("attr") == "val" and \ attrs.getValueByQName("attr") == "val" and \ attrs.getNameByQName("attr") == "attr" and \ attrs["attr"] == "val" and \ attrs.getQNameByName("attr") == "attr" def test_attrs_empty(): return verify_empty_attrs(AttributesImpl({})) def test_attrs_wattr(): return verify_attrs_wattr(AttributesImpl({"attr" : "val"})) # ===== AttributesImpl def verify_empty_nsattrs(attrs): try: attrs.getValue((ns_uri, "attr")) gvk = 0 except KeyError: gvk = 1 try: attrs.getValueByQName("ns:attr") gvqk = 0 except KeyError: gvqk = 1 try: attrs.getNameByQName("ns:attr") gnqk = 0 except KeyError: gnqk = 1 try: attrs.getQNameByName((ns_uri, "attr")) gqnk = 0 except KeyError: gqnk = 1 try: attrs[(ns_uri, "attr")] gik = 0 except KeyError: gik = 1 return attrs.getLength() == 0 and \ attrs.getNames() == [] and \ attrs.getQNames() == [] and \ len(attrs) == 0 and \ not attrs.has_key((ns_uri, "attr")) and \ attrs.keys() == [] and \ attrs.get((ns_uri, "attr")) is None and \ attrs.get((ns_uri, "attr"), 25) == 25 and \ attrs.items() == [] and \ attrs.values() == [] and \ gvk and gvqk and gnqk and gik and gqnk def test_nsattrs_empty(): return verify_empty_nsattrs(AttributesNSImpl({}, {})) def test_nsattrs_wattr(): attrs = AttributesNSImpl({(ns_uri, "attr") : "val"}, {(ns_uri, "attr") : "ns:attr"}) return attrs.getLength() == 1 and \ attrs.getNames() == [(ns_uri, "attr")] and \ attrs.getQNames() == ["ns:attr"] and \ len(attrs) == 1 and \ attrs.has_key((ns_uri, "attr")) and \ attrs.keys() == [(ns_uri, "attr")] and \ attrs.get((ns_uri, "attr")) == "val" and \ attrs.get((ns_uri, "attr"), 25) == "val" and \ attrs.items() == [((ns_uri, "attr"), "val")] and \ attrs.values() == ["val"] and \ attrs.getValue((ns_uri, "attr")) == "val" and \ attrs.getValueByQName("ns:attr") == "val" and \ attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \ attrs[(ns_uri, "attr")] == "val" and \ attrs.getQNameByName((ns_uri, "attr")) == "ns:attr" # ===== Main program def make_test_output(): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(findfile("test.xml")) outf = open(findfile("test.xml.out"), "w") outf.write(result.getvalue()) outf.close() items = locals().items() items.sort() for (name, value) in items: if name[ : 5] == "test_": confirm(value(), name) if verbose: print "%d tests, %d failures" % (tests, len(failures)) if failures: raise TestFailed("%d of %d tests failed: %s" % (len(failures), tests, ", ".join(failures))) PyXML-0.8.2/test/test_sax2.py0100644000076400001440000004555707537736435015220 0ustar martinusers# -*- coding: iso-8859-1 -*- # regression test for SAX 2.0 # $Id: test_sax2.py,v 1.5 2025/09/10 21:37:29 fdrake Exp $ from xml.sax import handler, make_parser, ContentHandler, \ SAXException, SAXReaderNotAvailable, SAXParseException try: make_parser() except SAXReaderNotAvailable: # don't try to test this module if we cannot create a parser raise ImportError("no XML parsers available") from xml.sax.saxutils import XMLGenerator, escape, quoteattr, XMLFilterBase, Location from xml.sax import expatreader from xml.sax.sax2exts import make_parser from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from cStringIO import StringIO from test.test_support import verbose, TestFailed, findfile import types # ===== Utilities tests = 0 fails = 0 def confirm(outcome, name): global tests, fails tests = tests + 1 if not outcome: print "Failed " + name fails = fails + 1 def test_make_parser2(): try: # Creating parsers several times in a row should succeed. # Testing this because there have been failures of this kind # before. from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() from xml.sax import make_parser p = make_parser() except: return 0 else: return p # =========================================================================== # # saxutils tests # # =========================================================================== # ===== escape def test_escape_basic(): return escape("Donald Duck & Co") == "Donald Duck & Co" def test_escape_all(): return escape("") == "<Donald Duck & Co>" def test_escape_extra(): return escape("Hei p deg", {"" : "å"}) == "Hei på deg" # ===== quoteattr def test_quoteattr_basic(): return quoteattr("Donald Duck & Co") == '"Donald Duck & Co"' def test_single_quoteattr(): return (quoteattr('Includes "double" quotes') == '\'Includes "double" quotes\'') def test_double_quoteattr(): return (quoteattr("Includes 'single' quotes") == "\"Includes 'single' quotes\"") def test_single_double_quoteattr(): return (quoteattr("Includes 'single' and \"double\" quotes") == "\"Includes 'single' and "double" quotes\"") # ===== make_parser def test_make_parser(): try: # Creating a parser should succeed - it should fall back # to the expatreader p = make_parser(['xml.parsers.no_such_parser']) except: return 0 else: return p # ===== XMLGenerator start = '\n' def test_xmlgen_basic(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "" def test_xmlgen_content(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.characters("huhei") gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "huhei" def test_xmlgen_pi(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.processingInstruction("test", "data") gen.startElement("doc", {}) gen.endElement("doc") gen.endDocument() return result.getvalue() == start + "" def test_xmlgen_content_escape(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.characters("<huhei&" def test_xmlgen_attr_escape(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {"a": '"'}) gen.startElement("e", {"a": "'"}) gen.endElement("e") gen.startElement("e", {"a": "'\""}) gen.endElement("e") gen.endElement("doc") gen.endDocument() return result.getvalue() == start \ + "" def test_xmlgen_ignorable(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startElement("doc", {}) gen.ignorableWhitespace(" ") gen.endElement("doc") gen.endDocument() return result.getvalue() == start + " " ns_uri = "http://www.python.org/xml-ns/saxtest/" def test_xmlgen_ns(): result = StringIO() gen = XMLGenerator(result) gen.startDocument() gen.startPrefixMapping("ns1", ns_uri) gen.startElementNS((ns_uri, "doc"), "ns1:doc", {}) # add an unqualified name gen.startElementNS((None, "udoc"), None, {}) gen.endElementNS((None, "udoc"), None) gen.endElementNS((ns_uri, "doc"), "ns1:doc") gen.endPrefixMapping("ns1") gen.endDocument() return result.getvalue() == start + \ ('' % ns_uri) # ===== XMLFilterBase def test_filter_basic(): result = StringIO() gen = XMLGenerator(result) filter = XMLFilterBase() filter.setContentHandler(gen) filter.startDocument() filter.startElement("doc", {}) filter.characters("content") filter.ignorableWhitespace(" ") filter.endElement("doc") filter.endDocument() return result.getvalue() == start + "content " # =========================================================================== # # expatreader tests # # =========================================================================== # ===== XMLReader support def test_expat_file(): parser = make_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(open(findfile("test.xml"))) #print result.getvalue() , xml_test_out f = open(findfile("test.xml.result"), 'wt') f.write(result.getvalue()) f.close() return result.getvalue() == xml_test_out # ===== DTDHandler support class TestDTDHandler: def __init__(self): self._notations = [] self._entities = [] def notationDecl(self, name, publicId, systemId): self._notations.append((name, publicId, systemId)) def unparsedEntityDecl(self, name, publicId, systemId, ndata): self._entities.append((name, publicId, systemId, ndata)) class LexicalHandler: _start_dtd = None _end_dtd = None def startDTD(self, *args): self._start_dtd = args def endDTD(self, *args): self._end_dtd = args def comment(self, text): pass def startCDATA(self): pass def endCDATA(self): pass def test_expat_dtdhandler(): parser = make_parser() dtdhandler = TestDTDHandler() lexhandler = LexicalHandler() parser.setDTDHandler(dtdhandler) parser.setProperty(handler.property_lexical_handler, lexhandler) parser.parse(StringIO(''' ]> ''')) if hasattr(types, 'UnicodeType'): def makestr(uni): if uni is None: return uni return str(uni) dtdhandler._notations = [tuple(map(makestr, dtdhandler._notations[0]))] dtdhandler._entities = [tuple(map(makestr, dtdhandler._entities[0]))] return dtdhandler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \ dtdhandler._entities == [("img", None, "expat.gif", "GIF")] and \ lexhandler._start_dtd == ("doc", None, None) and \ lexhandler._end_dtd == () # ===== EntityResolver support class TestEntityResolver: def resolveEntity(self, publicId, systemId): inpsrc = InputSource() inpsrc.setByteStream(StringIO("")) return inpsrc def test_expat_entityresolver(): parser = make_parser() parser.setEntityResolver(TestEntityResolver()) result = StringIO() parser.setContentHandler(XMLGenerator(result)) parser.parse(StringIO(''' ]> &test;''')) return result.getvalue() == start + "" # ===== Attributes support class AttrGatherer(ContentHandler): def startElement(self, name, attrs): self._attrs = attrs def startElementNS(self, name, qname, attrs): self._attrs = attrs def test_expat_attrs_empty(): parser = make_parser() gather = AttrGatherer() parser.setContentHandler(gather) parser.parse(StringIO("")) return verify_empty_attrs(gather._attrs) def test_expat_nsattrs_qnames(): parser = make_parser() parser.setFeature(handler.feature_namespaces, 1) assert parser._namespaces testhandler = AttrGatherer() parser.setContentHandler(testhandler) ns_uri = 'http://relaxng.org/ns/structure/1.0' stream = StringIO("" % ns_uri) parser.parse(stream) attrs = testhandler._attrs return attrs.getQNames() == ["foo"] and \ attrs.has_key((None, "foo")) def test_expat_attrs_wattr(): parser = make_parser() parser.setFeature(handler.feature_namespaces, 0) gather = AttrGatherer() parser.setContentHandler(gather) parser.parse(StringIO("")) return verify_attrs_wattr(gather._attrs) def test_expat_nsattrs_empty(): parser = make_parser() parser.setFeature(handler.feature_namespaces, 1) gather = AttrGatherer() parser.setContentHandler(gather) parser.parse(StringIO("")) return verify_empty_nsattrs(gather._attrs) def test_expat_nsattrs_wattr(): parser = make_parser() parser.setFeature(handler.feature_namespaces, 1) gather = AttrGatherer() parser.setContentHandler(gather) parser.parse(StringIO("" % ns_uri)) attrs = gather._attrs return attrs.getLength() == 1 and \ attrs.getNames() == [(ns_uri, "attr")] and \ attrs.getQNames() == ['ns:attr'] and \ len(attrs) == 1 and \ attrs.has_key((ns_uri, "attr")) and \ attrs.keys() == [(ns_uri, "attr")] and \ attrs.get((ns_uri, "attr")) == "val" and \ attrs.get((ns_uri, "attr"), 25) == "val" and \ attrs.items() == [((ns_uri, "attr"), "val")] and \ attrs.values() == ["val"] and \ attrs.getValue((ns_uri, "attr")) == "val" and \ attrs[(ns_uri, "attr")] == "val" # ===== InputSource support xml_test_out = open(findfile("test.xml.out")).read() def test_expat_inpsource_filename(): parser = make_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(findfile("test.xml")) return result.getvalue() == xml_test_out def test_expat_inpsource_sysid(): parser = make_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(InputSource(findfile("test.xml"))) return result.getvalue() == xml_test_out def test_expat_inpsource_stream(): parser = make_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) inpsrc = InputSource() inpsrc.setByteStream(open(findfile("test.xml"))) parser.parse(inpsrc) return result.getvalue() == xml_test_out # ===== IncrementalParser support def test_expat_incremental(): result = StringIO() xmlgen = XMLGenerator(result) parser = expatreader.create_parser() parser.setContentHandler(xmlgen) parser.feed("") parser.feed("") parser.close() return result.getvalue() == start + "" def test_expat_incremental_reset(): result = StringIO() xmlgen = XMLGenerator(result) parser = expatreader.create_parser() parser.setContentHandler(xmlgen) parser.feed("") parser.feed("text") result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.reset() parser.feed("") parser.feed("text") parser.feed("") parser.close() return result.getvalue() == start + "text" # ===== Locator support class LocatorTest(XMLGenerator): def __init__(self, out=None, encoding="iso-8859-1"): XMLGenerator.__init__(self, out, encoding) self.location = None def endDocument(self): XMLGenerator.endDocument(self) self.location = Location(self._locator) def test_expat_locator_noinfo(): result = StringIO() xmlgen = LocatorTest(result) parser = make_parser() parser.setContentHandler(xmlgen) parser.parse(StringIO("")) return xmlgen.location.getSystemId() is None and \ xmlgen.location.getPublicId() is None and \ xmlgen.location.getLineNumber() == 1 def test_expat_locator_withinfo(): result = StringIO() xmlgen = LocatorTest(result) parser = make_parser() parser.setContentHandler(xmlgen) parser.parse(findfile("test.xml")) return xmlgen.location.getSystemId() == findfile("test.xml") and \ xmlgen.location.getPublicId() is None # =========================================================================== # # error reporting # # =========================================================================== def test_expat_inpsource_location(): parser = make_parser() parser.setContentHandler(ContentHandler()) # do nothing source = InputSource() source.setByteStream(StringIO("")) #ill-formed name = "a file name" source.setSystemId(name) try: parser.parse(source) except SAXException, e: return e.getSystemId() == name def test_expat_incomplete(): parser = make_parser() parser.setContentHandler(ContentHandler()) # do nothing try: parser.parse(StringIO("")) except SAXParseException: return 1 # ok, error found else: return 0 # =========================================================================== # # xmlreader tests # # =========================================================================== # ===== AttributesImpl def verify_empty_attrs(attrs): try: attrs.getValue("attr") gvk = 0 except KeyError: gvk = 1 try: attrs.getValueByQName("attr") gvqk = 0 except KeyError: gvqk = 1 try: attrs.getNameByQName("attr") gnqk = 0 except KeyError: gnqk = 1 try: attrs.getQNameByName("attr") gqnk = 0 except KeyError: gqnk = 1 try: attrs["attr"] gik = 0 except KeyError: gik = 1 return attrs.getLength() == 0 and \ attrs.getNames() == [] and \ attrs.getQNames() == [] and \ len(attrs) == 0 and \ not attrs.has_key("attr") and \ attrs.keys() == [] and \ attrs.get("attrs") is None and \ attrs.get("attrs", 25) == 25 and \ attrs.items() == [] and \ attrs.values() == [] and \ gvk and gvqk and gnqk and gik and gqnk def verify_attrs_wattr(attrs): return attrs.getLength() == 1 and \ attrs.getNames() == ["attr"] and \ attrs.getQNames() == ["attr"] and \ len(attrs) == 1 and \ attrs.has_key("attr") and \ attrs.keys() == ["attr"] and \ attrs.get("attr") == "val" and \ attrs.get("attr", 25) == "val" and \ attrs.items() == [("attr", "val")] and \ attrs.values() == ["val"] and \ attrs.getValue("attr") == "val" and \ attrs.getValueByQName("attr") == "val" and \ attrs.getNameByQName("attr") == "attr" and \ attrs["attr"] == "val" and \ attrs.getQNameByName("attr") == "attr" def test_attrs_empty(): return verify_empty_attrs(AttributesImpl({})) def test_attrs_wattr(): return verify_attrs_wattr(AttributesImpl({"attr" : "val"})) # ===== AttributesImpl def verify_empty_nsattrs(attrs): try: attrs.getValue((ns_uri, "attr")) gvk = 0 except KeyError: gvk = 1 try: attrs.getValueByQName("ns:attr") gvqk = 0 except KeyError: gvqk = 1 try: attrs.getNameByQName("ns:attr") gnqk = 0 except KeyError: gnqk = 1 try: attrs.getQNameByName((ns_uri, "attr")) gqnk = 0 except KeyError: gqnk = 1 try: attrs[(ns_uri, "attr")] gik = 0 except KeyError: gik = 1 return attrs.getLength() == 0 and \ attrs.getNames() == [] and \ attrs.getQNames() == [] and \ len(attrs) == 0 and \ not attrs.has_key((ns_uri, "attr")) and \ attrs.keys() == [] and \ attrs.get((ns_uri, "attr")) is None and \ attrs.get((ns_uri, "attr"), 25) == 25 and \ attrs.items() == [] and \ attrs.values() == [] and \ gvk and gvqk and gnqk and gik and gqnk def test_nsattrs_empty(): return verify_empty_nsattrs(AttributesNSImpl({}, {})) def test_nsattrs_wattr(): attrs = AttributesNSImpl({(ns_uri, "attr") : "val"}, {(ns_uri, "attr") : "ns:attr"}) return attrs.getLength() == 1 and \ attrs.getNames() == [(ns_uri, "attr")] and \ attrs.getQNames() == ["ns:attr"] and \ len(attrs) == 1 and \ attrs.has_key((ns_uri, "attr")) and \ attrs.keys() == [(ns_uri, "attr")] and \ attrs.get((ns_uri, "attr")) == "val" and \ attrs.get((ns_uri, "attr"), 25) == "val" and \ attrs.items() == [((ns_uri, "attr"), "val")] and \ attrs.values() == ["val"] and \ attrs.getValue((ns_uri, "attr")) == "val" and \ attrs.getValueByQName("ns:attr") == "val" and \ attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \ attrs[(ns_uri, "attr")] == "val" and \ attrs.getQNameByName((ns_uri, "attr")) == "ns:attr" # ===== Main program def make_test_output(): parser = make_parser() result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.parse(findfile("test.xml")) outf = open(findfile("test.xml.out"), "w") outf.write(result.getvalue()) outf.close() if __name__ == "__main__": # print parser name if called directly ##print "Testing", make_parser() pass items = locals().items() items.sort() for (name, value) in items: if name[ : 5] == "test_": confirm(value(), name) if fails != 0: raise TestFailed, "%d of %d tests failed" % (fails, tests) PyXML-0.8.2/test/test_sax2_xmlproc.py0100644000076400001440000000243607413603011016721 0ustar martinusersimport unittest from cStringIO import StringIO import xml.sax from xml.sax import handler from xml.sax import xmlreader # constants & helpers _drv_xmlproc = "xml.sax.drivers2.drv_xmlproc" _xmls_nons = "data" _xmls_blankns = "data" class _MyHandler(handler.ContentHandler): def __init__(self,testCase): self.__testCase = testCase def startElementNS(self,name,qname,atts): # XXX: is this right ? At least pyexpat and xmlproc do it this way. self.__testCase.failIf(name[0] != None) # XXX: or should it be this one ? #self.__testCase.failIf(name[0] != '') def _makeParser(driver,ns): reader = xml.sax.make_parser([driver]) reader.setFeature(handler.feature_namespaces,ns) return reader def _saxParse(testCase,driver,ns,h,xmls): reader = _makeParser(driver,ns) reader.setContentHandler(h) inps = xmlreader.InputSource() inps.setByteStream(StringIO(xmls)) reader.parse(inps) # test cases class MyTest(unittest.TestCase): def test_sax_xmlproc_nson__nons(self): _saxParse(self,_drv_xmlproc,1,_MyHandler(self),_xmls_nons) def test_sax_xmlproc_nson__blankns(self): _saxParse(self,_drv_xmlproc,1,_MyHandler(self),_xmls_blankns) if __name__ == "__main__": unittest.main() PyXML-0.8.2/test/test_sax_xmlproc.py0100644000076400001440000000510507250536551016650 0ustar martinusersfrom test.test_support import verbose, TestFailed, findfile from xml.sax.sax2exts import XMLValParserFactory from xml.sax import InputSource, SAXException, ContentHandler from StringIO import StringIO import sys #make_parser, ContentHandler, \ # SAXException, SAXReaderNotAvailable, SAXParseException # try: # make_parser() # except SAXReaderNotAvailable: # # don't try to test this module if we cannot create a parser # raise ImportError("no XML parsers available") # from xml.sax.saxutils import XMLGenerator, escape, XMLFilterBase # from xml.sax.expatreader import create_parser # from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl # from cStringIO import StringIO # ===== Utilities tests = 0 fails = 0 def confirm(outcome, name): global tests, fails tests = tests + 1 if outcome: print "Passed", name else: print "Failed", name fails = fails + 1 def gen_inputs(): f = open("xmlval_illformed.dtd","w") f.write("""\n""") if __name__=='__main__' and len(sys.argv)>1 and sys.argv[1] == 'generate': gen_inputs() raise SystemExit doc1 = """ """ def test_nonexistent(): p = XMLValParserFactory.make_parser() i = InputSource("doc1.xml") i.setByteStream(StringIO(doc1)) try: p.parse(i) except SAXException,e: print "PASS:",e return 1 else: return 0 doc2 = """ <""" def test_illformed(): p = XMLValParserFactory.make_parser() i = InputSource("doc2.xml") i.setByteStream(StringIO(doc2)) try: p.parse(i) except SAXException,e: print "PASS:",e return 1 else: return 0 doc3 = """ ]> """ class H(ContentHandler): def __init__(self): self.passed = 0 def ignorableWhitespace(self, data): self.passed = 1 def test_ignorable(): p = XMLValParserFactory.make_parser() i = InputSource("doc3.xml") i.setByteStream(StringIO(doc3)) h = H() p.setContentHandler(h) p.parse(i) return h.passed items = locals().items() items.sort() for (name, value) in items: if name[ : 5] == "test_": confirm(value(), name) print "%d tests, %d failures" % (tests, fails) if fails != 0: raise TestFailed, "%d of %d tests failed" % (fails, tests) PyXML-0.8.2/test/test_saxdrivers.py0100644000076400001440000000732607517567471016525 0ustar martinusers# regression test for SAX drivers # $Id: test_saxdrivers.py,v 1.6 2025/07/01 18:42:04 fdrake Exp $ from xml.sax.saxutils import XMLGenerator, ContentGenerator from xml.sax import handler, SAXReaderNotAvailable import xml.sax.saxexts import xml.sax.sax2exts from cStringIO import StringIO from test.test_support import verbose, TestFailed, findfile try: import warnings except ImportError: pass else: warnings.filterwarnings("ignore", ".* xmllib .* obsolete.*", DeprecationWarning, 'xmllib$') tests=0 fails=0 xml_test = open(findfile("test.xml.out")).read() xml_test_out = open(findfile("test.xml.out")).read() expected_failures=[ "xml.sax.drivers.drv_sgmlop", # does not handle " entity reference "xml.sax.drivers.drv_xmllib", # reports S before first tag, # does not report xmlns: attribute ] def summarize(p,result): global tests,fails tests=tests+1 if result == xml_test_out: if p in expected_failures: print p,"XPASS" else: print p,"PASS" elif p in expected_failures: print p,"XFAIL" else: print p,"FAIL" fails=fails+1 if verbose: print result #open("test.xml."+p,"w").write(result.getvalue()) def test_sax1(): factory=xml.sax.saxexts.XMLParserFactory for p in factory.get_parser_list(): try: parser = factory._create_parser(p) except ImportError: print p,"NOT SUPPORTED" continue except SAXReaderNotAvailable: print p,"NOT SUPPORTED" continue result = StringIO() xmlgen = ContentGenerator(result) parser.setDocumentHandler(xmlgen) # We should not pass file names to parse; we don't have # any URLs, either parser.parseFile(open(findfile("test.xml"))) summarize(p,result.getvalue()) def test_sax2(): factory = xml.sax.sax2exts.XMLParserFactory for p in factory.get_parser_list(): try: parser = factory._create_parser(p) except ImportError: print p,"NOT SUPPORTED" continue except SAXReaderNotAvailable: print p,"NOT SUPPORTED" continue # Don't try to test namespace support, yet parser.setFeature(handler.feature_namespaces,0) result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) # In SAX2, we can pass an open file object to parse() parser.parse(open(findfile("test.xml"))) summarize(p,result.getvalue()) def test_incremental(): global tests, fails factory = xml.sax.sax2exts.XMLParserFactory for p in factory.get_parser_list(): try: parser = factory._create_parser(p) except ImportError: print p,"NOT SUPPORTED" continue except SAXReaderNotAvailable: print p,"NOT SUPPORTED" continue if not hasattr(parser, "feed"): continue # Don't try to test namespace support, yet result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.feed("") parser.feed("") parser.close() tests = tests + 1 if result.getvalue() == '\n': print p, "PASS" else: print p, "FAIL" fails = fails + 1 items = locals().items() items.sort() for (name, value) in items: if name[ : 5] == "test_": value() print "%d tests, %d failures" % (tests, fails) if fails != 0: raise TestFailed, "%d of %d tests failed" % (fails, tests) PyXML-0.8.2/test/test_support.py0100644000076400001440000000321107537435047016027 0ustar martinusers"""PyUNIT-based compatibility module for the test.test_support module. When running PyUNIT-based tests, this should be used for the run_suite() and run_unittest() functions. """ from test.test_support import verbose, TestFailed try: from test.test_support import run_suite, run_unittest except ImportError: #======================================================================= # Preliminary PyUNIT integration. import sys import unittest class BasicTestRunner: def run(self, test): result = unittest.TestResult() test(result) return result def run_suite(suite, testclass=None): """Run tests from a unittest.TestSuite-derived class.""" if verbose: runner = unittest.TextTestRunner(sys.stdout, verbosity=2) else: runner = BasicTestRunner() result = runner.run(suite) if not result.wasSuccessful(): if len(result.errors) == 1 and not result.failures: err = result.errors[0][1] elif len(result.failures) == 1 and not result.errors: err = result.failures[0][1] else: if testclass is None: msg = "errors occurred; run in verbose mode for details" else: msg = "errors occurred in %s.%s" \ % (testclass.__module__, testclass.__name__) raise TestFailed(msg) raise TestFailed(err) def run_unittest(testclass): """Run tests from a unittest.TestCase-derived class.""" run_suite(unittest.makeSuite(testclass), testclass) PyXML-0.8.2/test/test_utils.py0100644000076400001440000000165507463735541015465 0ustar martinusers# Test the modules in the utils/ subpackage # FIXME: escape is now in xml.sax.saxutils, need to move testcase as well from xml.utils import * from xml.sax.saxutils import escape print 'Testing utils.escape' print 'These pairs of strings should all be identical' v1, v2 = escape('&<>'), '&<>' print int(v1 == v2), repr(v1), repr(v2) v1, v2 = escape('foo&bar'), 'foo&bar' print int(v1 == v2), repr(v1), repr(v2) v1, v2 = escape('< test > &', {'test': '&myentity;'}), '< &myentity; > &' print int(v1 == v2), repr(v1), repr(v2) v1, v2 = escape('&\'"<>', {'"': '"', "'": '''}), '&'"<>' print int(v1 == v2), repr(v1), repr(v2) # Test the iso8601 module for dt in ['1998', '1998-06', '2025-06-13', '1998-06-13T14:12Z', '1998-06-13T14:12:30Z', '1998-06-13T14:12:30.2Z' ]: date = iso8601.parse( dt ) print iso8601.tostring( date ) PyXML-0.8.2/test/test_xmlbuilder.py0100644000076400001440000003173007611541422016455 0ustar martinusers"""Tests of the extended features of xml.dom.expatbuilder.""" import os import pprint import unittest from cStringIO import StringIO from xml.dom import XMLNS_NAMESPACE from xml.dom import xmlbuilder INTERNAL_SUBSET = ("\n" "") DOCUMENT_SOURCE = ( ' ''') class Tests(unittest.TestCase): def setUp(self): self.builder = xmlbuilder.DOMBuilder() def makeSource(self, text): source = xmlbuilder.DOMInputSource() source.byteStream = StringIO(text) return source def check_attrs(self, atts, expected): self.assertEqual(atts.length, len(expected)) info = atts.itemsNS() info.sort() if info != expected: self.fail("bad attribute information:\n" + pprint.pformat(info)) def run_checks(self, attributes): document = self.builder.parse(self.makeSource(DOCUMENT_SOURCE)) self.assertEqual(document.doctype.internalSubset, INTERNAL_SUBSET) self.assertEqual(document.doctype.entities.length, 1, "entity not stored in doctype") node = document.doctype.entities['e'] self.assert_(node.notationName is None) self.assert_(node.publicId is None) self.assertEqual(node.systemId, 'http://xml.python.org/entity/e') self.assertEqual(document.doctype.notations.length, 1) node = document.doctype.notations['x'] self.assert_(node.publicId is None) self.assertEqual(node.systemId, 'http://xml.python.org/notation/x') self.check_attrs(document.documentElement.attributes, attributes) def test_namespace_decls_on(self): self.builder.setFeature("namespace_declarations", 1) self.run_checks(#((nsuri, localName), value), [((XMLNS_NAMESPACE, "A"), "http://xml.python.org/a"), ((XMLNS_NAMESPACE, "a"), "http://xml.python.org/a"), ((XMLNS_NAMESPACE, "b"), "http://xml.python.org/b"), (("http://xml.python.org/a", "a"), "a"), (("http://xml.python.org/b", "b"), "b"), ]) def test_namespace_decls_off(self): self.builder.setFeature("namespace_declarations", 0) self.run_checks(#((nsuri, localName), value), [(("http://xml.python.org/a", "a"), "a"), (("http://xml.python.org/b", "b"), "b"), ]) def test_get_element_by_id(self): ID_PREFIX = " ]>" doc = self.builder.parse(self.makeSource( ID_PREFIX + "")) self.assert_(doc.getElementById("bar") is None, "received unexpected node") self.assertEqual(doc.getElementById("foo").nodeName, "e", "did not get expected node") # Check an implementation detail; this is testing the # ID-caching behavior. self.assert_(doc._id_cache.has_key("foo")) # make sure adding an element with an ID works e = doc.createElement("e") e.setAttribute("id", "new") doc.documentElement.appendChild(e) self.assert_(e.isSameNode(doc.getElementById("new"))) # make sure the cache doesn't cause false hits when we remove nodes doc.documentElement.removeChild(e) self.assert_(e.parentNode is None) self.assert_(doc.getElementById("new") is None) # now add the node back, make sure we can still get it by id, # the change the value of the id attribute and check that it's # returned only for the new ID doc.documentElement.appendChild(e) self.assert_(e.isSameNode(doc.getElementById("new"))) a = e.getAttributeNode("id") a.value = "no-longer-new" self.assert_(doc.getElementById("new") is None) self.assert_(e.isSameNode(doc.getElementById("no-longer-new"))) # make sure removing the attribute makes the ID lookup return None: e.removeAttributeNode(a) self.assertEqual(e.getAttribute("id"), "") self.assert_(doc.getElementById("no-longer-new") is None) # check that modifying e.attributes works as well attrs = e.attributes e.setAttributeNode(a) self.assert_(e.isSameNode(doc.getElementById("no-longer-new"))) attrs.removeNamedItem("id") self.assert_(doc.getElementById("no-longer-new") is None) a2 = doc.createAttribute("id") a2.value = "alternate-id" attrs.setNamedItem(a) self.assert_(e.isSameNode(doc.getElementById("no-longer-new"))) attrs.setNamedItem(a2) self.assert_(doc.getElementById("no-longer-new") is None) self.assert_(e.isSameNode(doc.getElementById("alternate-id"))) # make sure nodes with an ID in a fragment are not located. f = doc.createDocumentFragment() e = doc.createElement("e") e.setAttribute("id", "in-fragment") f.appendChild(e) self.assert_(doc.getElementById("in-fragment") is None) doc = self.builder.parse(self.makeSource( ID_PREFIX + "")) self.assertEqual(doc.getElementById("foo").nodeName, "e", "did not get expected node") doc = self.builder.parse(self.makeSource( ID_PREFIX + ("" ""))) self.assertEqual(doc.getElementById("foo").getAttribute("name"), "a", "did not get expected node") def test_whitespace_in_element_content(self): DTD_PREFIX = " ]>" doc = self.builder.parse(self.makeSource( DTD_PREFIX + (" "))) docelem = doc.documentElement e1, e2 = docelem.getElementsByTagName("e") ws1 = docelem.firstChild ws2 = e2.firstChild # test WS in element content self.assert_(ws1.isWhitespaceInElementContent) ws1.appendData("not-white") self.assert_(not ws1.isWhitespaceInElementContent) ws1.replaceData(0, len(ws1.data), " ") self.assert_(ws1.isWhitespaceInElementContent) ws1.replaceData(0, len(ws1.data), "not-white") self.assert_(not ws1.isWhitespaceInElementContent) ws1.data = " " self.assert_(ws1.isWhitespaceInElementContent) # test WS not in element content self.assert_(not ws2.isWhitespaceInElementContent) ws2.appendData("not-white") self.assert_(not ws2.isWhitespaceInElementContent) ws2.replaceData(0, len(ws2.data), " ") self.assert_(not ws2.isWhitespaceInElementContent) ws2.replaceData(0, len(ws2.data), "not-white") self.assert_(not ws2.isWhitespaceInElementContent) ws2.data = " " self.assert_(not ws2.isWhitespaceInElementContent) def check_resolver(self, content_type, encoding): resolver = TestingResolver(content_type) source = resolver.resolveEntity(None, DUMMY_URL) self.assertEqual(source.encoding, encoding, "wrong encoding; expected %s, got %s" % (repr(encoding), repr(source.encoding))) def test_entity_resolver_encodings(self): self.check_resolver((None, None, []), None) self.check_resolver(("text", "plain", []), None) self.check_resolver(("text", "plain", ["charset=iso-8859-1"]), "iso-8859-1") self.check_resolver(("text", "plain", ["charset=UTF-8"]), "utf-8") def test_internal_subset_isolation(self): document = self.builder.parse(self.makeSource( " " "]>" )) s = document.toxml() self.assertEqual(s, '\n' ' ' ']>\n' '') def test_document_prolog_in_order(self): source = self.makeSource( "\n" "\n" "\n" "") document = self.builder.parse(source) s = document.toxml() self.assertEqual(s, '\n' '' '\n' '' '') def test_docelem_has_namespace(self): source = self.makeSource( "abcdef") document = self.builder.parse(source) self.assertEqual(document.documentElement.namespaceURI, 'http://xml.python.org/namespace/x') def test_isId(self): source = self.makeSource( "\n" "]>") document = self.builder.parse(source) elem = document.documentElement a1 = elem.getAttributeNode("id") a2 = elem.getAttributeNode("notid") self.failUnless(a1.isId) self.failIf(a2.isId) def test_schemaType(self): source = self.makeSource( "\n" " \n" " \n" "]>") document = self.builder.parse(source) elem = document.documentElement t = elem.schemaType self.assert_(t.name is None) self.assert_(t.namespace is None) check_attr = self.check_attr_schemaType check_attr(elem, "id", "id") check_attr(elem, "notid", None) check_attr(elem, "enum", "enumeration") check_attr(elem, "ent", "entity") check_attr(elem, "ents", "entities") check_attr(elem, "ref", "idref") check_attr(elem, "refs", "idrefs") check_attr(elem, "text", "cdata") def check_attr_schemaType(self, elem, attrname, name): a = elem.getAttributeNode(attrname) t = a.schemaType self.assert_(t.namespace is None) self.assertEqual(t.name, name) DUMMY_URL = "http://xml.python.org/dummy.xml" class TestingResolver(xmlbuilder.DOMEntityResolver): def __init__(self, content_type): self._content_type = content_type def _create_opener(self): return FakeOpener(self._content_type) if os.name == "nt": NULLFILE = "nul" else: NULLFILE = "/dev/null" class FakeOpener: def __init__(self, content_type): self._content_type = content_type def open(self, url): if url != DUMMY_URL: raise ValueError, "unexpected URL: " + repr(url) return FakeFile(open(NULLFILE, "rb"), self._content_type) class FakeFile: def __init__(self, file, content_type): self._file = file self._content_type = content_type def info(self): return FakeMessage(self._content_type) def __getattr__(self, name): return getattr(self._file, name) class FakeMessage: def __init__(self, content_type): self._maintype, self._subtype, self._plist = content_type def has_key(self, name): name = name.lower() if name != "content-type": raise ValueError, "unexpected has_key(%s)" % repr(name) return self._maintype is not None def getplist(self): return self._plist def getmaintype(self): return self._maintype or "text" def getsubtype(self): return self._subtype or "plain" def gettype(self): return "%s/%s" % (self.getmaintype(), self.getsubtype()) def test_suite(): return unittest.makeSuite(Tests) def test_main(): import test_support test_support.run_suite(test_suite()) if __name__ == "__main__": import test_support test_support.verbose = 1 test_main() PyXML-0.8.2/test/test_xmlproc.py0100644000076400001440000000261507550506761016003 0ustar martinusersimport os import sys from xml.parsers.xmlproc import xmlval from xml.parsers.xmlproc.utils import validate_doc, load_dtd, ErrorPrinter dtd = load_dtd("xmlval_illformed.dtd") f = open("doc.xml", "w") f.write(""" """) f.close() try: # validate_doc(dtd, "doc.xml") # validate_doc is not suitable since it prints to stderr parser = xmlval.XMLValidator() parser.dtd = dtd # FIXME: what to do if there is a !DOCTYPE? parser.set_error_handler(ErrorPrinter(parser, out=sys.stdout)) parser.parse_resource("doc.xml") finally: os.unlink("doc.xml") DOC_TEXT ="""\ %big-ent; ]> """ LINE = "\n" f1 = open("doc.xml", "w") f2 = open("larger-than-16K.ent", "w") try: f1.write(DOC_TEXT) f1.close() for i in range(int(17*1024 / len(LINE))): f2.write(LINE) f2.close() parser = xmlval.XMLValidator() #parser.dtd = dtd # FIXME: what to do if there is a !DOCTYPE? parser.set_error_handler(ErrorPrinter(parser, out=sys.stdout)) parser.parse_resource("doc.xml") finally: os.unlink("doc.xml") os.unlink("larger-than-16K.ent") PyXML-0.8.2/test/testxml.py0100644000076400001440000000033007413603011014730 0ustar martinusers# # Top-level program for XML test suite # import regrtest del regrtest.STDTESTS[:] def main(): tests = regrtest.findtests('.') regrtest.main( tests, testdir = '.' ) if __name__ == '__main__': main() PyXML-0.8.2/test/unittest.py0100644000076400001440000006136007517567471015151 0ustar martinusers#!/usr/bin/env python ''' Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's Smalltalk testing framework. This module contains the core framework classes that form the basis of specific test cases and suites (TestCase, TestSuite etc.), and also a text-based utility class for running the tests and reporting the results (TextTestRunner). Simple usage: import unittest class IntegerArithmenticTestCase(unittest.TestCase): def testAdd(self): ## test method names begin 'test*' self.assertEquals((1 + 2), 3) self.assertEquals(0 + 1, 1) def testMultiply(self): self.assertEquals((0 * 10), 0) self.assertEquals((5 * 8), 40) if __name__ == '__main__': unittest.main() Further information is available in the bundled documentation, and from http://pyunit.sourceforge.net/ Copyright (c) 1999, 2000, 2001 Steve Purcell This module is free software, and you may redistribute it and/or modify it under the same terms as Python itself, so long as this copyright message and disclaimer are retained in their original form. IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ''' __author__ = "Steve Purcell" __email__ = "stephen_purcell at yahoo dot com" __version__ = "#Revision: 1.43 $"[11:-2] import time import sys import traceback import string import os import types ############################################################################## # Test framework core ############################################################################## class TestResult: """Holder for test result information. Test results are automatically managed by the TestCase and TestSuite classes, and do not need to be explicitly manipulated by writers of tests. Each instance holds the total number of tests run, and collections of failures and errors that occurred among those test runs. The collections contain tuples of (testcase, exceptioninfo), where exceptioninfo is the formatted traceback of the error that occurred. """ def __init__(self): self.failures = [] self.errors = [] self.testsRun = 0 self.shouldStop = 0 def startTest(self, test): "Called when the given test is about to be run" self.testsRun = self.testsRun + 1 def stopTest(self, test): "Called when the given test has been run" pass def addError(self, test, err): """Called when an error has occurred. 'err' is a tuple of values as returned by sys.exc_info(). """ self.errors.append((test, self._exc_info_to_string(err))) def addFailure(self, test, err): """Called when an error has occurred. 'err' is a tuple of values as returned by sys.exc_info().""" self.failures.append((test, self._exc_info_to_string(err))) def addSuccess(self, test): "Called when a test has completed successfully" pass def wasSuccessful(self): "Tells whether or not this result was a success" return len(self.failures) == len(self.errors) == 0 def stop(self): "Indicates that the tests should be aborted" self.shouldStop = 1 def _exc_info_to_string(self, err): """Converts a sys.exc_info()-style tuple of values into a string.""" return string.join(apply(traceback.format_exception, err), '') def __repr__(self): return "<%s run=%i errors=%i failures=%i>" % \ (self.__class__, self.testsRun, len(self.errors), len(self.failures)) class TestCase: """A class whose instances are single test cases. By default, the test code itself should be placed in a method named 'runTest'. If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute. Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively. If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run. """ # This attribute determines which exception will be raised when # the instance's assertion methods fail; test methods raising this # exception will be deemed to have 'failed' rather than 'errored' failureException = AssertionError def __init__(self, methodName='runTest'): """Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name. """ try: self.__testMethodName = methodName testMethod = getattr(self, methodName) self.__testMethodDoc = testMethod.__doc__ except AttributeError: raise ValueError, "no such test method in %s: %s" % \ (self.__class__, methodName) def setUp(self): "Hook method for setting up the test fixture before exercising it." pass def tearDown(self): "Hook method for deconstructing the test fixture after testing it." pass def countTestCases(self): return 1 def defaultTestResult(self): return TestResult() def shortDescription(self): """Returns a one-line description of the test, or None if no description has been provided. The default implementation of this method returns the first line of the specified test method's docstring. """ doc = self.__testMethodDoc return doc and string.strip(string.split(doc, "\n")[0]) or None def id(self): return "%s.%s" % (self.__class__, self.__testMethodName) def __str__(self): return "%s (%s)" % (self.__testMethodName, self.__class__) def __repr__(self): return "<%s testMethod=%s>" % \ (self.__class__, self.__testMethodName) def run(self, result=None): return self(result) def __call__(self, result=None): if result is None: result = self.defaultTestResult() result.startTest(self) testMethod = getattr(self, self.__testMethodName) try: try: self.setUp() except KeyboardInterrupt: raise except: result.addError(self, self.__exc_info()) return ok = 0 try: testMethod() ok = 1 except self.failureException, e: result.addFailure(self, self.__exc_info()) except KeyboardInterrupt: raise except: result.addError(self, self.__exc_info()) try: self.tearDown() except KeyboardInterrupt: raise except: result.addError(self, self.__exc_info()) ok = 0 if ok: result.addSuccess(self) finally: result.stopTest(self) def debug(self): """Run the test without collecting errors in a TestResult""" self.setUp() getattr(self, self.__testMethodName)() self.tearDown() def __exc_info(self): """Return a version of sys.exc_info() with the traceback frame minimised; usually the top level of the traceback frame is not needed. """ exctype, excvalue, tb = sys.exc_info() if sys.platform[:4] == 'java': ## tracebacks look different in Jython return (exctype, excvalue, tb) newtb = tb.tb_next if newtb is None: return (exctype, excvalue, tb) return (exctype, excvalue, newtb) def fail(self, msg=None): """Fail immediately, with the given message.""" raise self.failureException, msg def failIf(self, expr, msg=None): "Fail the test if the expression is true." if expr: raise self.failureException, msg def failUnless(self, expr, msg=None): """Fail the test unless the expression is true.""" if not expr: raise self.failureException, msg def failUnlessRaises(self, excClass, callableObj, *args, **kwargs): """Fail unless an exception of class excClass is thrown by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is thrown, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception. """ try: apply(callableObj, args, kwargs) except excClass: return else: if hasattr(excClass,'__name__'): excName = excClass.__name__ else: excName = str(excClass) raise self.failureException, excName def failUnlessEqual(self, first, second, msg=None): """Fail if the two objects are unequal as determined by the '!=' operator. """ if first != second: raise self.failureException, \ (msg or '%s != %s' % (`first`, `second`)) def failIfEqual(self, first, second, msg=None): """Fail if the two objects are equal as determined by the '==' operator. """ if first == second: raise self.failureException, \ (msg or '%s == %s' % (`first`, `second`)) assertEqual = assertEquals = failUnlessEqual assertNotEqual = assertNotEquals = failIfEqual assertRaises = failUnlessRaises assert_ = failUnless class TestSuite: """A test suite is a composite test consisting of a number of TestCases. For use, create an instance of TestSuite, then add test case instances. When all tests have been added, the suite can be passed to a test runner, such as TextTestRunner. It will run the individual test cases in the order in which they were added, aggregating the results. When subclassing, do not forget to call the base class constructor. """ def __init__(self, tests=()): self._tests = [] self.addTests(tests) def __repr__(self): return "<%s tests=%s>" % (self.__class__, self._tests) __str__ = __repr__ def countTestCases(self): cases = 0 for test in self._tests: cases = cases + test.countTestCases() return cases def addTest(self, test): self._tests.append(test) def addTests(self, tests): for test in tests: self.addTest(test) def run(self, result): return self(result) def __call__(self, result): for test in self._tests: if result.shouldStop: break test(result) return result def debug(self): """Run the tests without collecting errors in a TestResult""" for test in self._tests: test.debug() class FunctionTestCase(TestCase): """A test case that wraps a test function. This is useful for slipping pre-existing test functions into the PyUnit framework. Optionally, set-up and tidy-up functions can be supplied. As with TestCase, the tidy-up ('tearDown') function will always be called if the set-up ('setUp') function ran successfully. """ def __init__(self, testFunc, setUp=None, tearDown=None, description=None): TestCase.__init__(self) self.__setUpFunc = setUp self.__tearDownFunc = tearDown self.__testFunc = testFunc self.__description = description def setUp(self): if self.__setUpFunc is not None: self.__setUpFunc() def tearDown(self): if self.__tearDownFunc is not None: self.__tearDownFunc() def runTest(self): self.__testFunc() def id(self): return self.__testFunc.__name__ def __str__(self): return "%s (%s)" % (self.__class__, self.__testFunc.__name__) def __repr__(self): return "<%s testFunc=%s>" % (self.__class__, self.__testFunc) def shortDescription(self): if self.__description is not None: return self.__description doc = self.__testFunc.__doc__ return doc and string.strip(string.split(doc, "\n")[0]) or None ############################################################################## # Locating and loading tests ############################################################################## class TestLoader: """This class is responsible for loading tests according to various criteria and returning them wrapped in a Test """ testMethodPrefix = 'test' sortTestMethodsUsing = cmp suiteClass = TestSuite def loadTestsFromTestCase(self, testCaseClass): """Return a suite of all tests cases contained in testCaseClass""" return self.suiteClass(map(testCaseClass, self.getTestCaseNames(testCaseClass))) def loadTestsFromModule(self, module): """Return a suite of all tests cases contained in the given module""" tests = [] for name in dir(module): obj = getattr(module, name) if type(obj) == types.ClassType and issubclass(obj, TestCase): tests.append(self.loadTestsFromTestCase(obj)) return self.suiteClass(tests) def loadTestsFromName(self, name, module=None): """Return a suite of all tests cases given a string specifier. The name may resolve either to a module, a test case class, a test method within a test case class, or a callable object which returns a TestCase or TestSuite instance. The method optionally resolves the names relative to a given module. """ parts = string.split(name, '.') if module is None: if not parts: raise ValueError, "incomplete test name: %s" % name else: parts_copy = parts[:] while parts_copy: try: module = __import__(string.join(parts_copy,'.')) break except ImportError: del parts_copy[-1] if not parts_copy: raise parts = parts[1:] obj = module for part in parts: obj = getattr(obj, part) import unittest if type(obj) == types.ModuleType: return self.loadTestsFromModule(obj) elif type(obj) == types.ClassType and issubclass(obj, unittest.TestCase): return self.loadTestsFromTestCase(obj) elif type(obj) == types.UnboundMethodType: return obj.im_class(obj.__name__) elif callable(obj): test = obj() if not isinstance(test, unittest.TestCase) and \ not isinstance(test, unittest.TestSuite): raise ValueError, \ "calling %s returned %s, not a test" % (obj,test) return test else: raise ValueError, "don't know how to make test from: %s" % obj def loadTestsFromNames(self, names, module=None): """Return a suite of all tests cases found using the given sequence of string specifiers. See 'loadTestsFromName()'. """ suites = [] for name in names: suites.append(self.loadTestsFromName(name, module)) return self.suiteClass(suites) def getTestCaseNames(self, testCaseClass): """Return a sorted sequence of method names found within testCaseClass """ testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p, dir(testCaseClass)) for baseclass in testCaseClass.__bases__: for testFnName in self.getTestCaseNames(baseclass): if testFnName not in testFnNames: # handle overridden methods testFnNames.append(testFnName) if self.sortTestMethodsUsing: testFnNames.sort(self.sortTestMethodsUsing) return testFnNames defaultTestLoader = TestLoader() ############################################################################## # Patches for old functions: these functions should be considered obsolete ############################################################################## def _makeLoader(prefix, sortUsing, suiteClass=None): loader = TestLoader() loader.sortTestMethodsUsing = sortUsing loader.testMethodPrefix = prefix if suiteClass: loader.suiteClass = suiteClass return loader def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp): return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass) def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite): return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass) def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite): return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module) ############################################################################## # Text UI ############################################################################## class _WritelnDecorator: """Used to decorate file-like objects with a handy 'writeln' method""" def __init__(self,stream): self.stream = stream def __getattr__(self, attr): return getattr(self.stream,attr) def writeln(self, *args): if args: apply(self.write, args) self.write('\n') # text-mode streams translate to \r\n if needed class _TextTestResult(TestResult): """A test result class that can print formatted text results to a stream. Used by TextTestRunner. """ separator1 = '=' * 70 separator2 = '-' * 70 def __init__(self, stream, descriptions, verbosity): TestResult.__init__(self) self.stream = stream self.showAll = verbosity > 1 self.dots = verbosity == 1 self.descriptions = descriptions def getDescription(self, test): if self.descriptions: return test.shortDescription() or str(test) else: return str(test) def startTest(self, test): TestResult.startTest(self, test) if self.showAll: self.stream.write(self.getDescription(test)) self.stream.write(" ... ") def addSuccess(self, test): TestResult.addSuccess(self, test) if self.showAll: self.stream.writeln("ok") elif self.dots: self.stream.write('.') def addError(self, test, err): TestResult.addError(self, test, err) if self.showAll: self.stream.writeln("ERROR") elif self.dots: self.stream.write('E') def addFailure(self, test, err): TestResult.addFailure(self, test, err) if self.showAll: self.stream.writeln("FAIL") elif self.dots: self.stream.write('F') def printErrors(self): if self.dots or self.showAll: self.stream.writeln() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) def printErrorList(self, flavour, errors): for test, err in errors: self.stream.writeln(self.separator1) self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) self.stream.writeln(self.separator2) self.stream.writeln("%s" % err) class TextTestRunner: """A test runner class that displays results in textual form. It prints out the names of tests as they are run, errors as they occur, and a summary of the results at the end of the test run. """ def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1): self.stream = _WritelnDecorator(stream) self.descriptions = descriptions self.verbosity = verbosity def _makeResult(self): return _TextTestResult(self.stream, self.descriptions, self.verbosity) def run(self, test): "Run the given test case or test suite." result = self._makeResult() startTime = time.time() test(result) stopTime = time.time() timeTaken = float(stopTime - startTime) result.printErrors() self.stream.writeln(result.separator2) run = result.testsRun self.stream.writeln("Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() if not result.wasSuccessful(): self.stream.write("FAILED (") failed, errored = map(len, (result.failures, result.errors)) if failed: self.stream.write("failures=%d" % failed) if errored: if failed: self.stream.write(", ") self.stream.write("errors=%d" % errored) self.stream.writeln(")") else: self.stream.writeln("OK") return result ############################################################################## # Facilities for running tests from the command line ############################################################################## class TestProgram: """A command-line program that runs a set of tests; this is primarily for making test modules conveniently executable. """ USAGE = """\ Usage: %(progName)s [options] [test] [...] Options: -h, --help Show this message -v, --verbose Verbose output -q, --quiet Minimal output Examples: %(progName)s - run default set of tests %(progName)s MyTestSuite - run suite 'MyTestSuite' %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething %(progName)s MyTestCase - run all 'test*' test methods in MyTestCase """ def __init__(self, module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=defaultTestLoader): if type(module) == type(''): self.module = __import__(module) for part in string.split(module,'.')[1:]: self.module = getattr(self.module, part) else: self.module = module if argv is None: argv = sys.argv self.verbosity = 1 self.defaultTest = defaultTest self.testRunner = testRunner self.testLoader = testLoader self.progName = os.path.basename(argv[0]) self.parseArgs(argv) self.runTests() def usageExit(self, msg=None): if msg: print msg print self.USAGE % self.__dict__ sys.exit(2) def parseArgs(self, argv): import getopt try: options, args = getopt.getopt(argv[1:], 'hHvq', ['help','verbose','quiet']) for opt, value in options: if opt in ('-h','-H','--help'): self.usageExit() if opt in ('-q','--quiet'): self.verbosity = 0 if opt in ('-v','--verbose'): self.verbosity = 2 if len(args) == 0 and self.defaultTest is None: self.test = self.testLoader.loadTestsFromModule(self.module) return if len(args) > 0: self.testNames = args else: self.testNames = (self.defaultTest,) self.createTests() except getopt.error, msg: self.usageExit(msg) def createTests(self): self.test = self.testLoader.loadTestsFromNames(self.testNames, self.module) def runTests(self): if self.testRunner is None: self.testRunner = TextTestRunner(verbosity=self.verbosity) result = self.testRunner.run(self.test) sys.exit(not result.wasSuccessful()) main = TestProgram ############################################################################## # Executing this module from the command line ############################################################################## if __name__ == "__main__": main(module=None) PyXML-0.8.2/test/xmlval_illformed.dtd0100644000076400001440000000003707250122417016724 0ustar martinusers PyXML-0.8.2/xml/0040755000076400001440000000000007614726123012523 5ustar martinusersPyXML-0.8.2/xml/dom/0040755000076400001440000000000007614726123013302 5ustar martinusersPyXML-0.8.2/xml/dom/de/0040755000076400001440000000000007614726123013672 5ustar martinusersPyXML-0.8.2/xml/dom/de/LC_MESSAGES/0040755000076400001440000000000007614726123015457 5ustar martinusersPyXML-0.8.2/xml/dom/de/LC_MESSAGES/4Suite.mo0100644000076400001440000000433307377133276017200 0ustar martinusers\$]$&.+H_&|#!?3D&x!&") $50Z#6-?(T}$.)-8>fC-46L*,Attempt to modify a read-only objectAttempt to modify the type of a nodeAttribute already in use by an elementDOMString exceeds maximum sizeIndex error accessing NodeList or NamedNodeMapInvalid Boundary Points specified for RangeInvalid Container NodeInvalid or illegal characterInvalid or illegal namespace operationNode does not exist in this contextNode does not support dataNode is from a different documentNode manipulation results in invalid parent/child relationship.Object does not support this operation or parameterObject is not, or is no longer, usableObject or operation not supportedSpecified string is invalid or illegalUninitialized type in Event objectXML parse error at line %d, column %d: %sProject-Id-Version: Dom PO-Revision-Date: 2025-01-31 08:09+01:00 Last-Translator: Martin v. Lwis Language-Team: German MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8-bit Generated-By: pygettext.py 1.1 nderung eines unvernderbaren Objekts versucht.Typnderung eines Knotens versucht.Das Attribut wird bereits von einem Element verwendet.Der DOMString ist grer als maximal erlaubt.Indexfehler bei Zugriff auf NodeList- oder NamedNodeMap-Objekt.Ungltige Endpunkte fr Range angegeben.Ungltiger Container-Knoten.Ungltiges oder unerlaubtes Zeichen.Ungltige oder unerlaubte Namespace-Operation.Knoten existiert in diesem Kontext nicht.Knoten untersttzt keine Daten.Der Knoten stammt aus einem anderen Dokument.Knotennderung resultiert in ungltiger Eltern-Kind-Beziehung.Das Objekt untersttzt diese Operation oder diesen Parameter nicht.Das Objekt ist nicht oder nicht mehr nutzbar.Das Objekt oder die Operation ist nicht untersttzt.Der angegebene String ist ungltig oder nicht erlaubt.Nicht-initialisierter Typ in Event-Objekt.XML-Parser-Fehler in Zeile %d, Spalte %d: %sPyXML-0.8.2/xml/dom/en_US/0040755000076400001440000000000007614726123014313 5ustar martinusersPyXML-0.8.2/xml/dom/en_US/LC_MESSAGES/0040755000076400001440000000000007614726123016100 5ustar martinusersPyXML-0.8.2/xml/dom/en_US/LC_MESSAGES/4Suite.mo0100644000076400001440000000051307244340623017602 0ustar martinusers$,-Project-Id-Version: PACKAGE VERSION PO-Revision-Date: Sun Feb 18 17:52:04 2001 Last-Translator: FULL NAME Language-Team: LANGUAGE MIME-Version: 1.0 Content-Type: text/plain; charset=CHARSET Content-Transfer-Encoding: ENCODING Generated-By: pygettext.py 1.1 PyXML-0.8.2/xml/dom/ext/0040755000076400001440000000000007614726123014102 5ustar martinusersPyXML-0.8.2/xml/dom/ext/reader/0040755000076400001440000000000007614726123015344 5ustar martinusersPyXML-0.8.2/xml/dom/ext/reader/test_suite/0040755000076400001440000000000007614726123017534 5ustar martinusersPyXML-0.8.2/xml/dom/ext/reader/test_suite/Benchmark.py0100644000076400001440000000046207253474633022004 0ustar martinusersfrom xml.dom.ext.reader import Sax2 def Benchmark(fileName): return Sax2.FromXmlFile(fileName) if __name__ == '__main__': import time,sys sTime = time.time() d = Benchmark(sys.argv[1]) print "Total Time: %f" % (time.time() - sTime) from xml.dom import ext ext.Print(d) PyXML-0.8.2/xml/dom/ext/reader/HtmlLib.py0100644000076400001440000000625207413602167017251 0ustar martinusers######################################################################## # # File Name: HtmlLib.py # # Documentation: http://docs.4suite.com/4DOM/HtmlLib.py.html # """ Components for reading HTML files using htmllib.py. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import os, urllib from xml.dom.ext import reader from xml.dom import Node import Sgmlop class Reader(reader.Reader): def __init__(self): self.parser = Sgmlop.HtmlParser() def fromStream(self, stream, ownerDoc=None, charset=''): self.parser.initParser() self.parser.initState(ownerDoc, charset) self.parser.parse(stream) frag = self.parser.rootNode if ownerDoc is None: # Use the created document doc = frag.ownerDocument # we have created a new document, and a documentFragment that belongs to this document. # However, the document is already '' # so we need to find out if we have an HTML node in the fragment. for child in frag.childNodes: if child.nodeType == Node.ELEMENT_NODE and child.tagName == 'HTML': # clean up the junk automatically generated by the HTMLDomImplementation while doc.documentElement.firstChild: c = doc.documentElement.removeChild(doc.documentElement.firstChild) self.releaseNode(c) # copy stuff while child.firstChild: doc.documentElement.appendChild(child.firstChild) self.releaseNode(frag) return doc # We are here if we could not find an HTML element in the fragment. # In this case, we should append everything under the BODY element in the document body = doc.documentElement.lastChild body.appendChild(frag) self.releaseNode(frag) return doc else: # an owner document was passed, we return the fragment, as is. return frag def fromUri(self, uri, ownerDoc=None, charset=''): stream = reader.BASIC_RESOLVER.resolve(uri) try: return self.fromStream(stream, ownerDoc, charset) finally: stream.close() def fromString(self, str, ownerDoc=None, charset=''): stream = reader.StrStream(str) try: return self.fromStream(stream, ownerDoc, charset) finally: stream.close() ########################## Deprecated ############################## def FromHtmlStream(fp, ownerDoc=None, charset=''): return Reader().fromStream(fp, ownerDoc, charset) def FromHtmlFile(fileName, ownerDoc=None, charset=''): return Reader().fromUri(fileName, ownerDoc, charset) def FromHtmlUrl(url, ownerDoc=None, charset=''): return Reader().fromUri(url, ownerDoc, charset) def FromHtml(text, ownerDoc=None, charset=''): return Reader().fromString(text, ownerDoc, charset) PyXML-0.8.2/xml/dom/ext/reader/HtmlSax.py0100644000076400001440000000616707271065024017300 0ustar martinusers######################################################################## # # File Name: HtmlSax.py # # Documentation: http://docs.4suite.com/4DOM/HtmlSax.py.html # # """ Components for reading HTML files from a SAX-like producer. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import sys, string, cStringIO import xml.dom.ext from xml.dom import Node from xml.dom import implementation class HtmlDomGenerator: def __init__(self, keepAllWs=0): self._keepAllWs = keepAllWs def initState(self, ownerDoc=None): """ If None is passed in as the doc, set up an empty document to act as owner and also add all elements to this document """ if ownerDoc == None: self._ownerDoc = implementation.createHTMLDocument('') de = self._ownerDoc.documentElement self._ownerDoc.removeChild(de) xml.dom.ext.ReleaseNode(de) self._rootNode = self._ownerDoc else: self._ownerDoc = ownerDoc #Create a docfrag to hold all the generated nodes. self._rootNode = self._ownerDoc.createDocumentFragment() #Set up the stack which keeps track of the nesting of DOM nodes. self._nodeStack = [] self._nodeStack.append(self._rootNode) self._currText = '' return def getRootNode(self): self._completeTextNode() return self._rootNode def _completeTextNode(self): if self._currText: new_text = self._ownerDoc.createTextNode(self._currText) self._nodeStack[-1].appendChild(new_text) self._currText = '' #Overridden DocumentHandler methods def startElement(self, name, attribs): self._completeTextNode() new_element = self._ownerDoc.createElement(name) for curr_attrib_key in attribs.keys(): new_element.setAttribute(curr_attrib_key, attribs[curr_attrib_key]) self._nodeStack.append(new_element) def endElement(self, name): self._completeTextNode() new_element = self._nodeStack[-1] del self._nodeStack[-1] self._nodeStack[-1].appendChild(new_element) def ignorableWhitespace(self, ch, start, length): """ If 'keepAllWs' permits, add ignorable white-space as a text node. Remember that a Document node cannot contain text nodes directly. If the white-space occurs outside the root element, there is no place for it in the DOM and it must be discarded. """ if self._keepAllWs and self._nodeStack[-1].nodeType != Node.DOCUMENT_NODE: self._currText = self._currText + ch[start:start+length] def characters(self, ch, start, length): self._currText = self._currText + ch[start:start+length] #Overridden ErrorHandler methods #def warning(self, exception): # raise exception def error(self, exception): raise exception def fatalError(self, exception): raise exception PyXML-0.8.2/xml/dom/ext/reader/PyExpat.py0100644000076400001440000002135307611541426017307 0ustar martinusers######################################################################## # # File Name: PyExpat.py # # Documentation: http://docs.4suite.com/4DOM/PyExpat.py.html # """ Components for reading XML files from PyExpat (Python 1.6, 2.0 or from PyXML). WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import os, sys, string, cStringIO from xml.dom import Entity, DocumentType, Document from xml.dom import Node from xml.dom import implementation from xml.dom.ext import SplitQName, ReleaseNode from xml.dom import XML_NAMESPACE, XMLNS_NAMESPACE from xml.dom import Element from xml.dom import Attr from xml.dom.ext import reader from xml.parsers import expat class Reader(reader.Reader): def __init__(self): return def initState(self, ownerDoc=None): self._ownerDoc = None self._rootNode = None #Set up the stack which keeps track of the nesting of DOM nodes. self._nodeStack = [] if ownerDoc: self._ownerDoc = ownerDoc #Create a docfrag to hold all the generated nodes. self._rootNode = self._ownerDoc.createDocumentFragment() self._nodeStack.append(self._rootNode) self._dt = None self._xmlDecl = None self._orphanedNodes = [] self._namespaces = {'xml': XML_NAMESPACE} self._namespaceStack = [] self._currText = '' return def initParser(self): self.parser = expat.ParserCreate() self.parser.buffer_text = 1 self.parser.StartElementHandler = self.startElement self.parser.EndElementHandler = self.endElement self.parser.CharacterDataHandler = self.characters self.parser.ProcessingInstructionHandler = self.processingInstruction self.parser.CommentHandler = self.comment self.parser.StartCdataSectionHandler = self.startCDATA self.parser.EndCdataSectionHandler = self.endCDATA self.parser.NotationDeclHandler = self.notationDecl self.parser.UnparsedEntityDeclHandler = self.unparsedEntityDecl return def fromStream(self, stream, ownerDoc=None): self.initParser() self.initState(ownerDoc) success = self.parser.ParseFile(stream) if not success: from xml.dom.ext import FtDomException from xml.dom import XML_PARSE_ERR if self._rootNode: ReleaseNode(self._rootNode) if self._ownerDoc: ReleaseNode(self._ownerDoc) raise FtDomException(XML_PARSE_ERR, (self.parser.ErrorLineNumber, self.parser.ErrorColumnNumber, expat.ErrorString(self.parser.ErrorCode))) self._completeTextNode() return self._rootNode or self._ownerDoc def _initRootNode(self, docElementUri, docElementName): if not self._dt: self._dt = implementation.createDocumentType(docElementName,'','') self._ownerDoc = implementation.createDocument(docElementUri, docElementName, self._dt) before_doctype = 1 for o_node in self._orphanedNodes: if o_node[0] == 'pi': pi = self._ownerDoc.createProcessingInstruction( o_node[1], o_node[2] ) if before_doctype: self._ownerDoc.insertBefore(pi, self._dt) else: self._ownerDoc.appendChild(pi) elif o_node[0] == 'comment': comment = self._ownerDoc.createComment(o_node[1]) if before_doctype: self._ownerDoc.insertBefore(comment, self._dt) else: self._ownerDoc.appendChild(comment) elif o_node[0] == 'doctype': before_doctype = 0 self._rootNode = self._ownerDoc self._nodeStack.append(self._rootNode) return def _completeTextNode(self): #Note some parsers don;t report ignorable white space properly if self._currText and len(self._nodeStack) and self._nodeStack[-1].nodeType != Node.DOCUMENT_NODE: new_text = self._ownerDoc.createTextNode(self._currText) self._nodeStack[-1].appendChild(new_text) self._currText = '' return def processingInstruction (self, target, data): if self._rootNode: self._completeTextNode() pi = self._ownerDoc.createProcessingInstruction(target, data) self._nodeStack[-1].appendChild(pi) else: self._orphanedNodes.append(('pi', target, data)) return def startElement(self, name, attribs): self._completeTextNode() old_nss = {} del_nss = [] for curr_attrib_key, value in attribs.items(): (prefix, local) = SplitQName(curr_attrib_key) if local == 'xmlns': if self._namespaces.has_key(prefix): old_nss[prefix] = self._namespaces[prefix] if value: self._namespaces[prefix] = attribs[curr_attrib_key] else: del self._namespaces[prefix] elif value: self._namespaces[prefix] = attribs[curr_attrib_key] del_nss.append(prefix) self._namespaceStack.append((old_nss, del_nss)) (prefix, local) = SplitQName(name) nameSpace = self._namespaces.get(prefix, None) if self._ownerDoc: new_element = self._ownerDoc.createElementNS( nameSpace, (prefix and prefix + ':' + local) or local ) else: self._initRootNode(nameSpace, name) new_element = self._ownerDoc.documentElement for curr_attrib_key,curr_attrib_value in attribs.items(): (prefix, local) = SplitQName(curr_attrib_key) qname = local if local == 'xmlns': namespace = XMLNS_NAMESPACE if prefix: qname = local + ':' + prefix attr = self._ownerDoc.createAttributeNS(namespace, qname) else: namespace = prefix and self._namespaces.get(prefix, None) or None if prefix: qname = prefix + ':' + local attr = self._ownerDoc.createAttributeNS(namespace, qname) attr.value = curr_attrib_value new_element.setAttributeNodeNS(attr) self._nodeStack.append(new_element) return def endElement(self, name): self._completeTextNode() new_element = self._nodeStack[-1] del self._nodeStack[-1] old_nss, del_nss = self._namespaceStack[-1] del self._namespaceStack[-1] self._namespaces.update(old_nss) for prefix in del_nss: del self._namespaces[prefix] if new_element != self._ownerDoc.documentElement: self._nodeStack[-1].appendChild(new_element) return def characters(self, data): self._currText = self._currText + data return def startDTD(self, doctype, publicID, systemID): if not self._rootNode: self._dt = implementation.createDocumentType(doctype, publicID, systemID) self._orphanedNodes.append(('doctype')) else: raise 'Illegal DocType declaration' return def comment(self, text): if self._rootNode: self._completeTextNode() new_comment = self._ownerDoc.createComment(text) self._nodeStack[-1].appendChild(new_comment) else: self._orphanedNodes.append(('comment', text)) return def startCDATA(self): self._completeTextNode() return def endCDATA(self): #NOTE: this doesn't handle the error where endCDATA is called #Without corresponding startCDATA. Is this a problem? if self._currText: new_text = self._ownerDoc.createCDATASection(self._currText) self._nodeStack[-1].appendChild(new_text) self._currText = '' return def notationDecl(self, name, base, publicId, systemId): #FIXME: Base URI resolution? new_notation = self._ownerDoc.getFactory().createNotation(self._ownerDoc, publicId, systemId, name) self._ownerDoc.getDocumentType().getNotations().setNamedItem(new_notation) return def unparsedEntityDecl(self, name, base, publicId, systemId, notationName): #FIXME: Base URI resolution? new_notation = self._ownerDoc.getFactory().createEntity(self._ownerDoc, publicId, systemId, notationName) self._ownerDoc.getDocumentType().getEntities().setNamedItem(new_notation) return PyXML-0.8.2/xml/dom/ext/reader/Sax.py0100644000076400001440000001445507537435062016462 0ustar martinusers######################################################################## # # File Name: Sax.py # # Documentation: http://docs.4suite.com/4DOM/Sax.py.html # """ Components for reading XML files from a SAX producer. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import sys, string, cStringIO, urllib2 from xml.sax import saxlib, saxexts, drivers from xml.dom import Entity, DocumentType, Document from xml.dom import DocumentType, Document from xml.dom import implementation from xml.dom.ext import SplitQName, ReleaseNode from xml.dom.ext import reader class XmlDomGenerator(saxlib.HandlerBase): def __init__(self, keepAllWs=0): self._keepAllWs = keepAllWs return def initState(self, ownerDoc=None): """ If None is passed in as the doc, set up an empty document to act as owner and also add all elements to this document """ if ownerDoc == None: dt = implementation.createDocumentType('', '', '') self._ownerDoc = implementation.createDocument('', None, dt) self._rootNode = self._ownerDoc else: self._ownerDoc = ownerDoc #Create a docfrag to hold all the generated nodes. self._rootNode = self._ownerDoc.createDocumentFragment() #Set up the stack which keeps track of the nesting of DOM nodes. self._nodeStack = [] self._nodeStack.append(self._rootNode) self._currText = '' return def getRootNode(self): self._completeTextNode() return self._rootNode def _completeTextNode(self): if self._currText: new_text = self._ownerDoc.createTextNode(self._currText) self._nodeStack[-1].appendChild(new_text) self._currText = '' #Overridden DTDHandler methods def notationDecl (self, name, publicId, systemId): new_notation = self._ownerDoc.createNotation(self._ownerDoc, publicId, systemId, name) self._ownerDoc.documentType.notations.setNamedItem(new_notation) def unparsedEntityDecl (self, name, publicId, systemId, notationName): new_notation = implementation.createEntity(self._ownerDoc, publicId, systemId, notationName) self._ownerDoc.documentType.entities.setNamedItem(new_notation) #Overridden DocumentHandler methods def processingInstruction (self, target, data): self._completeTextNode() p = self._ownerDoc.createProcessingInstruction(target,data); self._nodeStack[-1].appendChild(p) def startElement(self, name, attribs): self._completeTextNode() new_element = self._ownerDoc.createElement(name) for curr_attrib_key in attribs.keys(): new_element.setAttribute( curr_attrib_key, attribs[curr_attrib_key] ) self._nodeStack.append(new_element) def endElement(self, name): self._completeTextNode() new_element = self._nodeStack[-1] del self._nodeStack[-1] self._nodeStack[-1].appendChild(new_element) def ignorableWhitespace(self, ch, start, length): """ If 'keepAllWs' permits, add ignorable white-space as a text node. A Document node cannot contain text nodes directly. If the white-space occurs outside the root element, there is no place for it in the DOM and it must be discarded. """ if self._keepAllWs: self._currText = self._currText + ch[start:start+length] def characters(self, ch, start, length): self._currText = self._currText + ch[start:start+length] #Overridden ErrorHandler methods #def warning(self, exception): # raise exception def error(self, exception): raise exception def fatalError(self, exception): raise exception class Reader(reader.Reader): def __init__(self, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): #Create an XML DOM from SAX events self.parser = parser or (validate and saxexts.XMLValParserFactory.make_parser()) or saxexts.XMLParserFactory.make_parser() if catName: #set up the catalog, if there is one from xml.parsers.xmlproc import catalog cat_handler = catalog.SAX_catalog(catName, catalog.CatParserFactory()) self.parser.setEntityResolver(cat_handler) self.handler = saxHandlerClass(keepAllWs) self.parser.setDocumentHandler(self.handler) self.parser.setDTDHandler(self.handler) self.parser.setErrorHandler(self.handler) return def releaseNode(self, node): ReleaseNode(node) def fromStream(self, stream, ownerDocument=None): self.handler.initState(ownerDoc=ownerDocument) self.parser.parseFile(stream) return self.handler.getRootNode() ########################## Deprecated ############################## def FromXmlStream(stream, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): reader = Reader(validate, keepAllWs, catName, saxHandlerClass, parser) return reader.fromStream(stream, ownerDocument) def FromXml(text, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): fp = cStringIO.StringIO(text) rv = FromXmlStream(fp, ownerDocument, validate, keepAllWs, catName, saxHandlerClass, parser) return rv def FromXmlFile(fileName, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): fp = open(fileName, 'r') try: rv = FromXmlStream(fp, ownerDocument, validate, keepAllWs, catName, saxHandlerClass, parser) finally: fp.close() return rv def FromXmlUrl(url, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): fp = urllib2.urlopen(url) try: rv = FromXmlStream(fp, ownerDocument, validate, keepAllWs, catName, saxHandlerClass, parser) finally: fp.close() return rv PyXML-0.8.2/xml/dom/ext/reader/Sax2.py0100644000076400001440000003726207537435062016545 0ustar martinusers######################################################################## # # File Name: Sax2.py # # Documentation: http://docs.4suite.com/4DOM/Sax2.py.html # """ Components for reading XML files from a SAX2 producer. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000, 2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import sys, string, cStringIO, os, urllib2 from xml.sax import saxlib, saxutils, sax2exts, handler from xml.dom import Entity, DocumentType, Document from xml.dom import Node from xml.dom import implementation from xml.dom.ext import SplitQName, ReleaseNode from xml.dom import XML_NAMESPACE, XMLNS_NAMESPACE, EMPTY_NAMESPACE from xml.dom import Element from xml.dom import Attr from xml.dom.ext import reader class NsHandler: def initState(self, ownerDoc=None): self._namespaces = {'xml': XML_NAMESPACE, None: EMPTY_NAMESPACE} self._namespaceStack = [] return def startElement(self, name, attribs): self._completeTextNode() old_nss = {} del_nss = [] for curr_attrib_key, value in attribs.items(): (prefix, local) = SplitQName(curr_attrib_key) if local == 'xmlns': if self._namespaces.has_key(prefix): old_nss[prefix] = self._namespaces[prefix] if value: self._namespaces[prefix] = attribs[curr_attrib_key] else: del self._namespaces[prefix] elif value: self._namespaces[prefix] = attribs[curr_attrib_key] del_nss.append(prefix) self._namespaceStack.append((old_nss, del_nss)) (prefix, local) = SplitQName(name) nameSpace = self._namespaces.get(prefix, None) if self._ownerDoc: new_element = self._ownerDoc.createElementNS(nameSpace, (prefix and prefix + ':' + local) or local) else: self._initRootNode(nameSpace, name) new_element = self._ownerDoc.documentElement for curr_attrib_key,curr_attrib_value in attribs.items(): (prefix, local) = SplitQName(curr_attrib_key) qname = local if local == 'xmlns': namespace = XMLNS_NAMESPACE if prefix: qname = local + ':' + prefix attr = self._ownerDoc.createAttributeNS(namespace, qname) else: if prefix: qname = prefix + ':' + local namespace = prefix and self._namespaces.get(prefix, None) or None attr = self._ownerDoc.createAttributeNS(namespace, qname) attr.value = curr_attrib_value new_element.setAttributeNodeNS(attr) self._nodeStack.append(new_element) return def endElement(self, name): self._completeTextNode() new_element = self._nodeStack[-1] del self._nodeStack[-1] old_nss, del_nss = self._namespaceStack[-1] del self._namespaceStack[-1] self._namespaces.update(old_nss) for prefix in del_nss: del self._namespaces[prefix] if new_element != self._ownerDoc.documentElement: self._nodeStack[-1].appendChild(new_element) return class XmlDomGenerator(NsHandler, saxutils.DefaultHandler, saxlib.LexicalHandler, saxlib.DeclHandler): def __init__(self, keepAllWs=0, implementation=implementation): self._keepAllWs = keepAllWs self._impl = implementation return def initState(self, ownerDoc=None): self._ownerDoc = None self._rootNode = None #Set up the stack which keeps track of the nesting of DOM nodes. self._nodeStack = [] self._nsuri2pref = {EMPTY_NAMESPACE:[None], XML_NAMESPACE: ['xml']} self._pref2nsuri = {None: [EMPTY_NAMESPACE], 'xml': XML_NAMESPACE} self._new_prefix_mappings = [] if ownerDoc: self._ownerDoc = ownerDoc #Create a docfrag to hold all the generated nodes. self._rootNode = self._ownerDoc.createDocumentFragment() self._nodeStack.append(self._rootNode) self._dt = None self._xmlDecl = None self._orphanedNodes = [] self._currText = '' NsHandler.initState(self, ownerDoc) return def _initRootNode(self, docElementUri, docElementName): if not self._dt: self._dt = self._impl.createDocumentType(docElementName, None, '') self._ownerDoc = self._impl.createDocument(docElementUri, docElementName, self._dt) if self._xmlDecl: decl_data = 'version="%s"' % ( self._xmlDecl['version'] ) if self._xmlDecl['encoding']: decl_data = decl_data + ' encoding="%s"'%( self._xmlDecl['encoding'] ) if self._xmlDecl['standalone']: decl_data = decl_data + ' standalone="%s"'%( self._xmlDecl['standalone'] ) xml_decl_node = self._ownerDoc.createProcessingInstruction( 'xml', decl_data ) self._ownerDoc.insertBefore(xml_decl_node, self._ownerDoc.docType) before_doctype = 1 for o_node in self._orphanedNodes: if o_node[0] == 'pi': pi = self._ownerDoc.createProcessingInstruction( o_node[1], o_node[2] ) if before_doctype: self._ownerDoc.insertBefore(pi, self._dt) else: self._ownerDoc.appendChild(pi) elif o_node[0] == 'comment': comment = self._ownerDoc.createComment(o_node[1]) if before_doctype: self._ownerDoc.insertBefore(comment, self._dt) else: self._ownerDoc.appendChild(comment) elif o_node[0] == 'doctype': before_doctype = 0 elif o_node[0] == 'unparsedentitydecl': apply(self.unparsedEntityDecl, o_node[1:]) else: raise "Unknown orphaned node:"+o_node[0] self._rootNode = self._ownerDoc self._nodeStack.append(self._rootNode) return def _completeTextNode(self): #Note some parsers don't report ignorable white space properly if self._currText and len(self._nodeStack) and self._nodeStack[-1].nodeType != Node.DOCUMENT_NODE: new_text = self._ownerDoc.createTextNode(self._currText) self._nodeStack[-1].appendChild(new_text) self._currText = '' return def getRootNode(self): self._completeTextNode() return self._rootNode #Overridden DocumentHandler methods def processingInstruction(self, target, data): if self._rootNode: self._completeTextNode() pi = self._ownerDoc.createProcessingInstruction(target, data) self._nodeStack[-1].appendChild(pi) else: self._orphanedNodes.append(('pi', target, data)) return def startPrefixMapping(self, prefix, uri): try: map = self._pref2nsuri[prefix] except: map = [] self._pref2nsuri[prefix] = map map.append(uri) try: map = self._nsuri2pref[uri] except: map = [] self._nsuri2pref[uri] = map map.append(prefix) self._new_prefix_mappings.append((prefix,uri)) ## print 'startPrefixMapping',prefix,uri ## print 'pref->uri',self._pref2nsuri ## print 'uri->pref',self._nsuri2pref def endPrefixMapping(self, prefix): ## print 'endPrefixMapping',prefix ## print 'pref->uri',self._pref2nsuri ## print 'uri->pref',self._nsuri2pref uri = self._pref2nsuri[prefix][-1] del self._pref2nsuri[prefix][-1] del self._nsuri2pref[uri][-1] if not self._pref2nsuri[prefix]: del self._pref2nsuri[prefix] if not self._nsuri2pref[uri]: del self._nsuri2pref[uri] def startElementNS(self, name, qname, attribs): self._completeTextNode() namespace = name[0] local = name[1] if qname is None: if self._nsuri2pref[namespace][-1]: qname = string.join((self._nsuri2pref[namespace][-1], local), ':') else : qname = local if self._ownerDoc: new_element = self._ownerDoc.createElementNS(namespace, qname) else: self._initRootNode(namespace, qname) new_element = self._ownerDoc.documentElement for ((attr_ns, lname), value) in attribs.items(): if attr_ns is not None: try: attr_qname = attribs.getQNameByName((attr_ns, lname)) except KeyError:# pyexpat doesn't report qnames... attr_prefix = self._nsuri2pref[attr_ns][-1] if attr_prefix is None: # I'm not sure that this is possible attr_qname = lname else: attr_qname = string.join((attr_prefix,lname), ':') else: attr_qname = lname attr = self._ownerDoc.createAttributeNS(attr_ns, attr_qname) attr.value = value new_element.setAttributeNodeNS(attr) for (prefix,uri) in self._new_prefix_mappings: if prefix is None : new_element.setAttributeNS(XMLNS_NAMESPACE,'xmlns',uri or '') else: new_element.setAttributeNS(XMLNS_NAMESPACE,'xmlns'+':'+prefix,uri) self._new_prefix_mappings = [] self._nodeStack.append(new_element) return def endElementNS(self, name, qname): self._completeTextNode() new_element = self._nodeStack[-1] del self._nodeStack[-1] if new_element != self._ownerDoc.documentElement: self._nodeStack[-1].appendChild(new_element) return def ignorableWhitespace(self, chars): """ If 'keepAllWs' permits, add ignorable white-space as a text node. A Document node cannot contain text nodes directly. If the white-space occurs outside the root element, there is no place for it in the DOM and it must be discarded. """ if self._keepAllWs and self._nodeStack[-1].nodeType != Node.DOCUMENT_NODE: self._currText = self._currText + chars return def characters(self, chars): self._currText = self._currText + chars return #Overridden LexicalHandler methods def xmlDecl(self, version, encoding, standalone): self._xmlDecl = {'version': version, 'encoding': encoding, 'standalone': standalone} return def startDTD(self, doctype, publicID, systemID): self._dt = self._impl.createDocumentType(doctype, publicID, systemID) if not self._rootNode: self._orphanedNodes.append(('doctype',)) #else: #raise Exception('Illegal DocType declaration') return def comment(self, text): if self._rootNode: self._completeTextNode() new_comment = self._ownerDoc.createComment(text) self._nodeStack[-1].appendChild(new_comment) else: self._orphanedNodes.append(('comment', text)) return def startCDATA(self): self._completeTextNode() return def endCDATA(self): #NOTE: this doesn't handle the error where endCDATA is called #Without corresponding startCDATA. Is this a problem? if self._currText: new_text = self._ownerDoc.createCDATASection(self._currText) self._nodeStack[-1].appendChild(new_text) self._currText = '' return #Overridden DTDHandler methods def notationDecl (self, name, publicId, systemId): new_notation = self._ownerDoc.getFactory().createNotation(self._ownerDoc, publicId, systemId, name) self._ownerDoc.getDocumentType().getNotations().setNamedItem(new_notation) return def unparsedEntityDecl (self, name, publicId, systemId, ndata): if self._ownerDoc: new_notation = self._ownerDoc.getFactory().createEntity(self._ownerDoc, publicId, systemId, name) self._ownerDoc.getDocumentType().getEntities().setNamedItem(new_notation) else: self._orphanedNodes.append(('unparsedentitydecl', name, publicId, systemId, ndata)) return #Overridden ErrorHandler methods #FIXME: How do we handle warnings? def error(self, exception): raise exception def fatalError(self, exception): raise exception class Reader(reader.Reader): def __init__(self, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): self.parser = parser or (validate and sax2exts.XMLValParserFactory.make_parser()) or sax2exts.XMLParserFactory.make_parser() if catName: #set up the catalog, if there is one from xml.parsers.xmlproc import catalog cat_handler = catalog.SAX_catalog( catName, catalog.CatParserFactory() ) self.parser.setEntityResolver(cat_handler) self.handler = saxHandlerClass(keepAllWs) self.parser.setContentHandler(self.handler) self.parser.setDTDHandler(self.handler) self.parser.setErrorHandler(self.handler) try: #FIXME: Maybe raise a warning? self.parser.setProperty(handler.property_lexical_handler, self.handler) self.parser.setProperty(handler.property_declaration_handler, self.handler) except (SystemExit, KeyboardInterrupt): raise except: pass return def fromStream(self, stream, ownerDoc=None): self.handler.initState(ownerDoc=ownerDoc) #self.parser.parseFile(stream) s = saxutils.prepare_input_source(stream) self.parser.parse(s) rt = self.handler.getRootNode() #if hasattr(self.parser.parser,'deref'): # self.parser.parser.deref() #self.parser.parser = None #self.parser = None #self.handler = None return rt ########################## Deprecated ############################## def FromXmlStream(stream, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): reader = Reader(validate, keepAllWs, catName, saxHandlerClass, parser) return reader.fromStream(stream, ownerDocument) def FromXml(text, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): fp = cStringIO.StringIO(text) rv = FromXmlStream(fp, ownerDocument, validate, keepAllWs, catName, saxHandlerClass, parser) return rv def FromXmlFile(fileName, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): fp = open(fileName, 'r') try: rv = FromXmlStream(fp, ownerDocument, validate, keepAllWs, catName, saxHandlerClass, parser) finally: fp.close() return rv def FromXmlUrl(url, ownerDocument=None, validate=0, keepAllWs=0, catName=None, saxHandlerClass=XmlDomGenerator, parser=None): fp = urllib2.urlopen(url) try: rv = FromXmlStream(fp, ownerDocument, validate, keepAllWs, catName, saxHandlerClass, parser) finally: fp.close() return rv PyXML-0.8.2/xml/dom/ext/reader/Sax2Lib.py0100644000076400001440000002014707277501550017163 0ustar martinusers"""A Python translation of the SAX2 parser API. This file provides only default classes with absolutely minimum functionality, from which drivers and applications can be subclassed. Many of these classes are empty and are included only as documentation of the interfaces. """ from xml.sax import saxlib class LexicalHandler: """ Default handler for lexical events Note: All methods can raise SAXException """ handlerId = 'http://xml.org/sax/handlers/lexical' def xmlDecl(self, version, encoding, standalone): """The XML Declaration""" pass def startDTD(self, doctype, publicID, systemID): """Invoked at the beginning of the DOCTYPE declaration""" pass def endDTD(self): """ Invoked after all components of the DOCTYPE declaration, including both internal and external DTD subsets """ pass def startEntity(self, name): """ Note: If an external DTD subset is read, it will invoke this method with special entity name of "[DTD]" """ pass def endEntity(self, name): pass def comment(self, text): """XML Comment""" pass def startCDATA(self): """Beginning of CDATA Section""" pass def endCDATA(self): """End of CDATA Section""" pass class AttributeList2(saxlib. AttributeList): def isSpecified(self, id): """ Whether the attribute value with the given name or index was explicitly specified in the element, or was determined from the default. Parameter can be either integer index or attribute name. None (the default) signals 'Don't Know', else a boolean return """ pass def getEntityRefList(self, id): """ XML 1,0 parsers are required to report all entity references, even if unexpanded. This includes those in attribute strings. Many parsers and apps ignore this, but for full conformance, This method can be called to get a list of indexes referring to entity references within the attribute value string for the given name or index. Parameter can be either integer index or attribute name. """ pass class EntityRefList: """ This is the entity-reference list returned by AttributeList2.getEntityRefList(index) """ def getLength(self): "Return the number of Entity Ref pointers" pass def getEntityName(self, index): "Return the name of the entity reference at the given index" pass def getEntityRefStart(self, index): """ Return the string start position of the entity reference at the given index """ pass def getEntityRefEnd(self, index): """ Return the string end position of the entity reference at the given index """ pass def __len__(self): "Alias for getLength." pass class DTDDeclHandler: """ A handler for a minimal set of DTD Events """ MODEL_ELEMENTS = 1 MODEL_MIXED = 2 MODEL_ANY = 3 MODEL_EMPTY = 4 ATTRIBUTE_DEFAULTED = 1 ATTRIBUTE_IMPLIED = 2 ATTRIBUTE_REQUIRED = 3 ATTRIBUTE_FIXED = 4 handlerId = 'http://xml.org/sax/handlers/dtd-decl' def elementDecl(self, name, modelType, model): """ Report an element-type declaration. name and model are strings, modelType is an enumerated int from 1 to 4 """ pass def attributeDecl(self, element, name, type, defaultValue, defaultType, entityRefs): """ Report an attribute declaration. The first 4 parameters are strings, defaultType is an integer from 1 to 4, entityRefs is an EntityRefList """ pass def externalEntityDecl(self, name, isParameterEntity, publicId, systemId): """ Report an external entity declaration. All parameters are strings except for isParameterEntity, which is 0 or 1 """ pass def internalEntityDecl(self, name, isParameterEntity, value): """ Report an external entity declaration. All parameters are strings except for isParameterEntity, which is 0 or 1 """ pass class NamespaceHandler: """ Receive callbacks for the start and end of the scope of each namespace declaration. """ handlerId = 'http://xml.org/sax/handlers/namespace' def startNamespaceDeclScope(self, prefix, uri): """ Report the start of the scope of a namespace declaration. This event will be reported before the startElement event for the element containing the namespace declaration. All declarations must be properly nested; if there are multiple declarations in a single element, they must end in the opposite order that they began. both parameters are strings """ pass def endNamespaceDeclScope(self, prefix): """ Report the end of the scope of a namespace declaration. This event will be reported after the endElement event for the element containing the namespace declaration. Namespace scopes must be properly nested. """ pass class ModParser(saxlib.Parser): """ All methods may raise SAXNotSupportedException """ def setFeature(self, featureID, state): """ featureId is a string, state a boolean """ pass def setHandler(self, handlerID, handler): """ handlerID is a string, handler a handler instance """ pass def set(self, propID, value): """ propID is a string, value of arbitrary type """ pass def get(self, propID): pass import sys if sys.platform[0:4] == 'java': from exceptions import Exception class SAXNotSupportedException(Exception): """ Indicate that a SAX2 parser interface does not support a particular feature or handler, or property. """ pass #Just a few helper lists with the core components CoreHandlers = [ 'http://xml.org/sax/handlers/lexical', 'http://xml.org/sax/handlers/dtd-decl', 'http://xml.org/sax/handlers/namespace' ] CoreProperties = [ 'http://xml.org/sax/properties/namespace-sep', #write-only string #Set the separator to be used between the URI part of a name and the #local part of a name when namespace processing is being performed #(see the http://xml.org/sax/features/namespaces feature). By #default, the separator is a single space. This property may not be #set while a parse is in progress (raises SAXNotSupportedException). 'http://xml.org/sax/properties/dom-node', #read-only Node instance #Get the DOM node currently being visited, if the SAX parser is #iterating over a DOM tree. If the parser recognises and supports #this property but is not currently visiting a DOM node, it should #return null (this is a good way to check for availability before the #parse begins). 'http://xml.org/sax/properties/xml-string' #read-only string #Get the literal string of characters associated with the current #event. If the parser recognises and supports this property but is #not currently parsing text, it should return null (this is a good #way to check for availability before the parse begins). ] CoreFeatures = [ 'http://xml.org/sax/features/validation', #Validate (1) or don't validate (0). 'http://xml.org/sax/features/external-general-entities', #Expand external general entities (1) or don't expand (0). 'http://xml.org/sax/features/external-parameter-entities', #Expand external parameter entities (1) or don't expand (0). 'http://xml.org/sax/features/namespaces', #Preprocess namespaces (1) or don't preprocess (0). See also #the http://xml.org/sax/properties/namespace-sep property. 'http://xml.org/sax/features/normalize-text' #Ensure that all consecutive text is returned in a single callback to #DocumentHandler.characters or DocumentHandler.ignorableWhitespace #(1) or explicitly do not require it (0). ] PyXML-0.8.2/xml/dom/ext/reader/Sgmlop.py0100644000076400001440000002410607521676037017164 0ustar martinusersimport string, re, types, sys from xml.parsers import sgmlop from xml.dom import implementation from xml.dom import Node from xml.dom import NotSupportedErr from xml.dom import EMPTY_NAMESPACE from xml.dom.html import HTML_DTD, HTML_CHARACTER_ENTITIES DEFAULT_CHARSET = 'ISO-8859-1' _root = '(?P[a-zA-Z][a-zA-Z0-9]*)' _quoted = '("[^"]*")|' + "('[^']*')" _sysId = r'\s*(?P' + _quoted + ')' _pubId = r'\s*PUBLIC\s*(?P' + _quoted + '(' + (_sysId % 1) + ')?)' _sysId = 'SYSTEM' + (_sysId % 2) _doctype = re.compile('DOCTYPE ' + _root + '(%s|%s)?' % (_pubId, _sysId), re.I) try: unicode() except: from xml.unicode.iso8859 import wstring wstring.install_alias('ISO-8859-1', 'ISO_8859-1:1987') def unicode(str, encoding='US-ASCII'): """Create a UTF-8 string""" try: return wstring.decode(string.upper(encoding), str).utf8() except: return str def unichr(char): """Create a UTF-8 string from a Unicode character code""" try: return wstring.chr(char).utf8() except: return char class SgmlopParser: def __init__(self, entities=None): self.entities = {'amp' : '&', 'apos' : "'", 'lt' : '<', 'gt' : '>', 'quot' : '"', } entities and self.entities.update(entities) def initParser(self, parser): self._parser = parser self._parser.register(self) return def initState(self, ownerDoc=None): raise NotImplementError('initState: ownerDoc=%s' % ownerDoc) def parse(self, stream): self._parser.parse(stream.read()) return def handle_special(self, data): """Handles directives""" raise NotImplementedError('handle_special: data=%s' % data) def handle_proc(self, target, data): """Handles processing instructions.""" raise NotImplementedError('handle_proc: target=%s, data=%s' % (target, data)) def finish_starttag(self, tagname, attrs): """ In XML mode attrs is a dictionary, otherwise a list. """ raise NotImplementedError('finish_starttag: name=%s' % tagname) def finish_endtag(self, tagname): raise NotImplementedError('finish_endtag: name=%s' % tagname) def handle_entityref(self, name): if self.entities.has_key(name): self.handle_data(self.entities[name]) else: self.unknown_entityref(name) return #Handled internally in sgmlop, but can be overridden #def handle_charref(self, char): # # char is a string number # # either DDD or xHHH # if char[0] == 'x': # self.handle_data(chr(eval('0' + char))) # else: # self.handle_data(chr(int(char))) # return def handle_cdata(self, data): raise NotImplementedError('handle_cdata: data=%s' % data) def handle_data(self, data): raise NotImplementedError('handle_data: data=%s' % data) def handle_comment(self, data): raise NotImplementedError('handle_comment: data=%s' % data) def unknown_endtag(self, name): pass def unknown_entityref(self, name): pass g_reCharset = re.compile(r'charset\s*=\s*(?P[a-zA-Z0-9_\-]+)') HTML_ENTITIES = {} for (char, name) in HTML_CHARACTER_ENTITIES.items(): HTML_ENTITIES[name] = unichr(char) class HtmlParser(SgmlopParser): def __init__(self): SgmlopParser.__init__(self, HTML_ENTITIES) def initParser(self): SgmlopParser.initParser(self, sgmlop.SGMLParser()) def initState(self, ownerDoc=None, charset=''): self._ownerDoc = ownerDoc or implementation.createHTMLDocument('') self._charset = charset or DEFAULT_CHARSET self.rootNode = self._ownerDoc.createDocumentFragment() self._stack = [self.rootNode] self._hasHtml = 0 return def handle_special(self, data): # This would be a doctype, but HTML DOMs do not use them return def handle_proc(self, target, data): # HTML DOMs do not support processing instructions either. return def finish_starttag(self, tagname, attrs): unicodeTagName = unicode(tagname, self._charset) lowerTagName = string.lower(unicodeTagName) if not HTML_DTD.has_key(lowerTagName): # Skip any tags not defined in HTML 4.01 return element = self._ownerDoc.createElementNS(EMPTY_NAMESPACE, unicodeTagName) # Allows for multiple META tags in a document if lowerTagName == 'meta': lowered = map(lambda (name, value): (string.lower(name), string.lower(value)), attrs) if ('http-equiv', 'content-type') in lowered: for (name, value) in lowered: if name == 'content': match = g_reCharset.search(value) if match: self._charset = match.group('charset') # Add any attributes to the tag for (name, value) in attrs: element.setAttributeNS(EMPTY_NAMESPACE, unicode(name, self._charset), unicode(value, self._charset)) # Look for its parent for i in range(1, len(self._stack)): parent = self._stack[-i] if lowerTagName in HTML_DTD[string.lower(parent.tagName)]: parent.appendChild(element) if i > 1: self._stack = self._stack[:-i+1] if HTML_DTD[lowerTagName]: self._stack.append(element) return # no parent found if not self._hasHtml and lowerTagName == 'html': self._stack[0].appendChild(element) self._stack.append(element) self._hasHtml = 1 return def finish_endtag(self, tagname): uppercase = string.upper(unicode(tagname, self._charset)) # Look for opening tag for i in range(1, len(self._stack)): element = self._stack[-i] if uppercase == element.tagName: self._stack = self._stack[:-i] break return def handle_entityref(self, name): if self.entities.has_key(name): unidata = self.entities[name] node = self._stack[-1] text_node = node.lastChild or node if text_node.nodeType == Node.TEXT_NODE: text_node.appendData(unidata) else: node.appendChild(self._ownerDoc.createTextNode(unidata)) else: self.unknown_entityref(name) return def handle_data(self, data): unidata = unicode(data, self._charset) node = self._stack[-1] text_node = node.lastChild or node if text_node.nodeType == Node.TEXT_NODE: text_node.appendData(unidata) else: node.appendChild(self._ownerDoc.createTextNode(unidata)) return def handle_charref(self, value): # Can't rely on sgmlop to handle charrefs itself: it can't # report Unicode (since it won't know the document encoding), # and it may encounter non-ASCII characters if value[0] == 'x': value = int(value[1:], 16) else: value = int(value) unidata = unichr(value) node = self._stack[-1] text_node = node.lastChild or node if text_node.nodeType == Node.TEXT_NODE: text_node.appendData(unidata) else: node.appendChild(self._ownerDoc.createTextNode(unidata)) return def handle_comment(self, data): comment = self._ownerDoc.createComment(data) self._stack[-1].appendChild(comment) return class XmlParser(SgmlopParser): def initParser(self): SgmlopParser.initParser(self, sgmlop.XMLParser()) def initState(self, ownerDoc=None): self._ownerDoc = None #Set up the stack which keeps track of the nesting of DOM nodes. if ownerDoc: self._ownerDoc = ownerDoc #Create a docfrag to hold all the generated nodes. self._rootNode = self._ownerDoc.createDocumentFragment() self._stack = [self._rootNode] else: self._rootNode = None self._stack = [] self._dt = None self._xmlDecl = None self._orphanedNodes = [] self._namespaces = {'xml': XML_NAMESPACE} self._namespaceStack = [] self._currText = '' return def finish_starttag(self, tagname, attrs): old_nss = {} del_nss = [] split_attrs = {} for (name, value) in attrs.items(): (prefix, local) = SplitQName(name) split_attrs[(prefix, local, name)] = value if local == 'xmlns': if self._namespaces.has_key(prefix): old_nss[prefix] = self._namespaces[prefix] else: del_nss.append(prefix) if prefix or value: self._namespaces[prefix] = value else: del_nss.append(prefix) self._namespaceStack.append((old_nss, del_nss)) (prefix, local) = SplitQName(tagname) namespace = self._namespaces.get(prefix, None) element = self._ownerDoc.createElementNS(namespace, tagname) for ((prefix, local, name), value) in split_attrs.items(): if local == 'xmlns': namespace = XMLNS_NAMESPACE else: namespace = self._namespaces.get(prefix, None) attr = self._ownerDoc.createAttributeNS(namespace, name) attr.value = value element.setAttributeNodeNS(attr) self._stack.append(element) def finish_endtag(self, tagname): element = self._stack.pop() (old_nss, del_nss) = self._namespaceStack.pop() self._namespaces.update(old_nss) for prefix in del_nss: del self._namespaces[prefix] self._stack[-1].appendChild(element) return PyXML-0.8.2/xml/dom/ext/reader/__init__.py0100644000076400001440000000435707534565153017470 0ustar martinusers######################################################################## # # File Name: __init__.py # # Documentation: http://docs.4suite.org/4DOM/ext/reader/__init__.py.html # """ The 4DOM reader module has routines for deserializing XML and HTML to DOM WWW: http://4suite.org/4DOM e-mail: support@4suite.org Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import string, urllib2, urlparse, cStringIO, os from xml.dom.ext import ReleaseNode try: import codecs from types import UnicodeType encoder = codecs.lookup("utf-8")[0] # encode,decode,reader,writer def StrStream(st): if type(st) is UnicodeType: st = encoder(st)[0] return cStringIO.StringIO(st) except ImportError: StrStream = lambda x: cStringIO.StringIO(x) class BaseUriResolver: def resolve(self, uri, base=''): #scheme, netloc, path, params, query, fragment scheme = urlparse.urlparse(uri)[0] if scheme in ['', 'http', 'ftp', 'file', 'gopher']: uri = urlparse.urljoin(base, uri) if os.access(uri, os.F_OK): #Hack because urllib breaks on Windows paths stream = open(uri) else: stream = urllib2.urlopen(uri) return stream BASIC_RESOLVER = BaseUriResolver() class Reader: def clone(self): """Used to create a new copy of this instance""" if hasattr(self,'__getinitargs__'): return apply(self.__class__,self.__getinitargs__()) else: return self.__class__() def fromStream(self, stream, ownerDoc=None): """Create a DOM from a stream""" raise "NOT OVERIDDEN" def fromString(self, str, ownerDoc=None): """Create a DOM from a string""" stream = StrStream(str) try: return self.fromStream(stream, ownerDoc) finally: stream.close() def fromUri(self, uri, ownerDoc=None): stream = BASIC_RESOLVER.resolve(uri) try: return self.fromStream(stream, ownerDoc) finally: stream.close() def releaseNode(self, node): "Free a DOM tree" node and ReleaseNode(node) PyXML-0.8.2/xml/dom/ext/Dom2Sax.py0100644000076400001440000002545607507520270015736 0ustar martinusers""" parser to generate SAX events from a DOM tree $Date: 2025/05/02 10:15:04 $ by $Author: loewis $ """ from xml.sax._exceptions import SAXNotSupportedException, SAXNotRecognizedException from xml.sax.xmlreader import XMLReader, AttributesNSImpl, AttributesImpl from xml.sax.saxlib import LexicalHandler, DeclHandler from xml.sax import handler from xml.dom import Node, XMLNS_NAMESPACE XMLNS_NS = XMLNS_NAMESPACE class Dom2SaxParser(XMLReader): """ Generate SAX events from a DOM tree handle _ feature_namespaces _ feature_namespace_prefixes, _ property_lexical_handler _ property_declaration_handler (not yet fully) differences with standard sax parser: _ no error handling (we start from a dom tree !!) _ no locator (same reason) """ def __init__(self): XMLReader.__init__(self) self._lex_handler = LexicalHandler() self._decl_handler = DeclHandler() self._ns = 0 self._ns_prfx = 1 self._parsing = 0 ## properties and features ################################################## def getFeature(self, name): if name == handler.feature_namespaces: return self._ns elif name == handler.feature_namespace_prefixes: return self._ns_prfx raise SAXNotRecognizedException("Feature '%s' not recognized"%name) def setFeature(self, name, state): if self._parsing: raise SAXNotSupportedException("Cannot set features while parsing") if name == handler.feature_namespaces: self._ns = state elif name == handler.feature_namespace_prefixes: self._ns_prfx = state else: raise SAXNotRecognizedException("Feature '%s' not recognized"%name) def getProperty(self, name): if name == handler.property_lexical_handler: return self._lex_handler_prop if name == handler.property_declaration_handler: return self._decl_handler_prop raise SAXNotRecognizedException("Property '%s' not recognized"%name) def setProperty(self, name, value): if self._parsing: raise SAXNotSupportedException("Cannot set properties while parsing") if name == handler.property_lexical_handler: self._lex_handler = value elif name == handler.property_declaration_handler: self._decl_handler = value else: raise SAXNotRecognizedException("Property '%s' not recognized"%name) ## parsing ################################################################ def parse(self, dom): if self._parsing: raise SAXNotSupportedException("Ask for parse while parsing") self._parsing = 1 if self._ns: self._element_ = self._element_ns else: self._element_ = self._element self._from_dom(dom) self._parsing = 0 ## private ################################################################# def _from_dom(self, n): while n: type = n.nodeType if type == Node.ELEMENT_NODE: self._element_(n) elif type == Node.TEXT_NODE: self._cont_handler.characters(n.data) elif type == Node.PROCESSING_INSTRUCTION_NODE: self._cont_handler.processingInstruction(n.target, n.data) elif type == Node.DOCUMENT_NODE: self._cont_handler.startDocument() self._from_dom(n.firstChild) self._cont_handler.endDocument() elif type == Node.DOCUMENT_FRAGMENT_NODE: for n in n.childNodes: self._cont_handler.startDocument() self._from_dom(n.firstChild) self._cont_handler.endDocument() elif type == Node.CDATA_SECTION_NODE: self._lex_handler.startCDATA() self._cont_handler.characters(n.data) self._lex_handler.endCDATA() elif type == Node.COMMENT_NODE: self._lex_handler.comment(n.data) elif type == Node.DOCUMENT_TYPE_NODE: self._lex_handler.startDTD(n.name, n.publicId, n.systemId) for i in range(n.entities.length): e = n.entities.item(i) if e.publicId or e.systemId: self._decl_handler.externalEntityDecl( e.notationName, e.publicId, e.systemId) else: self._decl_handler.externalEntityDecl( e.name, e.value) self._lex_handler.endDTD() elif type == Node.ENTITY_REFERENCE_NODE: self._lex_handler.startEntity(n.nodeName) self._from_dom(n.firstChild) self._lex_handler.endEntity(n.nodeName) #elif type == Node.ENTITY_NODE: #elif type == Node.NOTATION_NODE: n = n.nextSibling def _element(self, n): """ handle an ElementNode without NS interface""" ## convert DOM namedNodeMap to SAX attributes nnm = n.attributes attrs = {} for a in nnm.values(): attrs[a.nodeName] = a.value ## handle element name = n.nodeName self._cont_handler.startElement(name, AttributesImpl(attrs)) self._from_dom(n.firstChild) self._cont_handler.endElement(name) def _element_ns(self, n): """ handle an ElementNode with NS interface""" ## convert DOM namedNodeMap to SAX attributes NS prefix_list = [] nnm = n.attributes attrs, qnames = {}, {} for a in nnm.values(): a_uri = a.namespaceURI if a_uri == XMLNS_NS: prefix, val = a.localName, a.value self._cont_handler.startPrefixMapping(prefix, val) prefix_list.append(prefix) if self._ns_prfx: name = (a_uri, prefix) attrs[name] = val qnames[name] = a.nodeName else: name = (a_uri, a.localName) attrs[name] = a.value qnames[name] = a.nodeName ## handle element NS name = (n.namespaceURI, n.localName) self._cont_handler.startElementNS(name, n.nodeName, AttributesNSImpl(attrs, qnames)) self._from_dom(n.firstChild) self._cont_handler.endElementNS(name, n.nodeName) prefix_list.reverse() map(self._cont_handler.endPrefixMapping, prefix_list) ## full sax handler, print each event to output ################################ class PrintSaxHandler: ## content handler ######################################################### def setDocumentLocator(self, locator): print 'setDocumentLocator', locator def startDocument(self): print 'startDocument' def endDocument(self): print 'endDocument' def startElement(self, name, attrs): print 'startElement', name for key, val in attrs.items(): print 'attribute', key, val def endElement (self, name): print 'endElement', name def startElementNS(self, name, qname, attrs): print 'startElementNS', name, qname for key, val in attrs.items(): print 'attribute', key, val def endElementNS (self, name, qname): print 'endElementNS', name, qname def startPrefixMapping(self, prefix, uri): print 'startPrefixMapping', prefix, uri def endPrefixMapping(self, prefix): print 'endPrefixMapping', prefix def processingInstruction(self, target, data): print 'processingInstruction', target, data def ignorableWhitespace(self, whitespace): print 'ignorableWhitespace', whitespace def characters(self, ch): print 'characters', ch.encode('iso-8859-15') ## lexical handler ######################################################### def xmlDecl(self, version, encoding, standalone): print 'xmlDecl', version, encoding, standalone def comment(self, machin): print 'comment', machin.encode('UTF-8') def startEntity(self, name): print 'startEntity', name def endEntity(self, name): print 'endEntity', name def startCDATA(self): print 'startCDATA' def endCDATA(self): print 'endCDATA' def startDTD(self, name, public_id, system_id): print 'startDTD', name, public_id, system_id def endDTD(self): print 'endDTD' ## DTD decl handler ######################################################## def attributeDecl(self, elem_name, attr_name, type, value_def, value): print 'attributeDecl', elem_name, attr_name, type, value_def, value def elementDecl(self, elem_name, content_model): print 'elementDecl', elem_name, content_model def internalEntityDecl(self, name, value): print 'internalEntityDecl', name, value.encode('UTF-8') def externalEntityDecl(self, name, public_id, system_id): print 'externalEntityDecl', name, public_id, system_id # Test ######################################################################## def _parse(parser, doc, features, properties): import time h = PrintSaxHandler() parser.setContentHandler(h) print '-'*80 print parser.__class__ print for f,val in features: try: parser.setFeature(f, val) print f, val except Exception, e: print e for p, val in properties: try: if val: parser.setProperty(p, h) print p,val except Exception, e: print e print '*'*80 t = time.time() parser.parse(doc) print '*'*80 print 'TEMPS:', time.time() - t print if __name__ == '__main__': import sys from xml.sax import make_parser from xml.dom.ext.reader import Sax2 from xml.dom.ext import PrettyPrint from xml.sax.handler import feature_namespaces,\ feature_namespace_prefixes, property_lexical_handler,\ property_declaration_handler f1 = feature_namespaces f2 = feature_namespace_prefixes p1 = property_lexical_handler p2 = property_declaration_handler file = sys.argv[1] r = Sax2.Reader() f = open(file) doc = r.fromStream(f) print 'Initial document', doc, doc.__class__ PrettyPrint(doc) for (val1,val2,val3,val4) in ((0,0,0,0),(0,1,1,1),(1,0,0,0),(1,1,1,1)): for p,d in ((Dom2SaxParser(), doc), (make_parser(['xml.sax.drivers2.drv_pyexpat']), f), (make_parser(['xml.sax.drivers2.drv_xmlproc']), f)): if not d is doc: d = open(file) _parse(p, d, ((f1, val1), (f2,val2)), ((p1,val3),(p2,val4))) f.close() PyXML-0.8.2/xml/dom/ext/Printer.py0100644000076400001440000003311707534565153016106 0ustar martinusers######################################################################## # # File Name: Printer.py # # Documentation: http://docs.4suite.com/4DOM/Printer.py.html # """ The printing sub-system. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string, re from xml.dom import Node from xml.dom.ext.Visitor import Visitor, WalkerInterface from xml.dom import ext, XMLNS_NAMESPACE, XML_NAMESPACE, XHTML_NAMESPACE from xml.dom.html import TranslateHtmlCdata from xml.dom.html import HTML_4_TRANSITIONAL_INLINE from xml.dom.html import HTML_FORBIDDEN_END from xml.dom.html import HTML_BOOLEAN_ATTRS ILLEGAL_LOW_CHARS = '[\x01-\x08\x0B-\x0C\x0E-\x1F]' SURROGATE_BLOCK = '[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]' ILLEGAL_HIGH_CHARS = '\xEF\xBF[\xBE\xBF]' #Note: Prolly fuzzy on this, but it looks as if characters from the surrogate block are allowed if in scalar form, which is encoded in UTF8 the same was as in surrogate block form XML_ILLEGAL_CHAR_PATTERN = re.compile('%s|%s'%(ILLEGAL_LOW_CHARS, ILLEGAL_HIGH_CHARS)) g_utf8TwoBytePattern = re.compile('([\xC0-\xC3])([\x80-\xBF])') g_cdataCharPattern = re.compile('[&<]|]]>') g_charToEntity = { '&': '&', '<': '<', ']]>': ']]>', } try: #The following stanza courtesy Martin von Loewis import codecs # Python 1.6+ only from types import UnicodeType def utf8_to_code(text, encoding): encoder = codecs.lookup(encoding)[0] # encode,decode,reader,writer if type(text) is not UnicodeType: text = unicode(text, "utf-8") return encoder(text)[0] # result,size def strobj_to_utf8str(text, encoding): if string.upper(encoding) not in ["UTF-8", "ISO-8859-1", "LATIN-1"]: raise ValueError("Invalid encoding: %s"%encoding) encoder = codecs.lookup(encoding)[0] # encode,decode,reader,writer if type(text) is not UnicodeType: text = unicode(text, "utf-8") #FIXME return str(encoder(text)[0]) except ImportError: def utf8_to_code(text, encoding): encoding = string.upper(encoding) if encoding == 'UTF-8': return text from xml.unicode.iso8859 import wstring wstring.install_alias('ISO-8859-1', 'ISO_8859-1:1987') #Note: Pass through to wstrop. This means we don't play nice and #Escape characters that are not in the target encoding. ws = wstring.from_utf8(text) text = ws.encode(encoding) #This version would skip all untranslatable chars: see wstrop.c #text = ws.encode(encoding, 1) return text strobj_to_utf8str = utf8_to_code def TranslateCdataAttr(characters): '''Handles normalization and some intelligence about quoting''' if not characters: return '', "'" if "'" in characters: delimiter = '"' new_chars = re.sub('"', '"', characters) else: delimiter = "'" new_chars = re.sub("'", ''', characters) #FIXME: There's more to normalization #Convert attribute new-lines to character entity # characters is possibly shorter than new_chars (no entities) if "\n" in characters: new_chars = re.sub('\n', ' ', new_chars) return new_chars, delimiter #Note: Unicode object only for now def TranslateCdata(characters, encoding='UTF-8', prev_chars='', markupSafe=0, charsetHandler=utf8_to_code): """ charsetHandler is a function that takes a string or unicode object as the first argument, representing the string to be procesed, and an encoding specifier as the second argument. It must return a string or unicode object """ if not characters: return '' if not markupSafe: if g_cdataCharPattern.search(characters): new_string = g_cdataCharPattern.subn( lambda m, d=g_charToEntity: d[m.group()], characters)[0] else: new_string = characters if prev_chars[-2:] == ']]' and characters[0] == '>': new_string = '>' + new_string[1:] else: new_string = characters #Note: use decimal char entity rep because some browsers are broken #FIXME: This will bomb for high characters. Should, for instance, detect #The UTF-8 for 0xFFFE and put out ￾ if XML_ILLEGAL_CHAR_PATTERN.search(new_string): new_string = XML_ILLEGAL_CHAR_PATTERN.subn( lambda m: '&#%i;' % ord(m.group()), new_string)[0] new_string = charsetHandler(new_string, encoding) return new_string class PrintVisitor(Visitor): def __init__(self, stream, encoding, indent='', plainElements=None, nsHints=None, isXhtml=0, force8bit=0): self.stream = stream self.encoding = encoding # Namespaces self._namespaces = [{}] self._nsHints = nsHints or {} # PrettyPrint self._indent = indent self._depth = 0 self._inText = 0 self._plainElements = plainElements or [] # HTML support self._html = None self._isXhtml = isXhtml self.force8bit = force8bit return def _write(self, text): if self.force8bit: obj = strobj_to_utf8str(text, self.encoding) else: obj = utf8_to_code(text, self.encoding) self.stream.write(obj) return def _tryIndent(self): if not self._inText and self._indent: self._write('\n' + self._indent*self._depth) return def visit(self, node): if self._html is None: # Set HTMLDocument flag here for speed self._html = hasattr(node.ownerDocument, 'getElementsByName') nodeType = node.nodeType if node.nodeType == Node.ELEMENT_NODE: return self.visitElement(node) elif node.nodeType == Node.ATTRIBUTE_NODE: return self.visitAttr(node) elif node.nodeType == Node.TEXT_NODE: return self.visitText(node) elif node.nodeType == Node.CDATA_SECTION_NODE: return self.visitCDATASection(node) elif node.nodeType == Node.ENTITY_REFERENCE_NODE: return self.visitEntityReference(node) elif node.nodeType == Node.ENTITY_NODE: return self.visitEntity(node) elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: return self.visitProcessingInstruction(node) elif node.nodeType == Node.COMMENT_NODE: return self.visitComment(node) elif node.nodeType == Node.DOCUMENT_NODE: return self.visitDocument(node) elif node.nodeType == Node.DOCUMENT_TYPE_NODE: return self.visitDocumentType(node) elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE: return self.visitDocumentFragment(node) elif node.nodeType == Node.NOTATION_NODE: return self.visitNotation(node) # It has a node type, but we don't know how to handle it raise Exception("Unknown node type: %s" % repr(node)) def visitNodeList(self, node, exclude=None): for curr in node: curr is not exclude and self.visit(curr) return def visitNamedNodeMap(self, node): for item in node.values(): self.visit(item) return def visitAttr(self, node): if node.namespaceURI == XMLNS_NAMESPACE: # Skip namespace declarations return self._write(' ' + node.name) value = node.value if value or not self._html: text = TranslateCdata(value, self.encoding) text, delimiter = TranslateCdataAttr(text) self.stream.write("=%s%s%s" % (delimiter, text, delimiter)) return def visitProlog(self): self._write("" % ( self.encoding or 'utf-8' )) self._inText = 0 return def visitDocument(self, node): not self._html and self.visitProlog() node.doctype and self.visitDocumentType(node.doctype) self.visitNodeList(node.childNodes, exclude=node.doctype) return def visitDocumentFragment(self, node): self.visitNodeList(node.childNodes) return def visitElement(self, node): self._namespaces.append(self._namespaces[-1].copy()) inline = node.tagName in self._plainElements not inline and self._tryIndent() self._write('<%s' % node.tagName) if self._isXhtml or not self._html: namespaces = '' if self._isXhtml: nss = {'xml': XML_NAMESPACE, None: XHTML_NAMESPACE} else: nss = ext.GetAllNs(node) if self._nsHints: self._nsHints.update(nss) nss = self._nsHints self._nsHints = {} del nss['xml'] for prefix in nss.keys(): if not self._namespaces[-1].has_key(prefix) or self._namespaces[-1][prefix] != nss[prefix]: nsuri, delimiter = TranslateCdataAttr(nss[prefix]) if prefix: xmlns = " xmlns:%s=%s%s%s" % (prefix, delimiter,nsuri,delimiter) else: xmlns = " xmlns=%s%s%s" % (delimiter,nsuri,delimiter) namespaces = namespaces + xmlns self._namespaces[-1][prefix] = nss[prefix] self._write(namespaces) for attr in node.attributes.values(): self.visitAttr(attr) if len(node.childNodes): self._write('>') self._depth = self._depth + 1 self.visitNodeList(node.childNodes) self._depth = self._depth - 1 if not self._html or (node.tagName not in HTML_FORBIDDEN_END): not (self._inText and inline) and self._tryIndent() self._write('' % node.tagName) elif not self._html: self._write('/>') elif node.tagName not in HTML_FORBIDDEN_END: self._write('>' % node.tagName) else: self._write('>') del self._namespaces[-1] self._inText = 0 return def visitText(self, node): text = node.data if self._indent: text = string.strip(text) and text if text: if self._html: text = TranslateHtmlCdata(text, self.encoding) else: text = TranslateCdata(text, self.encoding) self.stream.write(text) self._inText = 1 return def visitDocumentType(self, doctype): if not doctype.systemId and not doctype.publicId: return self._tryIndent() self._write(' | | | # [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] public = "'%s'" % doctype.publicId else: public = '"%s"' % doctype.publicId if doctype.publicId and doctype.systemId: self._write(' PUBLIC %s %s' % (public, system)) elif doctype.systemId: self._write(' SYSTEM %s' % system) if doctype.entities or doctype.notations: self._write(' [') self._depth = self._depth + 1 self.visitNamedNodeMap(doctype.entities) self.visitNamedNodeMap(doctype.notations) self._depth = self._depth - 1 self._tryIndent() self._write(']>') else: self._write('>') self._inText = 0 return def visitEntity(self, node): """Visited from a NamedNodeMap in DocumentType""" self._tryIndent() self._write('') return def visitNotation(self, node): """Visited from a NamedNodeMap in DocumentType""" self._tryIndent() self._write('') return def visitCDATASection(self, node): self._tryIndent() self._write('' % (node.data)) self._inText = 0 return def visitComment(self, node): self._tryIndent() self._write('' % (node.data)) self._inText = 0 return def visitEntityReference(self, node): self._write('&%s;' % node.nodeName) self._inText = 1 return def visitProcessingInstruction(self, node): self._tryIndent() self._write('' % (node.target, node.data)) self._inText = 0 return class PrintWalker(WalkerInterface): def __init__(self, visitor, startNode): WalkerInterface.__init__(self, visitor) self.start_node = startNode return def step(self): """There is really no step to printing. It prints the whole thing""" self.visitor.visit(self.start_node) return def run(self): return self.step() PyXML-0.8.2/xml/dom/ext/Visitor.py0100644000076400001440000000455407253474633016125 0ustar martinusers######################################################################## # # File Name: Visitor.py # # Documentation: http://docs.4suite.com/4DOM/Visitor.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ class Visitor: def visit(self, node): """Default behavior for the visitor is simply to print an informational message""" print "Visiting %s node %s\n"%(node.nodeType, node.nodeName) return None class WalkerInterface: def __init__(self, visitor): self.visitor = visitor pass def step(self): """Advance to the next item in order, visit, and then pause""" pass def run(self): """Continue advancing from the current position through the last leaf node without pausing.""" pass class PreOrderWalker(WalkerInterface): def __init__(self, visitor, startNode): WalkerInterface.__init__(self, visitor) self.node_stack = [] self.node_stack.append(startNode) def step(self): """ Visits the current node, and then advances to its first child, if any, else the next sibling. returns a tuple completed, ret_val completed -- flags whether or not we've traversed the entire tree ret_val -- return value from the visitor """ completed = 0 ret_val = self.visitor.visit(self.node_stack[-1]) if (self.node_stack[-1].hasChildNodes()): self.node_stack.append(self.node_stack[-1].firstChild) else: #Back-track until we can find a node with an unprocessed sibling next_sib = None while not next_sib and not completed: next_sib = self.node_stack[-1].nextSibling del self.node_stack[-1] if next_sib: self.node_stack.append(next_sib) else: if not len(self.node_stack): completed = 1 return completed, ret_val def run(self): completed = 0 while not completed: completed, ret_val = self.step() #Set the default Walker class to the PreOrderWalker. #User can change this according to preferences Walker = PreOrderWalker PyXML-0.8.2/xml/dom/ext/XHtml2HtmlPrinter.py0100644000076400001440000000306007307246400017751 0ustar martinusersimport string import Printer from xml.dom import XHTML_NAMESPACE from xml.dom.html import HTML_FORBIDDEN_END class HtmlDocType: name = 'HTML' publicId = "-//W3C//DTD HTML 4.0//EN" systemId = "http://www.w3.org/TR/REC-html40/strict.dtd" entities = notations = [] class HtmlAttr: def __init__(self, node): self.namespaceURI = None self.name = string.upper(node.localName or node.nodeName) self.value = node.value return class HtmlElement: def __init__(self, node): self.tagName = string.upper(node.localName or node.nodeName) self.childNodes = node.childNodes self.attributes = node.attributes return class XHtml2HtmlPrintVisitor(Printer.PrintVisitor): def __init__(self, stream, encoding, indent='', plainElements=None): Printer.PrintVisitor.__init__(self,stream,encoding,indent,plainElements) self._html = 1 return def visitDocument(self, doc): self.visitDocumentType(HtmlDocType) self.visitNodeList(doc.childNodes, exclude=doc.doctype) return def visitAttr(self, node): if node.namespaceURI and node.namespaceURI != XHTML_NAMESPACE: return Printer.PrintVisitor.visitAttr(self,HtmlAttr(node)) def visitElement(self, node): if node.namespaceURI and node.namespaceURI != XHTML_NAMESPACE: return htmlElement = HtmlElement(node) if htmlElement.tagName == 'XHTML': htmlElement.tagName = 'HTML' Printer.PrintVisitor.visitElement(self,htmlElement) PyXML-0.8.2/xml/dom/ext/XHtmlPrinter.py0100644000076400001440000000314207253474633017056 0ustar martinusersimport string import Printer from xml.dom import XHTML_NAMESPACE # Wrapper classes to convert nodes from HTML to XHTML class XHtmlDocType: def __init__(self, doctype): self.name = 'html' self.publicId = "-//W3C//DTD XHTML 1.0 Strict//EN" self.systemId = "DTD/xhtml1-strict.dtd" self.entities = doctype and doctype.entities or [] self.notations = doctype and doctype.notation or [] return class XHtmlAttr: def __init__(self, node): self.namespaceURI = XHTML_NAMESPACE self.name = string.lower(node.name) self.node = node return def __getattr__(self, key): return getattr(self.node, key) class XHtmlElement: def __init__(self, node): self.tagName = string.lower(node.tagName) self.node = node return def __getattr__(self, key): return getattr(self.node, key) class XHtmlPrintVisitor(Printer.PrintVisitor): def __init__(self, stream, encoding, indent): xhtml = {None: 'http://www.w3.org/1999/xhtml'} Printer.PrintVisitor.__init__(self, stream, encoding, indent, nsHints=xhtml) self._html = 0 return def visitDocument(self,node): self.visitProlog() self._tryIndent() self.visitDocumentType(XHtmlDocType(node.doctype)) self.visitNodeList(node.childNodes, exclude=node.doctype) return def visitAttr(self, node): Printer.PrintVisitor.visitAttr(self, XHtmlAttr(node)) return def visitElement(self, node): Printer.PrintVisitor.visitElement(self, XHtmlElement(node)) return PyXML-0.8.2/xml/dom/ext/__init__.py0100644000076400001440000002367307413602170016213 0ustar martinusers######################################################################## # # File Name: __init__.py # # Documentation: http://docs.4suite.com/4DOM/__init__.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ """Some Helper functions: 4DOM/PyXML-specific Extensions to the DOM, and DOM-related utilities.""" import sys,string from xml.dom import Node from xml.dom.NodeFilter import NodeFilter from xml.dom import XML_NAMESPACE, XMLNS_NAMESPACE, DOMException from xml.dom.html import HTML_4_TRANSITIONAL_INLINE from c14n import Canonicalize import re import types if (sys.hexversion >> 8) > 0x10502: IsDOMString = lambda s: type(s) in [types.StringType, types.UnicodeType] else: IsDOMString = lambda s: type(s) == types.StringType class FtDomException(DOMException): def __init__(self, *args): apply(DOMException.__init__,(self,)+ args) return NodeTypeDict = { Node.ELEMENT_NODE : "Element", Node.ATTRIBUTE_NODE : "Attr", Node.TEXT_NODE : "Text", Node.CDATA_SECTION_NODE : "CDATASection", Node.ENTITY_REFERENCE_NODE : "EntityReference", Node.ENTITY_NODE : "Entity", Node.PROCESSING_INSTRUCTION_NODE : "ProcessingInstruction", Node.COMMENT_NODE : "Comment", Node.DOCUMENT_NODE : "Document", Node.DOCUMENT_TYPE_NODE : "DocumentType", Node.DOCUMENT_FRAGMENT_NODE : "DocumentFragment", Node.NOTATION_NODE : "Notation" } def NodeTypeToClassName(nodeType): return NodeTypeDict[nodeType] def Print(root, stream=sys.stdout, encoding='UTF-8'): if not hasattr(root, "nodeType"): return from xml.dom.ext import Printer nss = SeekNss(root) visitor = Printer.PrintVisitor(stream, encoding, nsHints=nss) Printer.PrintWalker(visitor, root).run() return def PrettyPrint(root, stream=sys.stdout, encoding='UTF-8', indent=' ', preserveElements=None): if not hasattr(root, "nodeType"): return from xml.dom.ext import Printer nss_hints = SeekNss(root) preserveElements = preserveElements or [] owner_doc = root.ownerDocument or root if hasattr(owner_doc, 'getElementsByName'): #We don't want to insert any whitespace into HTML inline elements preserveElements = preserveElements + HTML_4_TRANSITIONAL_INLINE visitor = Printer.PrintVisitor(stream, encoding, indent, preserveElements, nss_hints) Printer.PrintWalker(visitor, root).run() stream.write('\n') return def XHtmlPrettyPrint(root, stream=sys.stdout, encoding='UTF-8', indent=' '): if not hasattr(root, "nodeType"): return from xml.dom.ext import XHtmlPrinter visitor = XHtmlPrinter.XHtmlPrintVisitor(stream, encoding, indent) Printer.PrintWalker(visitor, root).run() stream.write('\n') return def XHtmlPrint(root, stream=sys.stdout, encoding='UTF-8'): XHtmlPrettyPrint(root, stream, encoding, '') def ReleaseNode(node): cn = node.childNodes[:] for child in cn: if child.nodeType == Node.ELEMENT_NODE: ReleaseNode(child) node.removeChild(child) if node.nodeType == Node.ELEMENT_NODE: for ctr in range(node.attributes.length): attr = node.attributes.item(0) node.removeAttributeNode(attr) ReleaseNode(attr) def StripHtml(startNode, preserveElements=None): ''' Remove all text nodes in a given tree that do not have at least one non-whitespace character, taking into account special HTML elements ''' preserveElements = preserveElements or [] preserveElements = preserveElements + HTML_4_TRANSITIONAL_INLINE remove_list = [] owner_doc = startNode.ownerDocument or startNode snit = owner_doc.createNodeIterator(startNode, NodeFilter.SHOW_TEXT, None, 0) curr_node = snit.nextNode() while curr_node: #first of all make sure it is not inside one of the preserve_elements ancestor = curr_node while ancestor != startNode: if ancestor.nodeType == Node.ELEMENT_NODE: if ancestor.nodeName in preserveElements: break ancestor = ancestor.parentNode else: if not string.strip(curr_node.data): remove_list.append(curr_node) ancestor = ancestor.parentNode curr_node = snit.nextNode() for node_to_remove in remove_list: node_to_remove.parentNode.removeChild(node_to_remove) return startNode def StripXml(startNode, preserveElements=None): ''' Remove all text nodes in a given tree that do not have at least one non-whitespace character, taking into account xml:space ''' preserveElements = preserveElements or [] remove_list = [] owner_doc = startNode.ownerDocument or startNode snit = owner_doc.createNodeIterator(startNode, NodeFilter.SHOW_TEXT, None, 0) curr_node = snit.nextNode() while curr_node: #first of all make sure it is not inside xml:space='preserve' if XmlSpaceState(curr_node) != 'preserve': if not string.strip(curr_node.data): #also make sure it is not inside one of the preserve elements ancestor = curr_node while ancestor != startNode: if ancestor.nodeType == Node.ELEMENT_NODE: if ancestor.localName in preserveElements or (ancestor.namespaceURI, ancestor.localName) in preserveElements: break ancestor = ancestor.parentNode else: remove_list.append(curr_node) ancestor = ancestor.parentNode curr_node = snit.nextNode() for node_to_remove in remove_list: node_to_remove.parentNode.removeChild(node_to_remove) return startNode _id_key = ('', 'ID') def GetElementById(startNode, targetId): ''' Return the element in the given tree with an ID attribute of the given value ''' owner_doc = startNode.ownerDocument or startNode snit = owner_doc.createNodeIterator(startNode, NodeFilter.SHOW_ELEMENT, None, 0) curr_node = snit.nextNode() while curr_node: attr = curr_node.attributes.get(_id_key, None) if attr and attr._get_nodeValue() == targetId: return curr_node curr_node = snit.nextNode() return None def XmlSpaceState(node): ''' Return the valid value of the xml:space attribute currently in effect ''' valid_values = ['', 'preserve', 'default'] xml_space_found = 0 root_reached = 0 xml_space_state = '' while not(xml_space_state or root_reached): if node.nodeType == Node.ELEMENT_NODE: xml_space_state = node.getAttributeNS(XML_NAMESPACE, 'space') if xml_space_state not in valid_values: xml_space_state = '' parent_node = node.parentNode if not (parent_node and parent_node.nodeType == Node.ELEMENT_NODE): root_reached = 1 node = parent_node return xml_space_state def GetAllNs(node): #The xml namespace is implicit nss = {'xml': XML_NAMESPACE} if node.nodeType == Node.ATTRIBUTE_NODE and node.ownerElement: return GetAllNs(node.ownerElement) if node.nodeType == Node.ELEMENT_NODE: if node.namespaceURI: nss[node.prefix] = node.namespaceURI for attr in node.attributes.values(): if attr.namespaceURI == XMLNS_NAMESPACE: if attr.localName == 'xmlns': nss[None] = attr.value else: nss[attr.localName] = attr.value elif attr.namespaceURI: nss[attr.prefix] = attr.namespaceURI if node.parentNode: #Inner NS/Prefix mappings take precedence over outer ones parent_nss = GetAllNs(node.parentNode) parent_nss.update(nss) nss = parent_nss return nss #FIXME: this dict is a small memory leak: a splay tree that rotates out #out of the tree would be perfect. #g_splitNames = {} def SplitQName(qname): """ Input a QName according to XML Namespaces 1.0 http://www.w3.org/TR/REC-xml-names Return the name parts according to the spec In the case of namespace declarations the tuple returned is (prefix, 'xmlns') Note that this won't hurt users since prefixes and local parts starting with "xml" are reserved, but it makes ns-aware builders easier to write """ #sName = g_splitNames.get(qname) sName = None if sName == None: fields = string.splitfields(qname, ':') if len(fields) == 1: #Note: we could gain a tad more performance by interning 'xmlns' if qname == 'xmlns': sName = (None, 'xmlns') else: sName = (None, qname) elif len(fields) == 2: if fields[0] == 'xmlns': sName = (fields[1], 'xmlns') else: sName = (fields[0], fields[1]) else: sname = (None, None) #g_splitNames[qname] = sName return sName def SeekNss(node, nss=None): '''traverses the tree to seek an approximate set of defined namespaces''' nss = nss or {} for child in node.childNodes: if child.nodeType == Node.ELEMENT_NODE: if child.namespaceURI: nss[child.prefix] = child.namespaceURI for attr in child.attributes.values(): if attr.namespaceURI == XMLNS_NAMESPACE: if attr.localName == 'xmlns': nss[None] = attr.value else: nss[attr.localName] = attr.value elif attr.namespaceURI: nss[attr.prefix] = attr.namespaceURI SeekNss(child, nss) return nss PyXML-0.8.2/xml/dom/ext/c14n.py0100644000076400001440000003157707614725771015243 0ustar martinusers#! /usr/bin/env python '''XML Canonicalization This module generates canonical XML of a document or element. http://www.w3.org/TR/2001/REC-xml-c14n-20010315 and includes a prototype of exclusive canonicalization http://www.w3.org/Signature/Drafts/xml-exc-c14n Requires PyXML 0.7.0 or later. Known issues if using Ft.Lib.pDomlette: 1. Unicode 2. does not white space normalize attributes of type NMTOKEN and ID? 3. seems to be include "\n" after importing external entities? Note, this version processes a DOM tree, and consequently it processes namespace nodes as attributes, not from a node's namespace axis. This permits simple document and element canonicalization without XPath. When XPath is used, the XPath result node list is passed and used to determine if the node is in the XPath result list, but little else. Authors: "Joseph M. Reagle Jr." "Rich Salz" $Date: 2025/01/25 11:41:21 $ by $Author: loewis $ ''' _copyright = '''Copyright 2001, Zolera Systems Inc. All Rights Reserved. Copyright 2001, MIT. All Rights Reserved. Distributed under the terms of: Python 2.0 License or later. http://www.python.org/2.0.1/license.html or W3C Software License http://www.w3.org/Consortium/Legal/copyright-software-19980720 ''' import string from xml.dom import Node try: from xml.ns import XMLNS except: class XMLNS: BASE = "http://www.w3.org/2000/xmlns/" XML = "http://www.w3.org/XML/1998/namespace" try: import cStringIO StringIO = cStringIO except ImportError: import StringIO _attrs = lambda E: (E.attributes and E.attributes.values()) or [] _children = lambda E: E.childNodes or [] _IN_XML_NS = lambda n: n.name.startswith("xmlns") _inclusive = lambda n: n.unsuppressedPrefixes == None # Does a document/PI has lesser/greater document order than the # first element? _LesserElement, _Element, _GreaterElement = range(3) def _sorter(n1,n2): '''_sorter(n1,n2) -> int Sorting predicate for non-NS attributes.''' i = cmp(n1.namespaceURI, n2.namespaceURI) if i: return i return cmp(n1.localName, n2.localName) def _sorter_ns(n1,n2): '''_sorter_ns((n,v),(n,v)) -> int "(an empty namespace URI is lexicographically least)."''' if n1[0] == 'xmlns': return -1 if n2[0] == 'xmlns': return 1 return cmp(n1[0], n2[0]) def _utilized(n, node, other_attrs, unsuppressedPrefixes): '''_utilized(n, node, other_attrs, unsuppressedPrefixes) -> boolean Return true if that nodespace is utilized within the node''' if n.startswith('xmlns:'): n = n[6:] elif n.startswith('xmlns'): n = n[5:] if (n=="" and node.prefix in ["#default", None]) or \ n == node.prefix or n in unsuppressedPrefixes: return 1 for attr in other_attrs: if n == attr.prefix: return 1 return 0 #_in_subset = lambda subset, node: not subset or node in subset _in_subset = lambda subset, node: subset is None or node in subset # rich's tweak class _implementation: '''Implementation class for C14N. This accompanies a node during it's processing and includes the parameters and processing state.''' # Handler for each node type; populated during module instantiation. handlers = {} def __init__(self, node, write, **kw): '''Create and run the implementation.''' self.write = write self.subset = kw.get('subset') self.comments = kw.get('comments', 0) self.unsuppressedPrefixes = kw.get('unsuppressedPrefixes') nsdict = kw.get('nsdict', { 'xml': XMLNS.XML, 'xmlns': XMLNS.BASE }) # Processing state. self.state = (nsdict, {'xml':''}, {}) #0422 if node.nodeType == Node.DOCUMENT_NODE: self._do_document(node) elif node.nodeType == Node.ELEMENT_NODE: self.documentOrder = _Element # At document element if not _inclusive(self): self._do_element(node) else: inherited = self._inherit_context(node) self._do_element(node, inherited) elif node.nodeType == Node.DOCUMENT_TYPE_NODE: pass else: raise TypeError, str(node) def _inherit_context(self, node): '''_inherit_context(self, node) -> list Scan ancestors of attribute and namespace context. Used only for single element node canonicalization, not for subset canonicalization.''' # Collect the initial list of xml:foo attributes. xmlattrs = filter(_IN_XML_NS, _attrs(node)) # Walk up and get all xml:XXX attributes we inherit. inherited, parent = [], node.parentNode while parent and parent.nodeType == Node.ELEMENT_NODE: for a in filter(_IN_XML_NS, _attrs(parent)): n = a.localName if n not in xmlattrs: xmlattrs.append(n) inherited.append(a) parent = parent.parentNode return inherited def _do_document(self, node): '''_do_document(self, node) -> None Process a document node. documentOrder holds whether the document element has been encountered such that PIs/comments can be written as specified.''' self.documentOrder = _LesserElement for child in node.childNodes: if child.nodeType == Node.ELEMENT_NODE: self.documentOrder = _Element # At document element self._do_element(child) self.documentOrder = _GreaterElement # After document element elif child.nodeType == Node.PROCESSING_INSTRUCTION_NODE: self._do_pi(child) elif child.nodeType == Node.COMMENT_NODE: self._do_comment(child) elif child.nodeType == Node.DOCUMENT_TYPE_NODE: pass else: raise TypeError, str(child) handlers[Node.DOCUMENT_NODE] = _do_document def _do_text(self, node): '''_do_text(self, node) -> None Process a text or CDATA node. Render various special characters as their C14N entity representations.''' if not _in_subset(self.subset, node): return s = string.replace(node.data, "&", "&") s = string.replace(s, "<", "<") s = string.replace(s, ">", ">") s = string.replace(s, "\015", " ") if s: self.write(s) handlers[Node.TEXT_NODE] = _do_text handlers[Node.CDATA_SECTION_NODE] = _do_text def _do_pi(self, node): '''_do_pi(self, node) -> None Process a PI node. Render a leading or trailing #xA if the document order of the PI is greater or lesser (respectively) than the document element. ''' if not _in_subset(self.subset, node): return W = self.write if self.documentOrder == _GreaterElement: W('\n') W('') if self.documentOrder == _LesserElement: W('\n') handlers[Node.PROCESSING_INSTRUCTION_NODE] = _do_pi def _do_comment(self, node): '''_do_comment(self, node) -> None Process a comment node. Render a leading or trailing #xA if the document order of the comment is greater or lesser (respectively) than the document element. ''' if not _in_subset(self.subset, node): return if self.comments: W = self.write if self.documentOrder == _GreaterElement: W('\n') W('') if self.documentOrder == _LesserElement: W('\n') handlers[Node.COMMENT_NODE] = _do_comment def _do_attr(self, n, value): ''''_do_attr(self, node) -> None Process an attribute.''' W = self.write W(' ') W(n) W('="') s = string.replace(value, "&", "&") s = string.replace(s, "<", "<") s = string.replace(s, '"', '"') s = string.replace(s, '\011', ' ') s = string.replace(s, '\012', ' ') s = string.replace(s, '\015', ' ') W(s) W('"') def _do_element(self, node, initial_other_attrs = []): '''_do_element(self, node, initial_other_attrs = []) -> None Process an element (and its children).''' # Get state (from the stack) make local copies. # ns_parent -- NS declarations in parent # ns_rendered -- NS nodes rendered by ancestors # ns_local -- NS declarations relevant to this element # xml_attrs -- Attributes in XML namespace from parent # xml_attrs_local -- Local attributes in XML namespace. ns_parent, ns_rendered, xml_attrs = \ self.state[0], self.state[1].copy(), self.state[2].copy() #0422 ns_local = ns_parent.copy() xml_attrs_local = {} # Divide attributes into NS, XML, and others. other_attrs = initial_other_attrs[:] in_subset = _in_subset(self.subset, node) for a in _attrs(node): if a.namespaceURI == XMLNS.BASE: n = a.nodeName if n == "xmlns:": n = "xmlns" # DOM bug workaround ns_local[n] = a.nodeValue elif a.namespaceURI == XMLNS.XML: if _inclusive(self) or (in_subset and _in_subset(self.subset, a)): #020925 Test to see if attribute node in subset xml_attrs_local[a.nodeName] = a #0426 else: if _in_subset(self.subset, a): #020925 Test to see if attribute node in subset other_attrs.append(a) #add local xml:foo attributes to ancestor's xml:foo attributes xml_attrs.update(xml_attrs_local) # Render the node W, name = self.write, None if in_subset: name = node.nodeName W('<') W(name) # Create list of NS attributes to render. ns_to_render = [] for n,v in ns_local.items(): # If default namespace is XMLNS.BASE or empty, # and if an ancestor was the same if n == "xmlns" and v in [ XMLNS.BASE, '' ] \ and ns_rendered.get('xmlns') in [ XMLNS.BASE, '', None ]: continue # "omit namespace node with local name xml, which defines # the xml prefix, if its string value is # http://www.w3.org/XML/1998/namespace." if n in ["xmlns:xml", "xml"] \ and v in [ 'http://www.w3.org/XML/1998/namespace' ]: continue # If not previously rendered # and it's inclusive or utilized if (n,v) not in ns_rendered.items() \ and (_inclusive(self) or \ _utilized(n, node, other_attrs, self.unsuppressedPrefixes)): ns_to_render.append((n, v)) # Sort and render the ns, marking what was rendered. ns_to_render.sort(_sorter_ns) for n,v in ns_to_render: self._do_attr(n, v) ns_rendered[n]=v #0417 # If exclusive or the parent is in the subset, add the local xml attributes # Else, add all local and ancestor xml attributes # Sort and render the attributes. if not _inclusive(self) or _in_subset(self.subset,node.parentNode): #0426 other_attrs.extend(xml_attrs_local.values()) else: other_attrs.extend(xml_attrs.values()) other_attrs.sort(_sorter) for a in other_attrs: self._do_attr(a.nodeName, a.value) W('>') # Push state, recurse, pop state. state, self.state = self.state, (ns_local, ns_rendered, xml_attrs) for c in _children(node): _implementation.handlers[c.nodeType](self, c) self.state = state if name: W('' % name) handlers[Node.ELEMENT_NODE] = _do_element def Canonicalize(node, output=None, **kw): '''Canonicalize(node, output=None, **kw) -> UTF-8 Canonicalize a DOM document/element node and all descendents. Return the text; if output is specified then output.write will be called to output the text and None will be returned Keyword parameters: nsdict: a dictionary of prefix:uri namespace entries assumed to exist in the surrounding context comments: keep comments if non-zero (default is 0) subset: Canonical XML subsetting resulting from XPath (default is []) unsuppressedPrefixes: do exclusive C14N, and this specifies the prefixes that should be inherited. ''' if output: apply(_implementation, (node, output.write), kw) else: s = StringIO.StringIO() apply(_implementation, (node, s.write), kw) return s.getvalue() PyXML-0.8.2/xml/dom/fr_FR/0040755000076400001440000000000007614726123014300 5ustar martinusersPyXML-0.8.2/xml/dom/fr_FR/LC_MESSAGES/0040755000076400001440000000000007614726123016065 5ustar martinusersPyXML-0.8.2/xml/dom/fr_FR/LC_MESSAGES/4Suite.mo0100644000076400001440000000355107377133276017607 0ustar martinusersL$M$r&.+0&M#t!?3&I!p&"))@0,q0?4D]8|&$'C)7m&"5#EAttempt to modify a read-only objectAttempt to modify the type of a nodeAttribute already in use by an elementIndex error accessing NodeList or NamedNodeMapInvalid Boundary Points specified for RangeInvalid Container NodeInvalid or illegal characterInvalid or illegal namespace operationNode does not exist in this contextNode does not support dataNode is from a different documentNode manipulation results in invalid parent/child relationship.Object does not support this operation or parameterObject is not, or is no longer, usableObject or operation not supportedSpecified string is invalid or illegalUninitialized type in Event objectXML parse error at line %d, column %d: %sLa DOMString a dpass la taille maximaleTentative de modification d'un objet accessible en lecture seuleTentative de modification du type d'un noeudL'attribut est dj utilis par un autre lmentErreur d'indexe pour l'accs la NodeList ou la NamedNodeMapDes bornes invalides ont t passes l'intervallesNoeud conteneur invalideCharactre invalide ou illgalOpration sur les domaines nominaux invalide ou illgaleLe noeud n'existe pas dans ce contexteCe noeud ne peut contenir de donnesLe noeud appartient un autre documentLa manipulation du noeud cause une relation parent/enfant invalide.L'objet ne supporte pas cette opration ou ce paramtreCet objet n'est pas ou plus utilisableObjet ou opration non supportLa chaine est invalide ou illgaleLe chanmp type de l'objet Event n'a pas t initialiErreur XML ligne %d, colonne %d: %sPyXML-0.8.2/xml/dom/html/0040755000076400001440000000000007614726123014246 5ustar martinusersPyXML-0.8.2/xml/dom/html/GenerateHtml.py0100755000076400001440000002315407253474633017211 0ustar martinusers#!/usr/bin/env python import string, os, sys try: from xml.dom import Node from xml.dom.ext.reader import Sax Reader = Sax.FromXmlFile except ImportError: print 'You need to have PyXML installed to run this program' sys.exit(1) def Generate(fileName, output_dir=None, program_name=None ): output_dir = output_dir or '.' dom = Reader(fileName) header = CreateHeader(dom, program_name) classes = dom.getElementsByTagName('class') outfiles = [] for klass in classes: outfiles.append(GenClassFile(klass, header, output_dir)) return outfiles def CreateHeader(dom, prog_name): result = '' header = dom.getElementsByTagName('header') if header: result = result + string.strip(header[0].childNodes[0].data) result = result + '\n\n' if prog_name: add_str = ' by ' + prog_name else: add_str = '' result = result + '### This file is automatically generated%s.\n' % add_str result = result + '### DO NOT EDIT!\n\n' copyright = dom.getElementsByTagName('copyright') if copyright: result = result + '"""\n' result = result + string.strip(copyright[0].childNodes[0].data) + '\n' result = result + '"""\n\n' return result # Helper function for indenting Python def indent(count, text, tab=' '*4): return tab*count + text # Get/Set routines for DOMString attributes def stringGetAttr(name, value): return indent(2, 'return self.getAttribute("%s")\n\n' % name) def stringSetAttr(name): return indent(2, 'self.setAttribute("%s", value)\n\n' % name) # Routines for boolean attributes def boolGetAttr(name, value): return indent(2, 'return self.hasAttribute("%s")\n\n' % name) def boolSetAttr(name): result = indent(2, 'if value:\n') result = result + indent(3, 'self.setAttribute("%s", "%s")\n' % (name, name)) result = result + indent(2, 'else:\n') result = result + indent(3, 'self.removeAttribute("%s")\n\n' % name) return result # Routines for number attributes def longGetAttr(name, value): result = indent(2, 'value = self.getAttribute("%s")\n' % name) result = result + indent(2, 'if value:\n') result = result + indent(3, 'return int(value)\n') result = result + indent(2, 'return 0\n\n') return result def longSetAttr(name): return indent(2, 'self.setAttribute("%s", str(value))\n\n' % name) # Routines for value-list attributes def listGetAttr(name, value): return indent(2, 'return string.capitalize(self.getAttribute("%s"))\n\n' % name) # Routines for attributes mapped to Text nodes def nodeGetAttr(dummy, value): result = indent(2, 'if not self.firstChild:\n') result = result + indent(3, 'return ''\n') result = result + indent(2, 'if self.firstChild == self.lastChild:\n') result = result + indent(3, 'return self.firstChild.data\n') result = result + indent(2, 'self.normalize()\n') result = result + indent(2, 'text = filter(lambda x: x.nodeType == Node.TEXT_NODE, self.childNodes)\n') result = result + indent(2, 'return text[0].data\n\n') return result def nodeSetAttr(dummy): result = indent(2, 'text = None\n') result = result + indent(2, 'for node in self.childNodes:\n') result = result + indent(3, 'if not text and node.nodeType == Node.TEXT_NODE:\n') result = result + indent(4, 'text = node\n') result = result + indent(3, 'else:\n') result = result + indent(4, 'self.removeChild(node)\n') result = result + indent(2, 'if text:\n') result = result + indent(3, 'text.data = value\n') result = result + indent(2, 'else:\n') result = result + indent(3, 'text = self.ownerDocument.createTextNode(value)\n') result = result + indent(3, 'self.appendChild(text)\n\n') return result #Routines for constant attributes def constGetAttr(name, value): if not value: value = 'None' else: value = '"%s"' % value return indent(2, 'return %s\n\n' % value) #Routines for form based classes def formGetAttr(dummy,dummy2): result = indent(2, 'parent = self.parentNode\n') result = result + indent(2, 'while parent:\n') result = result + indent(3, 'if parent.nodeName == "FORM":\n') result = result + indent(4, 'return parent\n') result = result + indent(3, 'parent = parent.parentNode\n') result = result + indent(2, 'return None\n\n') return result g_valueTypeMap = { 'bool' : (boolGetAttr, boolSetAttr), 'long' : (longGetAttr, longSetAttr), 'list' : (listGetAttr, stringSetAttr), 'node' : (nodeGetAttr, nodeSetAttr), 'string' : (stringGetAttr, stringSetAttr), 'form' : (formGetAttr, None), 'const' : (constGetAttr, None) } def GenClassFile(klass, header, output_dir): class_name = 'HTML%sElement' % klass.getAttribute('name') fileName = os.path.join(output_dir,class_name + '.py') file = open(fileName, 'w') # General header stuff file.write(string.replace(header, '$FILE$', class_name)) # Import statements file.write('import string\n') file.write('from xml.dom import Node\n') baseclass = klass.getElementsByTagName('baseclass')[0].getAttribute('name') base_name = string.split(baseclass, '.')[-1] file.write('from %s import %s\n' % (baseclass, base_name)) file.write('\n') # Class declaration file.write('class %s(%s):\n\n' % (class_name, base_name)) # Constructor file.write(indent(1, 'def __init__(self, ownerDocument, nodeName')) multiple = klass.getAttribute('multiple') tag_name = klass.getAttribute('tagname') if not multiple: if not tag_name: tag_name = string.upper(klass.getAttribute('name')) file.write('="%s"' % tag_name) file.write('):\n') file.write(indent(2, '%s.__init__(self, ownerDocument, nodeName)\n\n' % base_name)) # Attributes file.write(indent(1, '### Attribute Methods ###\n\n')) attrs = klass.getElementsByTagName('attribute') read_attrs = [] write_attrs = [] for attr in attrs: dom_name = attr.getAttribute('name') value_type = attr.getAttribute('type') html_name = attr.getAttribute('htmlname') if not html_name: html_name = string.upper(dom_name) value = attr.getAttribute('value') # for const value-type permissions = attr.getElementsByTagName('permissions')[0] readable = int(permissions.getAttribute('readable')) writeable = int(permissions.getAttribute('writeable')) if readable: file.write(indent(1, 'def _get_%s(self):\n' % dom_name)) get_func = g_valueTypeMap[value_type][0] file.write(get_func(html_name, value)) read_attrs.append(dom_name) if writeable: file.write(indent(1, 'def _set_%s(self, value):\n' % dom_name)) set_func = g_valueTypeMap[value_type][1] try: file.write(set_func(html_name or value)) except: raise "Set function '%s' in class %s, attribute %s" % (value_type, class_name, dom_name) write_attrs.append(dom_name) # Methods methods = klass.getElementsByTagName('method') if methods: file.write(indent(1, '### Methods ###\n\n')) for method in methods: method_name = method.getAttribute('name') params = method.getElementsByTagName('params')[0].childNodes param_list = [] for param in params: arg = param.getAttribute('name') default = param.firstChild param_list.append((arg,default)) file.write(indent(1, 'def %s(self' % method_name)) for arg,default in param_list: file.write(', %s' % arg) if default: file.write('=%s' % default.data) file.write('):\n') # The function code code = method.getElementsByTagName('code')[0].firstChild if code: lines = string.split(string.strip(code.data), '\n') for line in lines: writeTab(file, 2, line) else: file.write(indent(2, 'pass\n')) file.write('\n') # Attribute access control file.write(indent(1, '### Attribute Access Mappings ###\n\n')) file.write(indent(1, '_readComputedAttrs = %s._readComputedAttrs.copy()\n' % base_name)) if len(read_attrs): file.write(indent(1, '_readComputedAttrs.update({\n')) for attr in read_attrs[:-1]: file.write(indent(2, '"%s" : _get_%s,\n' % (attr, attr))) attr = read_attrs[-1] file.write(indent(2, '"%s" : _get_%s\n' % (attr, attr))) file.write(indent(2, '})\n\n')) file.write(indent(1, '_writeComputedAttrs = %s._writeComputedAttrs.copy()\n' % base_name)) if len(write_attrs): file.write(indent(1, '_writeComputedAttrs.update({\n')) for attr in write_attrs[:-1]: file.write(indent(2, '"%s" : _set_%s,\n' % (attr, attr))) attr = write_attrs[-1] file.write(indent(2, '"%s" : _set_%s\n' % (attr, attr))) file.write(indent(2, '})\n\n')) file.write(indent(1, '_readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k),\n')) file.write(indent(1, ' %s._readOnlyAttrs + _readComputedAttrs.keys())\n\n' % base_name)) return fileName if __name__ == '__main__': program_name = os.path.basename(sys.argv[0]) output_dir = None if len(sys.argv) < 2: print 'Usage: %s input_file [output_dir]' % program_name sys.exit(1) elif len(sys.argv) == 3: output_dir = sys.argv[2] input_file = sys.argv[1] Generate(input_file,output_dir,program_name) PyXML-0.8.2/xml/dom/html/HTMLAnchorElement.py0100644000076400001440000000742707253474633020045 0ustar martinusers######################################################################## # # File Name: HTMLAnchorElement # # Documentation: http://docs.4suite.com/4DOM/HTMLAnchorElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLAnchorElement(HTMLElement): def __init__(self, ownerDocument, nodeName="A"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_accessKey(self): return self.getAttribute("ACCESSKEY") def _set_accessKey(self, value): self.setAttribute("ACCESSKEY", value) def _get_charset(self): return self.getAttribute("CHARSET") def _set_charset(self, value): self.setAttribute("CHARSET", value) def _get_coords(self): return self.getAttribute("COORDS") def _set_coords(self, value): self.setAttribute("COORDS", value) def _get_href(self): return self.getAttribute("HREF") def _set_href(self, value): self.setAttribute("HREF", value) def _get_hreflang(self): return self.getAttribute("HREFLANG") def _set_hreflang(self, value): self.setAttribute("HREFLANG", value) def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_rel(self): return self.getAttribute("REL") def _set_rel(self, value): self.setAttribute("REL", value) def _get_rev(self): return self.getAttribute("REV") def _set_rev(self, value): self.setAttribute("REV", value) def _get_shape(self): return string.capitalize(self.getAttribute("SHAPE")) def _set_shape(self, value): self.setAttribute("SHAPE", value) def _get_tabIndex(self): value = self.getAttribute("TABINDEX") if value: return int(value) return 0 def _set_tabIndex(self, value): self.setAttribute("TABINDEX", str(value)) def _get_target(self): return self.getAttribute("TARGET") def _set_target(self, value): self.setAttribute("TARGET", value) def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) ### Methods ### def blur(self): pass def focus(self): pass ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "accessKey" : _get_accessKey, "charset" : _get_charset, "coords" : _get_coords, "href" : _get_href, "hreflang" : _get_hreflang, "name" : _get_name, "rel" : _get_rel, "rev" : _get_rev, "shape" : _get_shape, "tabIndex" : _get_tabIndex, "target" : _get_target, "type" : _get_type }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "accessKey" : _set_accessKey, "charset" : _set_charset, "coords" : _set_coords, "href" : _set_href, "hreflang" : _set_hreflang, "name" : _set_name, "rel" : _set_rel, "rev" : _set_rev, "shape" : _set_shape, "tabIndex" : _set_tabIndex, "target" : _set_target, "type" : _set_type }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLAppletElement.py0100644000076400001440000000663607253474633020061 0ustar martinusers######################################################################## # # File Name: HTMLAppletElement # # Documentation: http://docs.4suite.com/4DOM/HTMLAppletElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLAppletElement(HTMLElement): def __init__(self, ownerDocument, nodeName="APPLET"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) def _get_alt(self): return self.getAttribute("ALT") def _set_alt(self, value): self.setAttribute("ALT", value) def _get_archive(self): return self.getAttribute("ARCHIVE") def _set_archive(self, value): self.setAttribute("ARCHIVE", value) def _get_code(self): return self.getAttribute("CODE") def _set_code(self, value): self.setAttribute("CODE", value) def _get_codeBase(self): return self.getAttribute("CODEBASE") def _set_codeBase(self, value): self.setAttribute("CODEBASE", value) def _get_height(self): return self.getAttribute("HEIGHT") def _set_height(self, value): self.setAttribute("HEIGHT", value) def _get_hspace(self): return self.getAttribute("HSPACE") def _set_hspace(self, value): self.setAttribute("HSPACE", value) def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_object(self): return self.getAttribute("OBJECT") def _set_object(self, value): self.setAttribute("OBJECT", value) def _get_vspace(self): return self.getAttribute("VSPACE") def _set_vspace(self, value): self.setAttribute("VSPACE", value) def _get_width(self): return self.getAttribute("WIDTH") def _set_width(self, value): self.setAttribute("WIDTH", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align, "alt" : _get_alt, "archive" : _get_archive, "code" : _get_code, "codeBase" : _get_codeBase, "height" : _get_height, "hspace" : _get_hspace, "name" : _get_name, "object" : _get_object, "vspace" : _get_vspace, "width" : _get_width }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align, "alt" : _set_alt, "archive" : _set_archive, "code" : _set_code, "codeBase" : _set_codeBase, "height" : _set_height, "hspace" : _set_hspace, "name" : _set_name, "object" : _set_object, "vspace" : _set_vspace, "width" : _set_width }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLAreaElement.py0100644000076400001440000000573007253474633017476 0ustar martinusers######################################################################## # # File Name: HTMLAreaElement # # Documentation: http://docs.4suite.com/4DOM/HTMLAreaElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLAreaElement(HTMLElement): def __init__(self, ownerDocument, nodeName="AREA"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_accessKey(self): return self.getAttribute("ACCESSKEY") def _set_accessKey(self, value): self.setAttribute("ACCESSKEY", value) def _get_alt(self): return self.getAttribute("ALT") def _set_alt(self, value): self.setAttribute("ALT", value) def _get_coords(self): return self.getAttribute("COORDS") def _set_coords(self, value): self.setAttribute("COORDS", value) def _get_href(self): return self.getAttribute("HREF") def _set_href(self, value): self.setAttribute("HREF", value) def _get_noHref(self): return self.hasAttribute("NOHREF") def _set_noHref(self, value): if value: self.setAttribute("NOHREF", "NOHREF") else: self.removeAttribute("NOHREF") def _get_shape(self): return string.capitalize(self.getAttribute("SHAPE")) def _set_shape(self, value): self.setAttribute("SHAPE", value) def _get_tabIndex(self): value = self.getAttribute("TABINDEX") if value: return int(value) return 0 def _set_tabIndex(self, value): self.setAttribute("TABINDEX", str(value)) def _get_target(self): return self.getAttribute("TARGET") def _set_target(self, value): self.setAttribute("TARGET", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "accessKey" : _get_accessKey, "alt" : _get_alt, "coords" : _get_coords, "href" : _get_href, "noHref" : _get_noHref, "shape" : _get_shape, "tabIndex" : _get_tabIndex, "target" : _get_target }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "accessKey" : _set_accessKey, "alt" : _set_alt, "coords" : _set_coords, "href" : _set_href, "noHref" : _set_noHref, "shape" : _set_shape, "tabIndex" : _set_tabIndex, "target" : _set_target }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLBRElement.py0100644000076400001440000000254407253474633017131 0ustar martinusers######################################################################## # # File Name: HTMLBRElement # # Documentation: http://docs.4suite.com/4DOM/HTMLBRElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLBRElement(HTMLElement): def __init__(self, ownerDocument, nodeName="BR"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_clear(self): return string.capitalize(self.getAttribute("CLEAR")) def _set_clear(self, value): self.setAttribute("CLEAR", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "clear" : _get_clear }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "clear" : _set_clear }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLBaseElement.py0100644000076400001440000000304607253474633017476 0ustar martinusers######################################################################## # # File Name: HTMLBaseElement # # Documentation: http://docs.4suite.com/4DOM/HTMLBaseElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLBaseElement(HTMLElement): def __init__(self, ownerDocument, nodeName="BASE"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_href(self): return self.getAttribute("HREF") def _set_href(self, value): self.setAttribute("HREF", value) def _get_target(self): return self.getAttribute("TARGET") def _set_target(self, value): self.setAttribute("TARGET", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "href" : _get_href, "target" : _get_target }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "href" : _set_href, "target" : _set_target }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLBaseFontElement.py0100644000076400001440000000336307253474633020327 0ustar martinusers######################################################################## # # File Name: HTMLBaseFontElement # # Documentation: http://docs.4suite.com/4DOM/HTMLBaseFontElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLBaseFontElement(HTMLElement): def __init__(self, ownerDocument, nodeName="BASEFONT"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_color(self): return self.getAttribute("COLOR") def _set_color(self, value): self.setAttribute("COLOR", value) def _get_face(self): return self.getAttribute("FACE") def _set_face(self, value): self.setAttribute("FACE", value) def _get_size(self): return self.getAttribute("SIZE") def _set_size(self, value): self.setAttribute("SIZE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "color" : _get_color, "face" : _get_face, "size" : _get_size }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "color" : _set_color, "face" : _set_face, "size" : _set_size }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLBodyElement.py0100644000076400001440000000460207253474633017520 0ustar martinusers######################################################################## # # File Name: HTMLBodyElement # # Documentation: http://docs.4suite.com/4DOM/HTMLBodyElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLBodyElement(HTMLElement): def __init__(self, ownerDocument, nodeName="BODY"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_aLink(self): return self.getAttribute("ALINK") def _set_aLink(self, value): self.setAttribute("ALINK", value) def _get_background(self): return self.getAttribute("BACKGROUND") def _set_background(self, value): self.setAttribute("BACKGROUND", value) def _get_bgColor(self): return self.getAttribute("BGCOLOR") def _set_bgColor(self, value): self.setAttribute("BGCOLOR", value) def _get_link(self): return self.getAttribute("LINK") def _set_link(self, value): self.setAttribute("LINK", value) def _get_text(self): return self.getAttribute("TEXT") def _set_text(self, value): self.setAttribute("TEXT", value) def _get_vLink(self): return self.getAttribute("VLINK") def _set_vLink(self, value): self.setAttribute("VLINK", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "aLink" : _get_aLink, "background" : _get_background, "bgColor" : _get_bgColor, "link" : _get_link, "text" : _get_text, "vLink" : _get_vLink }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "aLink" : _set_aLink, "background" : _set_background, "bgColor" : _set_bgColor, "link" : _set_link, "text" : _set_text, "vLink" : _set_vLink }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLButtonElement.py0100644000076400001440000000531107253474633020074 0ustar martinusers######################################################################## # # File Name: HTMLButtonElement # # Documentation: http://docs.4suite.com/4DOM/HTMLButtonElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLButtonElement(HTMLElement): def __init__(self, ownerDocument, nodeName="BUTTON"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_accessKey(self): return self.getAttribute("ACCESSKEY") def _set_accessKey(self, value): self.setAttribute("ACCESSKEY", value) def _get_disabled(self): return self.hasAttribute("DISABLED") def _set_disabled(self, value): if value: self.setAttribute("DISABLED", "DISABLED") else: self.removeAttribute("DISABLED") def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_tabIndex(self): value = self.getAttribute("TABINDEX") if value: return int(value) return 0 def _set_tabIndex(self, value): self.setAttribute("TABINDEX", str(value)) def _get_type(self): return self.getAttribute("TYPE") def _get_value(self): return self.getAttribute("VALUE") def _set_value(self, value): self.setAttribute("VALUE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "accessKey" : _get_accessKey, "disabled" : _get_disabled, "form" : _get_form, "name" : _get_name, "tabIndex" : _get_tabIndex, "type" : _get_type, "value" : _get_value }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "accessKey" : _set_accessKey, "disabled" : _set_disabled, "name" : _set_name, "tabIndex" : _set_tabIndex, "value" : _set_value }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLCollection.py0100644000076400001440000000431207253474633017402 0ustar martinusers######################################################################## # # File Name: HTMLCollection.py # # Documentation: http://docs.4suite.com/4DOM/HTMLCollection.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from xml.dom import NoModificationAllowedErr from xml.dom.html import HTML_NAME_ALLOWED import UserList class HTMLCollection(UserList.UserList): def __init__(self, list=None): UserList.UserList.__init__(self, list or []) ### Attribute Access Methods ### def __getattr__(self, name): if name == 'length': return self._get_length() # Pass-through return getattr(HTMLCollection, name) def __setattr__(self, name, value): if name == 'length': self._set_length(value) # Pass-through self.__dict__[name] = value ### Attribute Methods ### def _get_length(self): return self.__len__() def _set_length(self, value): raise NoModificationAllowedErr() ### Methods ### def item(self, index): if index >= self.__len__(): return None else: return self[int(index)] def namedItem(self, name): found_node = None for node in self: # IDs take presedence over NAMEs if node.getAttribute('ID') == name: found_node = node break if not found_node and node.getAttribute('NAME') == name \ and node.tagName in HTML_NAME_ALLOWED: # We found a node with NAME attribute, but we have to wait # until all nodes are done (one might have an ID that matches) found_node = node print 'found:', found_node return found_node ### Overridden Methods ### def __repr__(self): st = "' return st PyXML-0.8.2/xml/dom/html/HTMLDListElement.py0100644000076400001440000000267607253474633017653 0ustar martinusers######################################################################## # # File Name: HTMLDListElement # # Documentation: http://docs.4suite.com/4DOM/HTMLDListElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLDListElement(HTMLElement): def __init__(self, ownerDocument, nodeName="DL"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_compact(self): return self.hasAttribute("COMPACT") def _set_compact(self, value): if value: self.setAttribute("COMPACT", "COMPACT") else: self.removeAttribute("COMPACT") ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "compact" : _get_compact }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "compact" : _set_compact }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLDOMImplementation.py0100644000076400001440000000214207271065024020621 0ustar martinusers######################################################################## # # File Name: implementation.py # # Documentation: http://docs.4suite.com/4DOM/implementation.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import DOMImplementation # Add the HTML feature DOMImplementation.FEATURES_MAP['HTML'] = 2.0 class HTMLDOMImplementation(DOMImplementation.DOMImplementation): def __init__(self): DOMImplementation.DOMImplementation.__init__(self) def createHTMLDocument(self, title): from xml.dom.html import HTMLDocument doc = HTMLDocument.HTMLDocument() h = doc.createElement('HTML') doc.appendChild(h) doc._set_title(title) return doc def _4dom_createHTMLCollection(self,list=None): if list is None: list = [] from xml.dom.html import HTMLCollection hc = HTMLCollection.HTMLCollection(list) return hc PyXML-0.8.2/xml/dom/html/HTMLDirectoryElement.py0100644000076400001440000000271307253474633020570 0ustar martinusers######################################################################## # # File Name: HTMLDirectoryElement # # Documentation: http://docs.4suite.com/4DOM/HTMLDirectoryElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLDirectoryElement(HTMLElement): def __init__(self, ownerDocument, nodeName="DIR"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_compact(self): return self.hasAttribute("COMPACT") def _set_compact(self, value): if value: self.setAttribute("COMPACT", "COMPACT") else: self.removeAttribute("COMPACT") ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "compact" : _get_compact }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "compact" : _set_compact }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLDivElement.py0100644000076400001440000000305507253474633017346 0ustar martinusers######################################################################## # # File Name: HTMLDivElement # # Documentation: http://docs.4suite.com/4DOM/HTMLDivElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLDivElement(HTMLElement): def __init__(self, ownerDocument, nodeName="DIV"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "type" : _get_type, "align" : _get_align }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "type" : _set_type, "align" : _set_align }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLDocument.py0100644000076400001440000002667207413106704017067 0ustar martinusers######################################################################## # # File Name: HTMLDocument.py # # Documentation: http://docs.4suite.com/4DOM/HTMLDocument.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from xml.dom import NotSupportedErr from xml.dom.Document import Document from xml.dom import implementation from xml.dom import ext import string, sys from xml.dom.html import HTML_DTD class HTMLDocument(Document): def __init__(self): Document.__init__(self, None) # These only make sense in a browser environment, therefore # they never change self.__dict__['__referrer'] = '' self.__dict__['__domain'] = None self.__dict__['__URL'] = '' self.__dict__['__cookie'] = '' self.__dict__['__writable'] = 0 self.__dict__['_html'] = vars(sys.modules['xml.dom.html']) ### Attribute Methods ### def _get_URL(self): return self.__dict__['__URL'] def _get_anchors(self): anchors = self.getElementsByTagName('A'); anchors = filter(lambda x: x._get_name(), anchors) return implementation._4dom_createHTMLCollection(anchors) def _get_applets(self): al = self.getElementsByTagName('APPLET') ol = self.getElementsByTagName('OBJECT') ol = filter(lambda x: x._get_code(), ol) return implementation._4dom_createHTMLCollection(al+ol) def _get_body(self): body = '' #Try to find the body or FRAMESET elements = self.getElementsByTagName('FRAMESET') if not elements: elements = self.getElementsByTagName('BODY') if elements: body = elements[0] else: #Create a body body = self.createElement('BODY') self.documentElement.appendChild(body) return body def _set_body(self, newBody): elements = self.getElementsByTagName('FRAMESET') if not elements: elements = self.getElementsByTagName('BODY') if elements: # Replace the existing one elements[0].parentNode.replaceChild(newBody, elements[0]) else: # Add it self.documentElement.appendChild(newBody) def _get_cookie(self): return self.__dict__['__cookie'] def _set_cookie(self, cookie): self.__dict__['__cookie'] = cookie def _get_domain(self): return self.__dict__['__domain'] def _get_forms(self): forms = self.getElementsByTagName('FORM') return implementation._4dom_createHTMLCollection(forms) def _get_images(self): images = self.getElementsByTagName('IMG') return implementation._4dom_createHTMLCollection(images) def _get_links(self): areas = self.getElementsByTagName('AREA') anchors = self.getElementsByTagName('A') links = filter(lambda x: x._get_href(), areas+anchors) return implementation._4dom_createHTMLCollection(links) def _get_referrer(self): return self.__dict__['__referrer'] def _get_title(self): elements = self.getElementsByTagName('TITLE') if elements: #Take the first title = elements[0] title.normalize() if title.firstChild: return title.firstChild.data return '' def _set_title(self, title): # See if we can find the title title_nodes = self.getElementsByTagName('TITLE') if title_nodes: title_node = title_nodes[0] title_node.normalize() if title_node.firstChild: title_node.firstChild.data = title return else: title_node = self.createElement('TITLE') self._4dom_getHead().appendChild(title_node) text = self.createTextNode(title) title_node.appendChild(text) ### Methods ### def close(self): self.__dict__['__writable'] = 0 def getElementsByName(self, elementName): return self._4dom_getElementsByAttribute('*', 'NAME', elementName) def open(self): #Clear out the doc self.__dict__['__referrer'] = '' self.__dict__['__domain'] = None self.__dict__['__url'] = '' self.__dict__['__cookie'] = '' self.__dict__['__writable'] = 1 def write(self, st): if not self.__dict__['__writable']: return #We need to parse the string here from xml.dom.ext.reader.HtmlLib import FromHTML d = FromHtml(st, self) if d != self: self.appendChild(d) def writeln(self, st): st = st + '\n' self.write(st) def getElementByID(self, ID): hc = self._4dom_getElementsByAttribute('*','ID',ID) if hc.length != 0: return hc[0] return None ### Overridden Methods ### def createElement(self, tagName): return self._4dom_createHTMLElement(tagName) def createElementNS(self, namespace, qname): return self._4dom_createHTMLElement(qname) def createAttribute(self, name): return Document.createAttribute(self, string.upper(name)) def createCDATASection(*args, **kw): raise NotSupportedErr() def createEntityReference(*args, **kw): raise NotSupportedErr() def createProcessingInstruction(*args, **kw): raise NotSupportedErr() def _4dom_createEntity(*args, **kw): raise NotSupportedErr() def _4dom_createNotation(*args, **kw): raise NotSupportedErr() ### Internal Methods ### def _4dom_getElementsByAttribute(self, tagName, attribute, attrValue=None): nl = self.getElementsByTagName(tagName) hc = implementation._4dom_createHTMLCollection() for elem in nl: attr = elem.getAttribute(attribute) if attrValue == None and attr != '': hc.append(elem) elif attr == attrValue: hc.append(elem) return hc def _4dom_getHead(self): nl = self.getElementsByTagName('HEAD') if not nl: head = self.createElement('HEAD') #The head goes in front of the body body = self._get_body() self.documentElement.insertBefore(head, body) else: head = nl[0] return head def _4dom_createHTMLElement(self, tagName): lowered = string.lower(tagName) if not HTML_DTD.has_key(lowered): raise TypeError('Unknown HTML Element: %s' % tagName) if lowered in NoClassTags: from HTMLElement import HTMLElement return HTMLElement(self, tagName) #FIXME: capitalize() broken with unicode in Python 2.0 #normTagName = string.capitalize(tagName) capitalized = string.upper(tagName[0]) + lowered[1:] element = HTMLTagMap.get(capitalized, capitalized) module = 'HTML%sElement' % element if not self._html.has_key(module): #Try to import it (should never fail) __import__('xml.dom.html.%s' % module) # Class and module have the same name klass = getattr(self._html[module], module) return klass(self, tagName) def cloneNode(self, deep): clone = HTMLDocument() clone.__dict__['__referrer'] = self._get_referrer() clone.__dict__['__domain'] = self._get_domain() clone.__dict__['__URL'] = self._get_URL() clone.__dict__['__cookie'] = self._get_cookie() if deep: if self.doctype is not None: # Cannot have any children, no deep needed dt = self.doctype.cloneNode(0) clone._4dom_setDocumentType(dt) if self.documentElement is not None: # The root element can have children, duh root = self.documentElement.cloneNode(1, newOwner=clone) clone.appendChild(root) return clone def isXml(self): return 0 def isHtml(self): return 1 ### Attribute Access Mappings ### _readComputedAttrs = Document._readComputedAttrs.copy() _readComputedAttrs.update ({ 'title' : _get_title, 'referrer' : _get_referrer, 'domain' : _get_domain, 'URL' : _get_URL, 'body' : _get_body, 'images' : _get_images, 'applets' : _get_applets, 'links' : _get_links, 'forms' : _get_forms, 'anchors' : _get_anchors, 'cookie' : _get_cookie }) _writeComputedAttrs = Document._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'title' : _set_title, 'body' : _set_body, 'cookie' : _set_cookie, }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), Document._readOnlyAttrs + _readComputedAttrs.keys()) # HTML tags that don't map directly to a class name HTMLTagMap = {'Isindex': 'IsIndex', 'Optgroup': 'OptGroup', 'Textarea': 'TextArea', 'Fieldset': 'FieldSet', 'Ul': 'UList', 'Ol': 'OList', 'Dl': 'DList', 'Dir': 'Directory', 'Li': 'LI', 'P': 'Paragraph', 'H1': 'Heading', 'H2': 'Heading', 'H3': 'Heading', 'H4': 'Heading', 'H5': 'Heading', 'H6': 'Heading', 'Q': 'Quote', 'Blockquote': 'Quote', 'Br': 'BR', 'Basefont': 'BaseFont', 'Hr': 'HR', 'A': 'Anchor', 'Img': 'Image', 'Caption': 'TableCaption', 'Col': 'TableCol', 'Colgroup': 'TableCol', 'Td': 'TableCell', 'Th': 'TableCell', 'Tr': 'TableRow', 'Thead': 'TableSection', 'Tbody': 'TableSection', 'Tfoot': 'TableSection', 'Frameset': 'FrameSet', 'Iframe': 'IFrame', 'Form': 'Form', 'Ins' : 'Mod', 'Del' : 'Mod', } #HTML Elements with no specific DOM Interface of their own NoClassTags = ['sub', 'sup', 'span', 'bdo', 'tt', 'i', 'b', 'u', 's', 'strike', 'big', 'small', 'em', 'strong', 'dfn', 'code', 'samp', 'kbd', 'var', 'cite', 'acronym', 'abbr', 'dd', 'dt', 'noframes', 'noscript', 'address', 'center', ] PyXML-0.8.2/xml/dom/html/HTMLElement.py0100644000076400001440000000707407452522431016677 0ustar martinusers######################################################################## # # File Name: HTMLElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom.Element import Element from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX import string class HTMLElement(Element): def __init__(self, ownerDocument, nodeName): tagName = string.upper(nodeName) Element.__init__(self, ownerDocument, tagName, EMPTY_NAMESPACE, EMPTY_PREFIX,tagName) ### Attribute Methods ### def _get_id(self): return self.getAttribute('ID') def _set_id(self,ID): self.setAttribute('ID',ID) def _get_title(self): return self.getAttribute('TITLE') def _set_title(self,title): self.setAttribute('TITLE',title) def _get_lang(self): return self.getAttribute('LANG') def _set_lang(self,lang): self.setAttribute('LANG',lang) def _get_dir(self): return self.getAttribute('DIR') def _set_dir(self,dir): self.setAttribute('DIR',dir) def _get_className(self): return self.getAttribute('CLASSNAME') def _set_className(self,className): self.setAttribute('CLASSNAME',className) ### Overridden Methods ### def getAttribute(self, name): attr = self.attributes.getNamedItem(string.upper(name)) return attr and attr.value or '' def getAttributeNode(self, name): return self.attributes.getNamedItem(string.upper(name)) def getElementsByTagName(self, tagName): return Element.getElementsByTagName(self, string.upper(tagName)) def hasAttribute(self, name): return self.attributes.getNamedItem(string.upper(name)) is not None def removeAttribute(self, name): attr = self.attributes.getNamedItem(string.upper(name)) attr and self.removeAttributeNode(attr) def setAttribute(self, name, value): Element.setAttribute(self, string.upper(name), value) def _4dom_validateString(self, value): return value ### Helper Functions For Cloning ### def _4dom_clone(self, owner): e = self.__class__(owner, self.tagName) for attr in self.attributes: clone = attr._4dom_clone(owner) if clone.localName is None: e.attributes.setNamedItem(clone) else: e.attributes.setNamedItemNS(clone) clone._4dom_setOwnerElement(self) return e def __getinitargs__(self): return (self.ownerDocument, self.tagName ) ### Attribute Access Mappings ### _readComputedAttrs = Element._readComputedAttrs.copy() _readComputedAttrs.update ({ 'id' : _get_id, 'title' : _get_title, 'lang' : _get_lang, 'dir' : _get_dir, 'className' : _get_className, }) _writeComputedAttrs = Element._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'id' : _set_id, 'title' : _set_title, 'lang' : _set_lang, 'dir' : _set_dir, 'className' : _set_className, }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), Element._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLFieldSetElement.py0100644000076400001440000000254007253474633020321 0ustar martinusers######################################################################## # # File Name: HTMLFieldSetElement # # Documentation: http://docs.4suite.com/4DOM/HTMLFieldSetElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLFieldSetElement(HTMLElement): def __init__(self, ownerDocument, nodeName="FIELDSET"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "form" : _get_form }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLFontElement.py0100644000076400001440000000334307253474633017532 0ustar martinusers######################################################################## # # File Name: HTMLFontElement # # Documentation: http://docs.4suite.com/4DOM/HTMLFontElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLFontElement(HTMLElement): def __init__(self, ownerDocument, nodeName="FONT"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_color(self): return self.getAttribute("COLOR") def _set_color(self, value): self.setAttribute("COLOR", value) def _get_face(self): return self.getAttribute("FACE") def _set_face(self, value): self.setAttribute("FACE", value) def _get_size(self): return self.getAttribute("SIZE") def _set_size(self, value): self.setAttribute("SIZE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "color" : _get_color, "face" : _get_face, "size" : _get_size }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "color" : _set_color, "face" : _set_face, "size" : _set_size }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLFormElement.py0100644000076400001440000000651307253474633017531 0ustar martinusers# # File Name: HTMLFormElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLFormElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import ext from xml.dom import implementation from xml.dom.html.HTMLElement import HTMLElement from xml.dom.html.HTMLCollection import HTMLCollection FORM_CHILDREN = ['INPUT', 'SELECT', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'LABEL', 'BUTTON', 'FIELDSET', 'LEGEND', 'OBJECT', 'ISINDEX' ] class HTMLFormElement(HTMLElement): def __init__(self, ownerDocument, nodeName='FORM'): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_acceptCharset(self): return self.getAttribute('ACCEPT-CHARSET') def _set_acceptCharset(self,acceptcharset): self.setAttribute('ACCEPT-CHARSET',acceptcharset) def _get_action(self): return self.getAttribute('ACTION') def _set_action(self,action): self.setAttribute('ACTION',action) def _get_elements(self): #Make a collection of control elements nl = self.getElementsByTagName('*') l = [] for child in nl: if child.tagName in FORM_CHILDREN: l.append(child) return implementation._4dom_createHTMLCollection(l) def _get_encType(self): return self.getAttribute('ENCTYPE') def _set_encType(self,enctype): self.setAttribute('ENCTYPE',enctype) def _get_length(self): return self._get_elements().length def _get_method(self): return string.capitalize(self.getAttribute('METHOD')) def _set_method(self,method): self.setAttribute('METHOD',method) def _get_name(self): return self.getAttribute('NAME') def _set_name(self,name): self.setAttribute('NAME',name) def _get_target(self): return self.getAttribute('TARGET') def _set_target(self,target): self.setAttribute('TARGET',target) ### Methods ### def reset(self): pass def submit(self): pass ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'acceptCharset' : _get_acceptCharset, 'action' : _get_action, 'elements' : _get_elements, 'encType' : _get_encType, 'length' : _get_length, 'method' : _get_method, 'name' : _get_name, 'target' : _get_target }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'acceptCharset' : _set_acceptCharset, 'action' : _set_action, 'encType' : _set_encType, 'method' : _set_method, 'name' : _set_name, 'target' : _set_target }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLFrameElement.py0100644000076400001440000000707107253474633017660 0ustar martinusers######################################################################## # # File Name: HTMLFrameElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLFrameElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom.html.HTMLElement import HTMLElement class HTMLFrameElement(HTMLElement): def __init__(self, ownerDocument, nodeName="FRAME"): HTMLElement.__init__(self, ownerDocument, nodeName) self.__content = None ### Attribute Methods ### def _get_contentDocument(self): if not self.__content: source = self._get_src() import os.path ext = os.path.splitext(source) if string.find(ext, 'htm') > 0: from xml.dom.ext.reader import HtmlLib self.__content = HtmlLib.FromHtmlUrl(source) elif string.lower(ext) == '.xml': from xml.dom.ext.reader import Sax2 self.__content = Sax2.FromXmlUrl(source) return self.__content def _get_frameBorder(self): return string.capitalize(self.getAttribute("FRAMEBORDER")) def _set_frameBorder(self, value): self.setAttribute("FRAMEBORDER", value) def _get_longDesc(self): return self.getAttribute("LONGDESC") def _set_longDesc(self, value): self.setAttribute("LONGDESC", value) def _get_marginHeight(self): return self.getAttribute("MARGINHEIGHT") def _set_marginHeight(self, value): self.setAttribute("MARGINHEIGHT", value) def _get_marginWidth(self): return self.getAttribute("MARGINWIDTH") def _set_marginWidth(self, value): self.setAttribute("MARGINWIDTH", value) def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_noResize(self): return self.hasAttribute("NORESIZE") def _set_noResize(self, value): if value: self.setAttribute("NORESIZE", "NORESIZE") else: self.removeAttribute("NORESIZE") def _get_scrolling(self): return string.capitalize(self.getAttribute("SCROLLING")) def _set_scrolling(self, value): self.setAttribute("SCROLLING", value) def _get_src(self): return self.getAttribute("SRC") def _set_src(self, value): self.setAttribute("SRC", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "contentDocument" : _get_contentDocument, "frameBorder" : _get_frameBorder, "longDesc" : _get_longDesc, "marginHeight" : _get_marginHeight, "marginWidth" : _get_marginWidth, "name" : _get_name, "noResize" : _get_noResize, "scrolling" : _get_scrolling, "src" : _get_src }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "frameBorder" : _set_frameBorder, "longDesc" : _set_longDesc, "marginHeight" : _set_marginHeight, "marginWidth" : _set_marginWidth, "name" : _set_name, "noResize" : _set_noResize, "scrolling" : _set_scrolling, "src" : _set_src }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLFrameSetElement.py0100644000076400001440000000304607253474633020332 0ustar martinusers######################################################################## # # File Name: HTMLFrameSetElement # # Documentation: http://docs.4suite.com/4DOM/HTMLFrameSetElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLFrameSetElement(HTMLElement): def __init__(self, ownerDocument, nodeName="FRAMESET"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_cols(self): return self.getAttribute("COLS") def _set_cols(self, value): self.setAttribute("COLS", value) def _get_rows(self): return self.getAttribute("ROWS") def _set_rows(self, value): self.setAttribute("ROWS", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "cols" : _get_cols, "rows" : _get_rows }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "cols" : _set_cols, "rows" : _set_rows }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLHRElement.py0100644000076400001440000000404707253474633017137 0ustar martinusers######################################################################## # # File Name: HTMLHRElement # # Documentation: http://docs.4suite.com/4DOM/HTMLHRElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLHRElement(HTMLElement): def __init__(self, ownerDocument, nodeName="HR"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) def _get_noShade(self): return self.hasAttribute("NOSHADE") def _set_noShade(self, value): if value: self.setAttribute("NOSHADE", "NOSHADE") else: self.removeAttribute("NOSHADE") def _get_size(self): return self.getAttribute("SIZE") def _set_size(self, value): self.setAttribute("SIZE", value) def _get_width(self): return self.getAttribute("WIDTH") def _set_width(self, value): self.setAttribute("WIDTH", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align, "noShade" : _get_noShade, "size" : _get_size, "width" : _get_width }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align, "noShade" : _set_noShade, "size" : _set_size, "width" : _set_width }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLHeadElement.py0100644000076400001440000000255107253474633017465 0ustar martinusers######################################################################## # # File Name: HTMLHeadElement # # Documentation: http://docs.4suite.com/4DOM/HTMLHeadElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLHeadElement(HTMLElement): def __init__(self, ownerDocument, nodeName="HEAD"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_profile(self): return self.getAttribute("PROFILE") def _set_profile(self, value): self.setAttribute("PROFILE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "profile" : _get_profile }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "profile" : _set_profile }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLHeadingElement.py0100644000076400001440000000255607253474633020170 0ustar martinusers######################################################################## # # File Name: HTMLHeadingElement # # Documentation: http://docs.4suite.com/4DOM/HTMLHeadingElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLHeadingElement(HTMLElement): def __init__(self, ownerDocument, nodeName): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLHtmlElement.py0100644000076400001440000000255107253474633017530 0ustar martinusers######################################################################## # # File Name: HTMLHtmlElement # # Documentation: http://docs.4suite.com/4DOM/HTMLHtmlElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLHtmlElement(HTMLElement): def __init__(self, ownerDocument, nodeName="HTML"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_version(self): return self.getAttribute("VERSION") def _set_version(self, value): self.setAttribute("VERSION", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "version" : _get_version }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "version" : _set_version }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLIFrameElement.py0100644000076400001440000000760407253474633017773 0ustar martinusers######################################################################## # # File Name: HTMLIFrameElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLIFrameElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom.html.HTMLElement import HTMLElement class HTMLIFrameElement(HTMLElement): def __init__(self, ownerDocument, nodeName="IFRAME"): HTMLElement.__init__(self, ownerDocument, nodeName) self.__content = None ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) def _get_contentDocument(self): if not self.__content: source = self._get_src() import os.path ext = os.path.splitext(source) if string.find(ext, 'htm') > 0: from xml.dom.ext.reader import HtmlLib self.__content = HtmlLib.FromHtmlUrl(source) elif string.lower(ext) == '.xml': from xml.dom.ext.reader import Sax2 self.__content = Sax2.FromXmlUrl(source) return self.__content def _get_frameBorder(self): return string.capitalize(self.getAttribute("FRAMEBORDER")) def _set_frameBorder(self, value): self.setAttribute("FRAMEBORDER", value) def _get_height(self): return self.getAttribute("HEIGHT") def _set_height(self, value): self.setAttribute("HEIGHT", value) def _get_longDesc(self): return self.getAttribute("LONGDESC") def _set_longDesc(self, value): self.setAttribute("LONGDESC", value) def _get_marginHeight(self): return self.getAttribute("MARGINHEIGHT") def _set_marginHeight(self, value): self.setAttribute("MARGINHEIGHT", value) def _get_marginWidth(self): return self.getAttribute("MARGINWIDTH") def _set_marginWidth(self, value): self.setAttribute("MARGINWIDTH", value) def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_scrolling(self): return string.capitalize(self.getAttribute("SCROLLING")) def _set_scrolling(self, value): self.setAttribute("SCROLLING", value) def _get_src(self): return self.getAttribute("SRC") def _set_src(self, value): self.setAttribute("SRC", value) def _get_width(self): return self.getAttribute("WIDTH") def _set_width(self, value): self.setAttribute("WIDTH", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align, "contentDocument" : _get_contentDocument, "frameBorder" : _get_frameBorder, "height" : _get_height, "longDesc" : _get_longDesc, "marginHeight" : _get_marginHeight, "marginWidth" : _get_marginWidth, "name" : _get_name, "scrolling" : _get_scrolling, "src" : _get_src, "Width" : _get_width }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align, "frameBorder" : _set_frameBorder, "height" : _set_height, "longDesc" : _set_longDesc, "marginHeight" : _set_marginHeight, "marginWidth" : _set_marginWidth, "name" : _set_name, "scrolling" : _set_scrolling, "src" : _set_src, "Width" : _set_width }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLImageElement.py0100644000076400001440000000757207253474633017656 0ustar martinusers######################################################################## # # File Name: HTMLImageElement # # Documentation: http://docs.4suite.com/4DOM/HTMLImageElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLImageElement(HTMLElement): def __init__(self, ownerDocument, nodeName="IMG"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_lowSrc(self): return self.getAttribute("LOWSRC") def _set_lowSrc(self, value): self.setAttribute("LOWSRC", value) def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) def _get_alt(self): return self.getAttribute("ALT") def _set_alt(self, value): self.setAttribute("ALT", value) def _get_border(self): return self.getAttribute("BORDER") def _set_border(self, value): self.setAttribute("BORDER", value) def _get_height(self): return self.getAttribute("HEIGHT") def _set_height(self, value): self.setAttribute("HEIGHT", value) def _get_hspace(self): return self.getAttribute("HSPACE") def _set_hspace(self, value): self.setAttribute("HSPACE", value) def _get_isMap(self): return self.hasAttribute("ISMAP") def _set_isMap(self, value): if value: self.setAttribute("ISMAP", "ISMAP") else: self.removeAttribute("ISMAP") def _get_longDesc(self): return self.getAttribute("LONGDESC") def _set_longDesc(self, value): self.setAttribute("LONGDESC", value) def _get_src(self): return self.getAttribute("SRC") def _set_src(self, value): self.setAttribute("SRC", value) def _get_useMap(self): return self.getAttribute("USEMAP") def _set_useMap(self, value): self.setAttribute("USEMAP", value) def _get_vspace(self): return self.getAttribute("VSPACE") def _set_vspace(self, value): self.setAttribute("VSPACE", value) def _get_width(self): return self.getAttribute("WIDTH") def _set_width(self, value): self.setAttribute("WIDTH", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "lowSrc" : _get_lowSrc, "name" : _get_name, "align" : _get_align, "alt" : _get_alt, "border" : _get_border, "height" : _get_height, "hspace" : _get_hspace, "isMap" : _get_isMap, "longDesc" : _get_longDesc, "src" : _get_src, "useMap" : _get_useMap, "vspace" : _get_vspace, "width" : _get_width }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "lowSrc" : _set_lowSrc, "name" : _set_name, "align" : _set_align, "alt" : _set_alt, "border" : _set_border, "height" : _set_height, "hspace" : _set_hspace, "isMap" : _set_isMap, "longDesc" : _set_longDesc, "src" : _set_src, "useMap" : _set_useMap, "vspace" : _set_vspace, "width" : _set_width }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLInputElement.py0100644000076400001440000001463607244340624017722 0ustar martinusers######################################################################## # # File Name: HTMLInputElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLInputElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom.html.HTMLElement import HTMLElement from xml.dom import InvalidAccessErr import string class HTMLInputElement(HTMLElement): def __init__(self, ownerDocument, nodeName='INPUT'): HTMLElement.__init__(self, ownerDocument, nodeName) def _get_accept(self): return self.getAttribute('ACCEPT') def _set_accept(self,accept): self.setAttribute('ACCEPT',accept) def _get_accessKey(self): return self.getAttribute('ACCESSKEY') def _set_accessKey(self,accessKey): self.setAttribute('ACCESSKEY',accessKey) def _get_align(self): return string.capitalize(self.getAttribute('ALIGN')) def _set_align(self,align): self.setAttribute('ALIGN',align) def _get_alt(self): return self.getAttribute('ALT') def _set_alt(self,alt): self.setAttribute('ALT',alt) def _get_checked(self): if self._get_type() in ['Radio', 'Checkbox']: return self.hasAttribute('CHECKED') else: raise InvalidAccessErr() def _set_checked(self,checked): if self._get_type() in ['Radio','Checkbox']: if checked: self.setAttribute('CHECKED', 'CHECKED') else: self.removeAttribute('CHECKED') else: raise InvalidAccessErr() def _get_defaultChecked(self): return self._get_checked() def _set_defaultChecked(self,checked): self._set_checked(checked) def _get_defaultValue(self): return self._get_value() def _set_defaultValue(self,value): self._set_value(value) def _get_disabled(self): return self.hasAttribute('DISABLED') def _set_disabled(self,disabled): if disabled: self.setAttribute('DISABLED', 'DISABLED') else: self.removeAttribute('DISABLED') def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None def _get_maxLength(self): if self._get_type() in ['Text','Password']: rt = self.getAttribute('MAXLENGTH') if rt: return int(rt) raise InvalidAccessErr() def _set_maxLength(self,maxLength): if self._get_type() in ['Text','Password']: self.setAttribute('MAXLENGTH',str(maxLength)) else: raise InvalidAccessErr() def _get_name(self): return self.getAttribute('NAME') def _set_name(self,name): self.setAttribute('NAME',name) def _get_readOnly(self): if self._get_type() in ['Text','Password']: return self.hasAttribute('READONLY') raise InvalidAccessErr() def _set_readOnly(self,readOnly): if self._get_type() in ['Text','Password']: if readOnly: self.setAttribute('READONLY', 'READONLY') else: self.removeAttribute('READONLY') else: raise InvalidAccessErr() def _get_size(self): return self.getAttribute('SIZE') def _set_size(self,size): self.setAttribute('SIZE',size) def _get_src(self): if self._get_type() == 'Image': return self.getAttribute('SRC') else: raise InvalidAccessErr() def _set_src(self,src): if self._get_type() == 'Image': self.setAttribute('SRC',src) else: raise InvalidAccessErr() def _get_tabIndex(self): rt = self.getAttribute('TABINDEX') if rt: return int(rt) return -1 def _set_tabIndex(self,tabIndex): self.setAttribute('TABINDEX',str(tabIndex)) def _get_type(self): return string.capitalize(self.getAttribute('TYPE')) def _get_useMap(self): return self.getAttribute('USEMAP') def _set_useMap(self,useMap): self.setAttribute('USEMAP',useMap) def _get_value(self): return self.getAttribute('VALUE') def _set_value(self,value): self.setAttribute('VALUE',value) ### Methods ### def blur(self): pass def click(self): pass def focus(self): pass def select(self): pass ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'accept' : _get_accept, 'accessKey' : _get_accessKey, 'align' : _get_align, 'alt' : _get_alt, 'checked' : _get_checked, 'defaultChecked' : _get_defaultChecked, 'defaultValue' : _get_defaultValue, 'disabled' : _get_disabled, 'form' : _get_form, 'maxLength' : _get_maxLength, 'name' : _get_name, 'readOnly' : _get_readOnly, 'size' : _get_size, 'src' : _get_src, 'tabIndex' : _get_tabIndex, 'type' : _get_type, 'useMap' : _get_useMap, 'value' : _get_value, }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'accept' : _set_accept, 'accessKey' : _set_accessKey, 'align' : _set_align, 'alt' : _set_alt, 'checked' : _set_checked, 'defaultChecked' : _set_defaultChecked, 'defaultValue' : _set_defaultValue, 'disabled' : _set_disabled, 'maxLength' : _set_maxLength, 'name' : _set_name, 'readOnly' : _set_readOnly, 'size' : _set_size, 'src' : _set_src, 'tabIndex' : _set_tabIndex, 'useMap' : _set_useMap, 'value' : _set_value, }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLIsIndexElement.py0100644000076400001440000000313507253474633020166 0ustar martinusers######################################################################## # # File Name: HTMLIsIndexElement # # Documentation: http://docs.4suite.com/4DOM/HTMLIsIndexElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLIsIndexElement(HTMLElement): def __init__(self, ownerDocument, nodeName="ISINDEX"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None def _get_prompt(self): return self.getAttribute("PROMPT") def _set_prompt(self, value): self.setAttribute("PROMPT", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "form" : _get_form, "prompt" : _get_prompt }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "prompt" : _set_prompt }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLLIElement.py0100644000076400001440000000313507253474633017127 0ustar martinusers######################################################################## # # File Name: HTMLLIElement # # Documentation: http://docs.4suite.com/4DOM/HTMLLIElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLLIElement(HTMLElement): def __init__(self, ownerDocument, nodeName="LI"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) def _get_value(self): value = self.getAttribute("VALUE") if value: return int(value) return 0 def _set_value(self, value): self.setAttribute("VALUE", str(value)) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "type" : _get_type, "value" : _get_value }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "type" : _set_type, "value" : _set_value }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLLabelElement.py0100644000076400001440000000350207253474633017640 0ustar martinusers######################################################################## # # File Name: HTMLLabelElement # # Documentation: http://docs.4suite.com/4DOM/HTMLLabelElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLLabelElement(HTMLElement): def __init__(self, ownerDocument, nodeName="LABEL"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_accessKey(self): return self.getAttribute("ACCESSKEY") def _set_accessKey(self, value): self.setAttribute("ACCESSKEY", value) def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None def _get_htmlFor(self): return self.getAttribute("FOR") def _set_htmlFor(self, value): self.setAttribute("FOR", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "accessKey" : _get_accessKey, "form" : _get_form, "htmlFor" : _get_htmlFor }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "accessKey" : _set_accessKey, "htmlFor" : _set_htmlFor }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLLegendElement.py0100644000076400001440000000352107253474633020020 0ustar martinusers######################################################################## # # File Name: HTMLLegendElement # # Documentation: http://docs.4suite.com/4DOM/HTMLLegendElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLLegendElement(HTMLElement): def __init__(self, ownerDocument, nodeName="LEGEND"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_accessKey(self): return self.getAttribute("ACCESSKEY") def _set_accessKey(self, value): self.setAttribute("ACCESSKEY", value) def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "accessKey" : _get_accessKey, "align" : _get_align, "form" : _get_form }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "accessKey" : _set_accessKey, "align" : _set_align }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLLinkElement.py0100644000076400001440000000605707253474633017526 0ustar martinusers######################################################################## # # File Name: HTMLLinkElement # # Documentation: http://docs.4suite.com/4DOM/HTMLLinkElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLLinkElement(HTMLElement): def __init__(self, ownerDocument, nodeName="LINK"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_disabled(self): return self.hasAttribute("DISABLED") def _set_disabled(self, value): if value: self.setAttribute("DISABLED", "DISABLED") else: self.removeAttribute("DISABLED") def _get_charset(self): return self.getAttribute("CHARSET") def _set_charset(self, value): self.setAttribute("CHARSET", value) def _get_href(self): return self.getAttribute("HREF") def _set_href(self, value): self.setAttribute("HREF", value) def _get_hreflang(self): return self.getAttribute("HREFLANG") def _set_hreflang(self, value): self.setAttribute("HREFLANG", value) def _get_media(self): return self.getAttribute("MEDIA") def _set_media(self, value): self.setAttribute("MEDIA", value) def _get_rel(self): return self.getAttribute("REL") def _set_rel(self, value): self.setAttribute("REL", value) def _get_rev(self): return self.getAttribute("REV") def _set_rev(self, value): self.setAttribute("REV", value) def _get_target(self): return self.getAttribute("TARGET") def _set_target(self, value): self.setAttribute("TARGET", value) def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "disabled" : _get_disabled, "charset" : _get_charset, "href" : _get_href, "hreflang" : _get_hreflang, "media" : _get_media, "rel" : _get_rel, "rev" : _get_rev, "target" : _get_target, "type" : _get_type }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "disabled" : _set_disabled, "charset" : _set_charset, "href" : _set_href, "hreflang" : _set_hreflang, "media" : _set_media, "rel" : _set_rel, "rev" : _set_rev, "target" : _set_target, "type" : _set_type }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLMapElement.py0100644000076400001440000000265407222740242017331 0ustar martinusers######################################################################## # # File Name: HTMLMapElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLMapElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom.html.HTMLElement import HTMLElement from xml.dom import implementation class HTMLMapElement(HTMLElement): def __init__(self, ownerDocument, nodeName='MAP'): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_areas(self): rt = self.getElementsByTagName('AREA') return implementation._4dom_createHTMLCollection(rt) def _get_name(self): return self.getAttribute('NAME') def _set_name(self,name): self.setAttribute('NAME',name) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'areas' : _get_areas, 'name' : _get_name }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'name' : _set_name }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLMenuElement.py0100644000076400001440000000267507253474633017537 0ustar martinusers######################################################################## # # File Name: HTMLMenuElement # # Documentation: http://docs.4suite.com/4DOM/HTMLMenuElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLMenuElement(HTMLElement): def __init__(self, ownerDocument, nodeName="MENU"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_compact(self): return self.hasAttribute("COMPACT") def _set_compact(self, value): if value: self.setAttribute("COMPACT", "COMPACT") else: self.removeAttribute("COMPACT") ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "compact" : _get_compact }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "compact" : _set_compact }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLMetaElement.py0100644000076400001440000000376207253474633017517 0ustar martinusers######################################################################## # # File Name: HTMLMetaElement # # Documentation: http://docs.4suite.com/4DOM/HTMLMetaElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLMetaElement(HTMLElement): def __init__(self, ownerDocument, nodeName="META"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_content(self): return self.getAttribute("CONTENT") def _set_content(self, value): self.setAttribute("CONTENT", value) def _get_httpEquiv(self): return self.getAttribute("HTTP-EQUIV") def _set_httpEquiv(self, value): self.setAttribute("HTTP-EQUIV", value) def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_scheme(self): return self.getAttribute("SCHEME") def _set_scheme(self, value): self.setAttribute("SCHEME", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "content" : _get_content, "httpEquiv" : _get_httpEquiv, "name" : _get_name, "scheme" : _get_scheme }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "content" : _set_content, "httpEquiv" : _set_httpEquiv, "name" : _set_name, "scheme" : _set_scheme }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLModElement.py0100644000076400001440000000306207253474633017341 0ustar martinusers######################################################################## # # File Name: HTMLModElement # # Documentation: http://docs.4suite.com/4DOM/HTMLModElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLModElement(HTMLElement): def __init__(self, ownerDocument, nodeName="MOD"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_cite(self): return self.getAttribute("CITE") def _set_cite(self, value): self.setAttribute("CITE", value) def _get_dateTime(self): return self.getAttribute("DATETIME") def _set_dateTime(self, value): self.setAttribute("DATETIME", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "cite" : _get_cite, "dateTime" : _get_dateTime }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "cite" : _set_cite, "dateTime" : _set_dateTime }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLOListElement.py0100644000076400001440000000362707253474633017663 0ustar martinusers######################################################################## # # File Name: HTMLOListElement # # Documentation: http://docs.4suite.com/4DOM/HTMLOListElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLOListElement(HTMLElement): def __init__(self, ownerDocument, nodeName="OL"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_compact(self): return self.hasAttribute("COMPACT") def _set_compact(self, value): if value: self.setAttribute("COMPACT", "COMPACT") else: self.removeAttribute("COMPACT") def _get_start(self): value = self.getAttribute("START") if value: return int(value) return 0 def _set_start(self, value): self.setAttribute("START", str(value)) def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "compact" : _get_compact, "start" : _get_start, "type" : _get_type }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "compact" : _set_compact, "start" : _set_start, "type" : _set_type }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLObjectElement.py0100644000076400001440000001227407253474633020035 0ustar martinusers######################################################################## # # File Name: HTMLObjectElement # # Documentation: http://docs.4suite.com/4DOM/HTMLObjectElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLObjectElement(HTMLElement): def __init__(self, ownerDocument, nodeName="OBJECT"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) def _get_archive(self): return self.getAttribute("ARCHIVE") def _set_archive(self, value): self.setAttribute("ARCHIVE", value) def _get_border(self): return self.getAttribute("BORDER") def _set_border(self, value): self.setAttribute("BORDER", value) def _get_code(self): return self.getAttribute("CODE") def _set_code(self, value): self.setAttribute("CODE", value) def _get_codeBase(self): return self.getAttribute("CODEBASE") def _set_codeBase(self, value): self.setAttribute("CODEBASE", value) def _get_codeType(self): return self.getAttribute("CODETYPE") def _set_codeType(self, value): self.setAttribute("CODETYPE", value) def _get_contentDocument(self): return "None" def _get_data(self): return self.getAttribute("DATA") def _set_data(self, value): self.setAttribute("DATA", value) def _get_declare(self): return self.hasAttribute("DECLARE") def _set_declare(self, value): if value: self.setAttribute("DECLARE", "DECLARE") else: self.removeAttribute("DECLARE") def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None def _get_height(self): return self.getAttribute("HEIGHT") def _set_height(self, value): self.setAttribute("HEIGHT", value) def _get_hspace(self): return self.getAttribute("HSPACE") def _set_hspace(self, value): self.setAttribute("HSPACE", value) def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_standby(self): return self.getAttribute("STANDBY") def _set_standby(self, value): self.setAttribute("STANDBY", value) def _get_tabIndex(self): value = self.getAttribute("TABINDEX") if value: return int(value) return 0 def _set_tabIndex(self, value): self.setAttribute("TABINDEX", str(value)) def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) def _get_useMap(self): return self.getAttribute("USEMAP") def _set_useMap(self, value): self.setAttribute("USEMAP", value) def _get_vspace(self): return self.getAttribute("VSPACE") def _set_vspace(self, value): self.setAttribute("VSPACE", value) def _get_width(self): return self.getAttribute("WIDTH") def _set_width(self, value): self.setAttribute("WIDTH", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align, "archive" : _get_archive, "border" : _get_border, "code" : _get_code, "codeBase" : _get_codeBase, "codeType" : _get_codeType, "contentDocument" : _get_contentDocument, "data" : _get_data, "declare" : _get_declare, "form" : _get_form, "height" : _get_height, "hspace" : _get_hspace, "name" : _get_name, "standby" : _get_standby, "tabIndex" : _get_tabIndex, "type" : _get_type, "useMap" : _get_useMap, "vspace" : _get_vspace, "width" : _get_width }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align, "archive" : _set_archive, "border" : _set_border, "code" : _set_code, "codeBase" : _set_codeBase, "codeType" : _set_codeType, "data" : _set_data, "declare" : _set_declare, "height" : _set_height, "hspace" : _set_hspace, "name" : _set_name, "standby" : _set_standby, "tabIndex" : _set_tabIndex, "type" : _set_type, "useMap" : _set_useMap, "vspace" : _set_vspace, "width" : _set_width }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLOptGroupElement.py0100644000076400001440000000324407253474633020403 0ustar martinusers######################################################################## # # File Name: HTMLOptGroupElement # # Documentation: http://docs.4suite.com/4DOM/HTMLOptGroupElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLOptGroupElement(HTMLElement): def __init__(self, ownerDocument, nodeName="OPTGROUP"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_disabled(self): return self.hasAttribute("DISABLED") def _set_disabled(self, value): if value: self.setAttribute("DISABLED", "DISABLED") else: self.removeAttribute("DISABLED") def _get_label(self): return self.getAttribute("LABEL") def _set_label(self, value): self.setAttribute("LABEL", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "disabled" : _get_disabled, "label" : _get_label }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "disabled" : _set_disabled, "label" : _set_label }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLOptionElement.py0100644000076400001440000000722107244340624020063 0ustar martinusers######################################################################## # # File Name: HTMLOptionElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLOptionElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom.html.HTMLElement import HTMLElement from xml.dom import Node class HTMLOptionElement(HTMLElement): def __init__(self, ownerDocument, nodeName='OPTION'): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_defaultSelected(self): return self._get_selected() def _set_defaultSelected(self, selected): self._set_selected(selected) def _get_disabled(self): return self.getAttributeNode('DISABLED') and 1 or 0 def _set_disabled(self,disabled): if disabled: self.setAttribute('DISABLED', 'DISABLED') else: self.removeAttribute('DISABLED') def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None def _get_index(self): p = self.parentNode if p.tagName != 'SELECT': return -1 options = p._get_options() try: return options.index(self) except: return -1 def _get_label(self): return self.getAttribute('LABEL') def _set_label(self,label): self.setAttribute('LABEL',label) def _get_selected(self): return self.hasAttribute('SELECTED') def _set_selected(self, selected): if selected: self.setAttribute('SELECTED', 'SELECTED') else: self.removeAttribute('SELECTED') def _get_text(self): if not self.firstChild: return if self.firstChild == self.lastChild: return self.firstChild.data self.normalize() text = filter(lambda x: x.nodeType == Node.TEXT_NODE, self.childNodes) return text[0].data def _set_text(self, value): text = None for node in self.childNodes: if not text and node.nodeType == Node.TEXT_NODE: text = node else: self.removeChild(node) if text: text.data = value else: text = self.ownerDocument.createTextNode(value) self.appendChild(text) def _get_value(self): return self.getAttribute('VALUE') def _set_value(self,value): self.setAttribute('VALUE',value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'defaultSelected' : _get_defaultSelected, 'disabled' : _get_disabled, 'form' : _get_form, 'index' : _get_index, 'label' : _get_label, 'selected' : _get_selected, 'text' : _get_text, 'value' : _get_value, }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'defaultSelected' : _set_defaultSelected, 'disabled' : _set_disabled, 'label' : _set_label, 'selected' : _set_selected, 'value' : _set_value, }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLParagraphElement.py0100644000076400001440000000257007253474633020532 0ustar martinusers######################################################################## # # File Name: HTMLParagraphElement # # Documentation: http://docs.4suite.com/4DOM/HTMLParagraphElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLParagraphElement(HTMLElement): def __init__(self, ownerDocument, nodeName="P"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLParamElement.py0100644000076400001440000000374707253474633017674 0ustar martinusers######################################################################## # # File Name: HTMLParamElement # # Documentation: http://docs.4suite.com/4DOM/HTMLParamElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLParamElement(HTMLElement): def __init__(self, ownerDocument, nodeName="PARAM"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) def _get_value(self): return self.getAttribute("VALUE") def _set_value(self, value): self.setAttribute("VALUE", value) def _get_valueType(self): return string.capitalize(self.getAttribute("VALUETYPE")) def _set_valueType(self, value): self.setAttribute("VALUETYPE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "name" : _get_name, "type" : _get_type, "value" : _get_value, "valueType" : _get_valueType }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "name" : _set_name, "type" : _set_type, "value" : _set_value, "valueType" : _set_valueType }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLPreElement.py0100644000076400001440000000263407253474633017354 0ustar martinusers######################################################################## # # File Name: HTMLPreElement # # Documentation: http://docs.4suite.com/4DOM/HTMLPreElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLPreElement(HTMLElement): def __init__(self, ownerDocument, nodeName="PRE"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_width(self): value = self.getAttribute("WIDTH") if value: return int(value) return 0 def _set_width(self, value): self.setAttribute("WIDTH", str(value)) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "width" : _get_width }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "width" : _set_width }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLQuoteElement.py0100644000076400001440000000251507253474633017721 0ustar martinusers######################################################################## # # File Name: HTMLQuoteElement # # Documentation: http://docs.4suite.com/4DOM/HTMLQuoteElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLQuoteElement(HTMLElement): def __init__(self, ownerDocument, nodeName): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_cite(self): return self.getAttribute("CITE") def _set_cite(self, value): self.setAttribute("CITE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "cite" : _get_cite }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "cite" : _set_cite }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLScriptElement.py0100644000076400001440000000623107253474633020067 0ustar martinusers######################################################################## # # File Name: HTMLScriptElement # # Documentation: http://docs.4suite.com/4DOM/HTMLScriptElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLScriptElement(HTMLElement): def __init__(self, ownerDocument, nodeName="SCRIPT"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_charset(self): return self.getAttribute("CHARSET") def _set_charset(self, value): self.setAttribute("CHARSET", value) def _get_defer(self): return self.hasAttribute("DEFER") def _set_defer(self, value): if value: self.setAttribute("DEFER", "DEFER") else: self.removeAttribute("DEFER") def _get_event(self): return self.getAttribute("EVENT") def _set_event(self, value): self.setAttribute("EVENT", value) def _get_htmlFor(self): return self.getAttribute("FOR") def _set_htmlFor(self, value): self.setAttribute("FOR", value) def _get_src(self): return self.getAttribute("SRC") def _set_src(self, value): self.setAttribute("SRC", value) def _get_text(self): if not self.firstChild: return if self.firstChild == self.lastChild: return self.firstChild.data self.normalize() text = filter(lambda x: x.nodeType == Node.TEXT_NODE, self.childNodes) return text[0].data def _set_text(self, value): text = None for node in self.childNodes: if not text and node.nodeType == Node.TEXT_NODE: text = node else: self.removeChild(node) if text: text.data = value else: text = self.ownerDocument.createTextNode(value) self.appendChild(text) def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "charset" : _get_charset, "defer" : _get_defer, "event" : _get_event, "htmlFor" : _get_htmlFor, "src" : _get_src, "text" : _get_text, "type" : _get_type }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "charset" : _set_charset, "defer" : _set_defer, "event" : _set_event, "htmlFor" : _set_htmlFor, "src" : _set_src, "text" : _set_text, "type" : _set_type }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLSelectElement.py0100644000076400001440000001133407244340624020032 0ustar martinusers######################################################################## # # File Name: HTMLSelectElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLSelectElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import implementation from xml.dom import IndexSizeErr from xml.dom.html.HTMLElement import HTMLElement import string class HTMLSelectElement(HTMLElement): def __init__(self, ownerDocument, nodeName='SELECT'): HTMLElement.__init__(self, ownerDocument, nodeName) def _get_type(self): if self._get_multiple(): return 'select-multiple' return 'select-one' def _get_selectedIndex(self): options = self._get_options() for ctr in range(len(options)): node = options.item(ctr) if node._get_selected() == 1: return ctr return -1 def _set_selectedIndex(self,index): options = self._get_options() if index < 0 or index >= len(options): raise IndexSizeErr() for ctr in range(len(options)): node = options.item(ctr) if ctr == index: node._set_selected(1) else: node._set_selected(0) def _get_value(self): options = self._get_options() node = options.item(self._get_selectedIndex()) if node.hasAttribute('VALUE'): value = node.getAttribute('VALUE') elif node.firstChild: value = node.firstChild.data else: value = '' return value def _set_value(self,value): # This doesn't seem to do anything in browsers pass def _get_length(self): return self._get_options()._get_length() def _get_options(self): children = self.getElementsByTagName('OPTION') return implementation._4dom_createHTMLCollection(children) def _get_disabled(self): if self.getAttributeNode('DISABLED'): return 1 return 0 def _set_disabled(self,disabled): if disabled: self.setAttribute('DISABLED', 'DISABLED') else: self.removeAttribute('DISABLED') def _get_multiple(self): if self.getAttributeNode('MULTIPLE'): return 1 return 0 def _set_multiple(self,mult): if mult: self.setAttribute('MULTIPLE', 'MULTIPLE') else: self.removeAttribute('MULTIPLE') def _get_name(self): return self.getAttribute('NAME') def _set_name(self,name): self.setAttribute('NAME',name) def _get_size(self): rt = self.getAttribute('SIZE') if rt != None: return string.atoi(rt) return -1 def _set_size(self,size): self.setAttribute('SIZE',str(size)) def _get_tabIndex(self): return string.atoi(self.getAttribute('TABINDEX')) def _set_tabIndex(self,tabindex): self.setAttribute('TABINDEX',str(tabindex)) def add(self,newElement,beforeElement): self.insertBefore(newElement,beforeElement) def remove(self,index): if index < 0 or index >= self._get_length: return hc = self._get_options() node = hc.item(index) self.removeChild(node) def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'type' : _get_type, 'length' : _get_length, 'options' : _get_options, 'form' : _get_form, 'selectedIndex' : _get_selectedIndex, 'value' : _get_value, 'disabled' : _get_disabled, 'multiple' : _get_multiple, 'name' : _get_name, 'size' : _get_size, 'tabIndex' : _get_tabIndex, }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'selectedIndex' : _set_selectedIndex, 'value' : _set_value, 'disabled' : _set_disabled, 'multiple' : _set_multiple, 'name' : _set_name, 'size' : _set_size, 'tabIndex' : _set_tabIndex, }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLStyleElement.py0100644000076400001440000000353507253474633017727 0ustar martinusers######################################################################## # # File Name: HTMLStyleElement # # Documentation: http://docs.4suite.com/4DOM/HTMLStyleElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLStyleElement(HTMLElement): def __init__(self, ownerDocument, nodeName="STYLE"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_disabled(self): return self.hasAttribute("DISABLED") def _set_disabled(self, value): if value: self.setAttribute("DISABLED", "DISABLED") else: self.removeAttribute("DISABLED") def _get_media(self): return self.getAttribute("MEDIA") def _set_media(self, value): self.setAttribute("MEDIA", value) def _get_type(self): return self.getAttribute("TYPE") def _set_type(self, value): self.setAttribute("TYPE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "disabled" : _get_disabled, "media" : _get_media, "type" : _get_type }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "disabled" : _set_disabled, "media" : _set_media, "type" : _set_type }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTableCaptionElement.py0100644000076400001440000000260707253474633021173 0ustar martinusers######################################################################## # # File Name: HTMLTableCaptionElement # # Documentation: http://docs.4suite.com/4DOM/HTMLTableCaptionElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLTableCaptionElement(HTMLElement): def __init__(self, ownerDocument, nodeName="CAPTION"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTableCellElement.py0100644000076400001440000001123507244340624020442 0ustar martinusers######################################################################## # # File Name: HTMLTableCellElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLTableCellElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom.html.HTMLElement import HTMLElement class HTMLTableCellElement(HTMLElement): def __init__(self, ownerDocument, nodeName='TD'): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_abbr(self): return self.getAttribute('ABBR') def _set_abbr(self,abbr): self.setAttribute('ABBR',abbr) def _get_align(self): return string.capitalize(self.getAttribute('ALIGN')) def _set_align(self, align): self.setAttribute('ALIGN', align) def _get_axis(self): return self.getAttribute('AXIS') def _set_axis(self, axis): self.setAttribute('AXIS', axis) def _get_bgColor(self): return self.getAttribute('BGCOLOR') def _set_bgColor(self, color): self.setAttribute('BGCOLOR', color) def _get_cellIndex(self): #We need to find the TR we are in if self.parentNode == None: return -1 cells = self.parentNode._get_cells() return cells.index(self) def _get_ch(self): return self.getAttribute('CHAR') def _set_ch(self,ch): self.setAttribute('CHAR',ch) def _get_chOff(self): return self.getAttribute('CHAROFF') def _set_chOff(self, offset): self.setAttribute('CHAROFF', offset) def _get_colSpan(self): value = self.getAttribute('COLSPAN') if value: return int(value) return 1 def _set_colSpan(self, span): self.setAttribute('COLSPAN',str(span)) def _get_headers(self): return self.getAttribute('HEADERS') def _set_headers(self,headers): self.setAttribute('HEADERS',headers) def _get_height(self): return self.getAttribute('HEIGHT') def _set_height(self,height): self.setAttribute('HEIGHT',height) def _get_noWrap(self): return self.hasAttribute('NOWRAP') def _set_noWrap(self,nowrap): if nowrap: self.setAttribute('NOWRAP', 'NOWRAP') else: self.removeAttribute('NOWRAP') def _get_rowSpan(self): value = self.getAttribute('ROWSPAN') if value: return int(value) return 1 def _set_rowSpan(self, span): self.setAttribute('ROWSPAN', str(span)) def _get_scope(self): return string.capitalize(self.getAttribute('SCOPE')) def _set_scope(self, scope): self.setAttribute('SCOPE', scope) def _get_vAlign(self): return string.capitalize(self.getAttribute('VALIGN')) def _set_vAlign(self, valign): self.setAttribute('VALIGN', valign) def _get_width(self): return self.getAttribute('WIDTH') def _set_width(self, width): self.setAttribute('WIDTH', width) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'cellIndex' : _get_cellIndex, 'abbr' : _get_abbr, 'align' : _get_align, 'axis' : _get_axis, 'bgColor' : _get_bgColor, 'ch' : _get_ch, 'chOff' : _get_chOff, 'colSpan' : _get_colSpan, 'headers' : _get_headers, 'height' : _get_height, 'noWrap' : _get_noWrap, 'rowSpan' : _get_rowSpan, 'scope' : _get_scope, 'vAlign' : _get_vAlign, 'width' : _get_width, }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'abbr' : _set_abbr, 'align' : _set_align, 'axis' : _set_axis, 'bgColor' : _set_bgColor, 'ch' : _set_ch, 'chOff' : _set_chOff, 'colSpan' : _set_colSpan, 'headers' : _set_headers, 'height' : _set_height, 'noWrap' : _set_noWrap, 'rowSpan' : _set_rowSpan, 'scope' : _set_scope, 'vAlign' : _set_vAlign, 'width' : _set_width, }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTableColElement.py0100644000076400001440000000470207253474633020311 0ustar martinusers######################################################################## # # File Name: HTMLTableColElement # # Documentation: http://docs.4suite.com/4DOM/HTMLTableColElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLTableColElement(HTMLElement): def __init__(self, ownerDocument, nodeName="COL"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute("ALIGN")) def _set_align(self, value): self.setAttribute("ALIGN", value) def _get_ch(self): return self.getAttribute("CHAR") def _set_ch(self, value): self.setAttribute("CHAR", value) def _get_chOff(self): return self.getAttribute("CHAROFF") def _set_chOff(self, value): self.setAttribute("CHAROFF", value) def _get_span(self): value = self.getAttribute("SPAN") if value: return int(value) return 0 def _set_span(self, value): self.setAttribute("SPAN", str(value)) def _get_vAlign(self): return string.capitalize(self.getAttribute("VALIGN")) def _set_vAlign(self, value): self.setAttribute("VALIGN", value) def _get_width(self): return self.getAttribute("WIDTH") def _set_width(self, value): self.setAttribute("WIDTH", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "align" : _get_align, "ch" : _get_ch, "chOff" : _get_chOff, "span" : _get_span, "vAlign" : _get_vAlign, "width" : _get_width }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "align" : _set_align, "ch" : _set_ch, "chOff" : _set_chOff, "span" : _set_span, "vAlign" : _set_vAlign, "width" : _set_width }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTableElement.py0100644000076400001440000002175207212031635017641 0ustar martinusers######################################################################## # # File Name: HTMLTableElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLTableElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom.html.HTMLElement import HTMLElement from xml.dom import IndexSizeErr from xml.dom import implementation from xml.dom.NodeFilter import NodeFilter import string class HTMLTableElement(HTMLElement): """ Operations follow the DOM spec, and the 4.0 DTD for TABLE """ def __init__(self, ownerDocument, nodeName='TABLE'): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute('ALIGN')) def _set_align(self,align): self.setAttribute('ALIGN',align) def _get_bgColor(self): return self.getAttribute('BGCOLOR') def _set_bgColor(self,bgcolor): self.setAttribute('BGCOLOR',bgcolor) def _get_border(self): return self.getAttribute('BORDER') def _set_border(self,border): self.setAttribute('BORDER',border) def _get_caption(self): nl = self.getElementsByTagName('CAPTION') if len(nl): return nl[0] return None def _set_caption(self,capt): nl = self.getElementsByTagName('CAPTION') if len(nl): self.replaceChild(capt, nl[0]) else: self.insertBefore(capt, self.firstChild) def _get_cellPadding(self): return self.getAttribute('CELLPADDING') def _set_cellPadding(self,cellpadding): self.setAttribute('CELLPADDING',cellpadding) def _get_cellSpacing(self): return self.getAttribute('CELLSPACING') def _set_cellSpacing(self,cellspacing): self.setAttribute('CELLSPACING',cellspacing) def _get_frame(self): return string.capitalize(self.getAttribute('FRAME')) def _set_frame(self,frame): self.setAttribute('FRAME',frame) def _get_rows(self): rows = [] tHead = self._get_tHead() if tHead: rows.extend(list(tHead._get_rows())) tFoot = self._get_tFoot() if tFoot: rows.extend(list(tFoot._get_rows())) for tb in self._get_tBodies(): rows.extend(list(tb._get_rows())) return implementation._4dom_createHTMLCollection(rows) def _get_rules(self): return string.capitalize(self.getAttribute('RULES')) def _set_rules(self,rules): self.setAttribute('RULES',rules) def _get_summary(self): return self.getAttribute('SUMMARY') def _set_summary(self,summary): self.setAttribute('SUMMARY',summary) def _get_tBodies(self): bodies = [] for child in self.childNodes: if child.nodeName == 'TBODY': bodies.append(child) return implementation._4dom_createHTMLCollection(bodies) def _get_tFoot(self): for child in self.childNodes: if child.nodeName == 'TFOOT': return child return None def _set_tFoot(self, newFooter): oldFooter = self._get_tFoot() if not oldFooter: # TFoot goes after THead iter = self.ownerDocument.createNodeIterator(self.firstChild, NodeFilter.SHOW_ELEMENT, None, 0) ref = None node = iter.nextNode() while not ref and node: tagName = node.tagName if tagName == 'THEAD': ref = iter.nextNode() elif tagName == 'TBODY': ref = node node = iter.nextNode() self.insertBefore(newFooter, ref) else: self.replaceChild(newFooter, oldFooter) def _get_tHead(self): for child in self.childNodes: if child.nodeName == 'THEAD': return child return None def _set_tHead(self, newHead): oldHead = self._get_tHead() if oldHead: self.replaceChild(newHead, oldHead) else: # We need to put the new Thead in the correct spot # Look for a TFOOT or a TBODY iter = self.ownerDocument.createNodeIterator(self.firstChild, NodeFilter.SHOW_ELEMENT, None, 0) ref = None node = iter.nextNode() while not ref and node: tagName = node.tagName if tagName == 'TFOOT': ref = node elif tagName == 'TBODY': ref = node elif tagName in ['COL','COLGROUP']: node = iter.nextNode() while node.tagName == tagName: node = iter.nextNode() ref = node elif tagName == 'CAPTION': ref = iter.nextNode() node = iter.nextNode() self.insertBefore(newHead, ref) def _get_width(self): return self.getAttribute('WIDTH') def _set_width(self,width): self.setAttribute('WIDTH',width) ### Methods ### def createCaption(self): #Create a new CAPTION if one does not exist caption = self._get_caption() if not caption: caption = self.ownerDocument.createElement('CAPTION') self._set_caption(caption) return caption def createTHead(self): #Create a new THEAD if one does not exist thead = self._get_tHead() if not thead: thead = self.ownerDocument.createElement('THEAD') self._set_tHead(thead) return thead def createTFoot(self): #Create a new TFOOT if one does not exist tfoot = self._get_tFoot() if not tfoot: tfoot = self.ownerDocument.createElement('TFOOT') self._set_tFoot(tfoot) return tfoot def deleteCaption(self): caption = self._get_caption() if caption: self.removeChild(caption) def deleteRow(self,index): rows = self._get_rows() if index < 0 or index >= len(rows): raise IndexSizeErr() rows[index].parentNode.removeChild(rows[index]) def deleteTHead(self): thead = self._get_tHead() if thead != None: self.removeChild(thead) def deleteTFoot(self): tfoot = self._get_tFoot() if tfoot: self.removeChild(tfoot) def insertRow(self,index): rows = self._get_rows() if index < 0 or index > len(rows): raise IndexSizeErr() newRow = self.ownerDocument.createElement('TR') if not rows: # An empty table, create a body in which to insert the row body = self.ownerDocument.createElement('TBODY') # The body is the last element according to DTD self.appendChild(body) parent = body ref = None elif index == len(rows): parent = rows[-1].parentNode ref = None else: ref = rows[index] parent = ref.parentNode return parent.insertBefore(newRow, ref) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'rows' : _get_rows, 'tBodies' : _get_tBodies, 'caption' : _get_caption, 'tHead' : _get_tHead, 'tFoot' : _get_tFoot, 'align' : _get_align, 'bgColor' : _get_bgColor, 'border' : _get_border, 'cellPadding' : _get_cellPadding, 'cellSpacing' : _get_cellSpacing, 'frame' : _get_frame, 'rules' : _get_rules, 'summary' : _get_summary, 'width' : _get_width, }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'caption' : _set_caption, 'tHead' : _set_tHead, 'tFoot' : _set_tFoot, 'align' : _set_align, 'bgColor' : _set_bgColor, 'border' : _set_border, 'cellPadding' : _set_cellPadding, 'cellSpacing' : _set_cellSpacing, 'frame' : _set_frame, 'rules' : _set_rules, 'summary' : _set_summary, 'width' : _set_width, }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTableRowElement.py0100644000076400001440000000731707217436116020342 0ustar martinusers######################################################################## # # File Name: HTMLTableRowElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLTableRowElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import implementation from xml.dom import IndexSizeErr from xml.dom.html.HTMLElement import HTMLElement class HTMLTableRowElement(HTMLElement): def __init__(self, ownerDocument, nodeName='TR'): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute('ALIGN')) def _set_align(self,align): self.setAttribute('ALIGN', align) def _get_bgColor(self): return self.getAttribute('BGCOLOR') def _set_bgColor(self, color): self.setAttribute('BGCOLOR', color) def _get_cells(self): cells = [] for child in self.childNodes: if child.tagName in ['TD','TH']: cells.append(child) return implementation._4dom_createHTMLCollection(cells) def _get_ch(self): return self.getAttribute('CHAR') def _set_ch(self, ch): self.setAttribute('CHAR', ch) def _get_chOff(self): return self.getAttribute('CHAROFF') def _set_chOff(self, offset): self.setAttribute('CHAROFF', offset) def _get_rowIndex(self): #Get our index in the table section = self.parentNode if section == None: return -1 table = section.parentNode if table == None: return -1 rows = table._get_rows() return rows.index(self) def _get_sectionRowIndex(self): section = self.parentNode if section == None: return -1 rows = section._get_rows() return rows.index(self) def _get_vAlign(self): return string.capitalize(self.getAttribute('VALIGN')) def _set_vAlign(self, valign): self.setAttribute('VALIGN', valign) ### Methods ### def insertCell(self, index): cells = self._get_cells() if index < 0 or index > len(cells): raise IndexSizeErr() cell = self.ownerDocument.createElement('TD') length = cells.length if index == len(cells): ref = None elif index < len(cells): ref = cells[index] return self.insertBefore(cell, ref) def deleteCell(self,index): cells = self._get_cells() if index < 0 or index >= len(cells): raise IndexSizeErr() self.removeChild(cells[index]) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'rowIndex' : _get_rowIndex, 'sectionRowIndex' : _get_sectionRowIndex, 'cells' : _get_cells, 'align' : _get_align, 'bgColor' : _get_bgColor, 'ch' : _get_ch, 'chOff' : _get_chOff, 'vAlign' : _get_vAlign, }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'align' : _set_align, 'bgColor' : _set_bgColor, 'ch' : _set_ch, 'chOff' : _set_chOff, 'vAlign' : _set_vAlign, }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTableSectionElement.py0100644000076400001440000000562107244340624021171 0ustar martinusers######################################################################## # # File Name: HTMLTableSectionElement.py # # Documentation: http://docs.4suite.com/4DOM/HTMLTableSectionElement.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import implementation from xml.dom.html.HTMLElement import HTMLElement from xml.dom import IndexSizeErr class HTMLTableSectionElement(HTMLElement): def __init__(self, ownerDocument, nodeName): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_align(self): return string.capitalize(self.getAttribute('ALIGN')) def _set_align(self,align): self.setAttribute('ALIGN',align) def _get_ch(self): return self.getAttribute('CHAR') def _set_ch(self,char): self.setAttribute('CHAR',char) def _get_chOff(self): return self.getAttribute('CHAROFF') def _set_chOff(self,offset): self.setAttribute('CHAROFF',offset) def _get_rows(self): rows = [] for child in self.childNodes: if child.tagName == 'TR': rows.append(child) return implementation._4dom_createHTMLCollection(rows) def _get_vAlign(self): return string.capitalize(self.getAttribute('VALIGN')) def _set_vAlign(self,valign): self.setAttribute('VALIGN',valign) ### Methods ### def deleteRow(self,index): rows = self._get_rows() if index < 0 or index > len(rows): raise IndexSizeErr() rows[index].parentNode.removeChild(rows[index]) def insertRow(self,index): rows = self._get_rows() if index < 0 or index > len(rows): raise IndexSizeErr() rows = self._get_rows() newRow = self.ownerDocument.createElement('TR') if index == len(rows): ref = None else: ref = rows[index] return self.insertBefore(newRow, ref) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update ({ 'rows' : _get_rows, 'align' : _get_align, 'ch' : _get_ch, 'chOff' : _get_chOff, 'vAlign' : _get_vAlign, }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update ({ 'align' : _set_align, 'ch' : _set_ch, 'chOff' : _set_chOff, 'vAlign' : _set_vAlign, }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTextAreaElement.py0100644000076400001440000001171207253474633020340 0ustar martinusers######################################################################## # # File Name: HTMLTextAreaElement # # Documentation: http://docs.4suite.com/4DOM/HTMLTextAreaElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLTextAreaElement(HTMLElement): def __init__(self, ownerDocument, nodeName="TEXTAREA"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_accessKey(self): return self.getAttribute("ACCESSKEY") def _set_accessKey(self, value): self.setAttribute("ACCESSKEY", value) def _get_cols(self): value = self.getAttribute("COLS") if value: return int(value) return 0 def _set_cols(self, value): self.setAttribute("COLS", str(value)) def _get_defaultValue(self): if not self.firstChild: return if self.firstChild == self.lastChild: return self.firstChild.data self.normalize() text = filter(lambda x: x.nodeType == Node.TEXT_NODE, self.childNodes) return text[0].data def _set_defaultValue(self, value): text = None for node in self.childNodes: if not text and node.nodeType == Node.TEXT_NODE: text = node else: self.removeChild(node) if text: text.data = value else: text = self.ownerDocument.createTextNode(value) self.appendChild(text) def _get_disabled(self): return self.hasAttribute("DISABLED") def _set_disabled(self, value): if value: self.setAttribute("DISABLED", "DISABLED") else: self.removeAttribute("DISABLED") def _get_form(self): parent = self.parentNode while parent: if parent.nodeName == "FORM": return parent parent = parent.parentNode return None def _get_name(self): return self.getAttribute("NAME") def _set_name(self, value): self.setAttribute("NAME", value) def _get_readonly(self): return self.hasAttribute("READONLY") def _set_readonly(self, value): if value: self.setAttribute("READONLY", "READONLY") else: self.removeAttribute("READONLY") def _get_rows(self): value = self.getAttribute("ROWS") if value: return int(value) return 0 def _set_rows(self, value): self.setAttribute("ROWS", str(value)) def _get_tabIndex(self): value = self.getAttribute("TABINDEX") if value: return int(value) return 0 def _set_tabIndex(self, value): self.setAttribute("TABINDEX", str(value)) def _get_type(self): return "textarea" def _get_value(self): if not self.firstChild: return if self.firstChild == self.lastChild: return self.firstChild.data self.normalize() text = filter(lambda x: x.nodeType == Node.TEXT_NODE, self.childNodes) return text[0].data def _set_value(self, value): text = None for node in self.childNodes: if not text and node.nodeType == Node.TEXT_NODE: text = node else: self.removeChild(node) if text: text.data = value else: text = self.ownerDocument.createTextNode(value) self.appendChild(text) ### Methods ### def blur(self): pass def focus(self): pass def select(self): pass ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "accessKey" : _get_accessKey, "cols" : _get_cols, "defaultValue" : _get_defaultValue, "disabled" : _get_disabled, "form" : _get_form, "name" : _get_name, "readonly" : _get_readonly, "rows" : _get_rows, "tabIndex" : _get_tabIndex, "type" : _get_type, "value" : _get_value }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "accessKey" : _set_accessKey, "cols" : _set_cols, "defaultValue" : _set_defaultValue, "disabled" : _set_disabled, "name" : _set_name, "readonly" : _set_readonly, "rows" : _set_rows, "tabIndex" : _set_tabIndex, "value" : _set_value }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLTitleElement.py0100644000076400001440000000356707253474633017715 0ustar martinusers######################################################################## # # File Name: HTMLTitleElement # # Documentation: http://docs.4suite.com/4DOM/HTMLTitleElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLTitleElement(HTMLElement): def __init__(self, ownerDocument, nodeName="TITLE"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_text(self): if not self.firstChild: return if self.firstChild == self.lastChild: return self.firstChild.data self.normalize() text = filter(lambda x: x.nodeType == Node.TEXT_NODE, self.childNodes) return text[0].data def _set_text(self, value): text = None for node in self.childNodes: if not text and node.nodeType == Node.TEXT_NODE: text = node else: self.removeChild(node) if text: text.data = value else: text = self.ownerDocument.createTextNode(value) self.appendChild(text) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "text" : _get_text }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "text" : _set_text }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/HTMLUListElement.py0100644000076400001440000000322607253474633017664 0ustar martinusers######################################################################## # # File Name: HTMLUListElement # # Documentation: http://docs.4suite.com/4DOM/HTMLUListElement.html # ### This file is automatically generated by GenerateHtml.py. ### DO NOT EDIT! """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import Node from xml.dom.html.HTMLElement import HTMLElement class HTMLUListElement(HTMLElement): def __init__(self, ownerDocument, nodeName="UL"): HTMLElement.__init__(self, ownerDocument, nodeName) ### Attribute Methods ### def _get_compact(self): return self.hasAttribute("COMPACT") def _set_compact(self, value): if value: self.setAttribute("COMPACT", "COMPACT") else: self.removeAttribute("COMPACT") def _get_type(self): return string.capitalize(self.getAttribute("TYPE")) def _set_type(self, value): self.setAttribute("TYPE", value) ### Attribute Access Mappings ### _readComputedAttrs = HTMLElement._readComputedAttrs.copy() _readComputedAttrs.update({ "compact" : _get_compact, "type" : _get_type }) _writeComputedAttrs = HTMLElement._writeComputedAttrs.copy() _writeComputedAttrs.update({ "compact" : _set_compact, "type" : _set_type }) _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), HTMLElement._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/html/__init__.py0100644000076400001440000010716607534565153016374 0ustar martinusersHTML_4_STRICT_INLINE = ['TT', 'I', 'B', 'BIG', 'SMALL', 'EM', 'STRONG', 'DFN', 'CODE', 'SAMP', 'KBD', 'VAR', 'CITE', 'ABBR', 'ACRONYM', 'A', 'IMG', 'OBJECT', 'SCRIPT', 'MAP', 'Q', 'SUB', 'SUP' 'SPAN', 'BDO', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL', 'BUTTON'] HTML_4_TRANSITIONAL_INLINE = ['TT', 'I', 'B', 'U', 'S', 'STRIKE', 'BIG', 'SMALL', 'EM', 'STRONG', 'DFN', 'CODE', 'SAMP', 'KBD', 'VAR', 'CITE', 'ABBR', 'ACRONYM', 'A', 'IMG', 'APPLET', 'OBJECT', 'FONT', 'BASEFONT', 'SCRIPT', 'MAP', 'Q', 'SUB', 'SUP', 'SPAN', 'BDO', 'IFRAME', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL', 'BUTTON'] HTML_FORBIDDEN_END = ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'FRAME', 'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM'] HTML_OPT_END = ['BODY', 'COLGROUP', 'DD', 'DT', 'HEAD', 'HTML', 'LI', 'OPTION', 'P', 'TBODY', 'TD', 'TFOOT', 'TH', 'THEAD', 'TR'] #FIXME: map attrs to the tags that use them HTML_BOOLEAN_ATTRS = ['CHECKED', 'COMPACT', 'DECLARE', 'DEFER', 'DISABLED', 'ISMAP', 'MULTIPLE', 'NOHREF', 'NORESIZE', 'NOSHADE', 'NOWRAP', 'READONLY', 'SELECTED'] HTML_CHARACTER_ENTITIES = { # Sect 24.2 -- ISO 8859-1 160: 'nbsp', 161: 'iexcl', 162: 'cent', 163: 'pound', 164: 'curren', 165: 'yen', 166: 'brvbar', 167: 'sect', 168: 'uml', 169: 'copy', 170: 'ordf', 171: 'laquo', 172: 'not', 173: 'shy', 174: 'reg', 175: 'macr', 176: 'deg', 177: 'plusmn', 178: 'sup2', 179: 'sup3', 180: 'acute', 181: 'micro', 182: 'para', 183: 'middot', 184: 'cedil', 185: 'sup1', 186: 'ordm', 187: 'raquo', 188: 'frac14', 189: 'frac12', 190: 'frac34', 191: 'iquest', 192: 'Agrave', 193: 'Aacute', 194: 'Acirc', 195: 'Atilde', 196: 'Auml', 197: 'Aring', 198: 'AElig', 199: 'Ccedil', 200: 'Egrave', 201: 'Eacute', 202: 'Ecirc', 203: 'Euml', 204: 'Igrave', 205: 'Iacute', 206: 'Icirc', 207: 'Iuml', 208: 'ETH', 209: 'Ntilde', 210: 'Ograve', 211: 'Oacute', 212: 'Ocirc', 213: 'Otilde', 214: 'Ouml', 215: 'times', 216: 'Oslash', 217: 'Ugrave', 218: 'Uacute', 219: 'Ucirc', 220: 'Uuml', 221: 'Yacute', 222: 'THORN', 223: 'szlig', 224: 'agrave', 225: 'aacute', 226: 'acirc', 227: 'atilde', 228: 'auml', 229: 'aring', 230: 'aelig', 231: 'ccedil', 232: 'egrave', 233: 'eacute', 234: 'ecirc', 235: 'euml', 236: 'igrave', 237: 'iacute', 238: 'icirc', 239: 'iuml', 240: 'eth', 241: 'ntilde', 242: 'ograve', 243: 'oacute', 244: 'ocirc', 245: 'otilde', 246: 'ouml', 247: 'divide', 248: 'oslash', 249: 'ugrave', 250: 'uacute', 251: 'ucirc', 252: 'uuml', 253: 'yacute', 254: 'thorn', 255: 'yuml', # Sect 24.3 -- Symbols, Mathematical Symbols, and Greek Letters # Latin Extended-B 402: 'fnof', # Greek 913: 'Alpha', 914: 'Beta', 915: 'Gamma', 916: 'Delta', 917: 'Epsilon', 918: 'Zeta', 919: 'Eta', 920: 'Theta', 921: 'Iota', 922: 'Kappa', 923: 'Lambda', 924: 'Mu', 925: 'Nu', 926: 'Xi', 927: 'Omicron', 928: 'Pi', 929: 'Rho', 931: 'Sigma', 932: 'Tau', 933: 'Upsilon', 934: 'Phi', 935: 'Chi', 936: 'Psi', 937: 'Omega', 945: 'alpha', 946: 'beta', 947: 'gamma', 948: 'delta', 949: 'epsilon', 950: 'zeta', 951: 'eta', 952: 'theta', 953: 'iota', 954: 'kappa', 955: 'lambda', 956: 'mu', 957: 'nu', 958: 'xi', 959: 'omicron', 960: 'pi', 961: 'rho', 962: 'sigmaf', 963: 'sigma', 964: 'tau', 965: 'upsilon', 966: 'phi', 967: 'chi', 968: 'psi', 969: 'omega', 977: 'thetasym', 978: 'upsih', 982: 'piv', # General Punctuation 8226: 'bull', # bullet 8230: 'hellip', # horizontal ellipsis 8242: 'prime', # prime (minutes/feet) 8243: 'Prime', # double prime (seconds/inches) 8254: 'oline', # overline (spacing overscore) 8250: 'frasl', # fractional slash # Letterlike Symbols 8472: 'weierp', # script capital P (power set/Weierstrass p) 8465: 'image', # blackletter capital I (imaginary part) 8476: 'real', # blackletter capital R (real part) 8482: 'trade', # trademark 8501: 'alefsym', # alef symbol (first transfinite cardinal) # Arrows 8592: 'larr', # leftwards arrow 8593: 'uarr', # upwards arrow 8594: 'rarr', # rightwards arrow 8595: 'darr', # downwards arrow 8596: 'harr', # left right arrow 8629: 'crarr', # downwards arrow with corner leftwards (carriage return) 8656: 'lArr', # leftwards double arrow 8657: 'uArr', # upwards double arrow 8658: 'rArr', # rightwards double arrow 8659: 'dArr', # downwards double arrow 8660: 'hArr', # left right double arrow # Mathematical Operators 8704: 'forall', # for all 8706: 'part', # partial differential 8707: 'exist', # there exists 8709: 'empty', # empty set, null set, diameter 8711: 'nabla', # nabla, backward difference 8712: 'isin', # element of 8713: 'notin', # not an element of 8715: 'ni', # contains as member 8719: 'prod', # n-ary product, product sign 8721: 'sum', # n-ary sumation 8722: 'minus', # minus sign 8727: 'lowast', # asterisk operator 8730: 'radic', # square root, radical sign 8733: 'prop', # proportional to 8734: 'infin', # infinity 8736: 'ang', # angle 8743: 'and', # logical and, wedge 8744: 'or', # logical or, vee 8745: 'cap', # intersection, cap 8746: 'cup', # union, cup 8747: 'int', # integral 8756: 'there4', # therefore 8764: 'sim', # tilde operator, varies with, similar to 8773: 'cong', # approximately equal to 8776: 'asymp', # almost equal to, asymptotic to 8800: 'ne', # not equal to 8801: 'equiv', # identical to 8804: 'le', # less-than or equal to 8805: 'ge', # greater-than or equal to 8834: 'sub', # subset of 8835: 'sup', # superset of 8836: 'nsub', # not subset of 8838: 'sube', # subset of or equal to 8839: 'supe', # superset of or equal to 8853: 'oplus', # circled plus, direct sum 8855: 'otimes', # circled times, vector product 8869: 'perp', # up tack, orthogonal to, perpendicular 8901: 'sdot', # dot operator 8968: 'lceil', # left ceiling, apl upstile 8969: 'rceil', # right ceiling 8970: 'lfloor', # left floor, apl downstile 8971: 'rfloor', # right floor 9001: 'lang', # left-pointing angle bracket, bra 9002: 'rang', # right-pointing angle bracket, ket 9674: 'loz', # lozenge # Miscellaneous Symbols 9824: 'spades', 9827: 'clubs', 9829: 'hearts', 9830: 'diams', # Sect 24.4 -- Markup Significant and Internationalization # Latin Extended-A 338: 'OElig', # capital ligature OE 339: 'oelig', # small ligature oe 352: 'Scaron', # capital S with caron 353: 'scaron', # small s with caron 376: 'Yuml', # capital Y with diaeresis # Spacing Modifier Letters 710: 'circ', # circumflexx accent 732: 'tidle', # small tilde # General Punctuation 8194: 'ensp', # en space 8195: 'emsp', # em space 8201: 'thinsp', # thin space 8204: 'zwnj', # zero-width non-joiner 8205: 'zwj', # zero-width joiner 8206: 'lrm', # left-to-right mark 8207: 'rlm', # right-to-left mark 8211: 'ndash', # en dash 8212: 'mdash', # em dash 8216: 'lsquo', # left single quotation mark 8217: 'rsquo', # right single quotation mark 8218: 'sbquo', # single low-9 quotation mark 8220: 'ldquo', # left double quotation mark 8221: 'rdquo', # right double quotation mark 8222: 'bdquo', # double low-9 quotation mark 8224: 'dagger', # dagger 8225: 'Dagger', # double dagger 8240: 'permil', # per mille sign 8249: 'lsaquo', # single left-pointing angle quotation mark 8250: 'rsaquo', # single right-pointing angle quotation mark 8364: 'euro', # euro sign } HTML_NAME_ALLOWED = ['A', 'APPLET', 'BUTTON', 'FORM', 'FRAME', 'IFRAME', 'IMG', 'INPUT', 'MAP', 'META', 'OBJECT', 'PARAM', 'SELECT', 'TEXTAREA'] # xhtml DTD HTML_DTD = { 'col': [], 'u': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'p': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'caption': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'q': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'i': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'textarea': ['#PCDATA'], 'center': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'script': [], 'ol': ['li'], 'a': ['#PCDATA', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'legend': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'strong': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'address': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'br': [], 'base': [], 'object': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'basefont': [], 'map': ['address', 'area', 'blockquote', 'center', 'del', 'dir', 'div', 'dl', 'fieldset', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'ins', 'isindex', 'menu', 'noframes', 'noscript', 'ol', 'p', 'pre', 'script', 'table', 'ul'], 'body': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'samp': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'dl': ['dd', 'dt'], 'acronym': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'html': ['body', 'frameset', 'head'], 'em': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'label': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'tbody': ['tr'], 'bdo': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'sub': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'meta': [], 'ins': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'frame': [], 's': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'title': ['#PCDATA'], 'frameset': ['frame', 'frameset', 'noframes'], 'pre': ['#PCDATA', 'a', 'abbr', 'acronym', 'b', 'bdo', 'br', 'button', 'cite', 'code', 'dfn', 'em', 'i', 'input', 'kbd', 'label', 'map', 'q', 's', 'samp', 'select', 'span', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'dir': ['li'], 'div': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'small': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'iframe': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'del': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'applet': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'ul': ['li'], 'isindex': [], 'button': ['#PCDATA', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'font', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'kbd', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'tt', 'u', 'ul', 'var'], 'colgroup': ['col'], 'b': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'table': ['caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr'], 'dt': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'optgroup': ['option'], 'abbr': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'link': [], 'h4': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'dd': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'big': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'hr': [], 'form': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'option': ['#PCDATA'], 'fieldset': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'legend', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'blockquote': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'head': ['base', 'isindex', 'link', 'meta', 'object', 'script', 'style', 'title'], 'thead': ['tr'], 'cite': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'td': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'input': [], 'var': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'th': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'tfoot': ['tr'], 'dfn': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'li': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'param': [], 'tr': ['td', 'th'], 'tt': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'menu': ['li'], 'area': [], 'img': [], 'span': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'style': [], 'noscript': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'noframes': ['#PCDATA', 'a', 'abbr', 'acronym', 'address', 'applet', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'button', 'center', 'cite', 'code', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label', 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', 'p', 'pre', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'textarea', 'tt', 'u', 'ul', 'var'], 'select': ['optgroup', 'option'], 'font': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'strike': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'sup': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'h5': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'kbd': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'h6': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'h1': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'h3': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'h2': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'], 'code': ['#PCDATA', 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'noscript', 'object', 'q', 's', 'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textarea', 'tt', 'u', 'var'] } from xml.dom.html import HTMLDOMImplementation htmlImplementation = HTMLDOMImplementation.HTMLDOMImplementation() #FIXME: all of this can be made much more efficient. Maybe when we leave Python 1.x behind try: #The following stanza courtesy Martin von Loewis import codecs # Python 1.6+ only from types import UnicodeType def utf8_to_code(text, encoding): encoder = codecs.lookup(encoding)[0] # encode,decode,reader,writer if type(text) is not UnicodeType: text = unicode(text, "utf-8") return encoder(text)[0] # result,size def ConvertChar(m): return '&'+HTML_CHARACTER_ENTITIES[ord(m.group())]+';' def UseHtmlCharEntities(text): if type(text) is not UnicodeType: text = unicode(text, "utf-8") new_text, num_subst = re.subn(g_htmlUniCharEntityPattern, ConvertChar, text) return new_text except ImportError: from xml.unicode.iso8859 import wstring wstring.install_alias('ISO-8859-1', 'ISO_8859-1:1987') def utf8_to_code(text, encoding): encoding = string.upper(encoding) if encoding == 'UTF-8': return text #Note: Pass through to wstrop. This means we don't play nice and #Escape characters that are not in the target encoding. ws = wstring.from_utf8(text) text = ws.encode(encoding) #This version would skip all untranslatable chars: see wstrop.c #text = ws.encode(encoding, 1) return text def ConvertChar(m): char = ((int(ord(m.group(1))) & 0x03) << 6) | (int(ord(m.group(2))) & 0x3F) if HTML_CHARACTER_ENTITIES.has_key(char): return '&'+HTML_CHARACTER_ENTITIES[char]+';' else: return m.group() def UseHtmlCharEntities(text): new_text, num_subst = re.subn(g_utf8TwoBytePattern, ConvertChar, text) return new_text import re, string g_xmlIllegalCharPattern = re.compile('[\x01-\x08\x0B-\x0D\x0E-\x1F\x80-\xFF]') g_numCharEntityPattern = re.compile('&#(\d+);') g_utf8TwoBytePattern = re.compile('([\xC0-\xC3])([\x80-\xBF])') g_htmlUniCharEntityPattern = re.compile('[\xa0-\xff]') g_cdataCharPattern = re.compile('[&<]|]]>') g_charToEntity = { '&': '&', '<': '<', ']]>': ']]>', } def TranslateHtmlCdata(characters, encoding='UTF-8', prev_chars=''): #Translate numerical char entity references with HTML entity equivalents new_string, num_subst = re.subn( g_cdataCharPattern, lambda m, d=g_charToEntity: d[m.group()], characters ) if prev_chars[-2:] == ']]' and new_string[0] == '>': new_string = '>' + new_string[1:] new_string = UseHtmlCharEntities(new_string) try: new_string = utf8_to_code(new_string, encoding) except: #FIXME: This is a work-around, contributed by Mike Brown, that #Deals with escaping output, until we have XML/HTML aware codecs tmp_new_string = "" for c in new_string: try: new_c = utf8_to_code(c, encoding) except: new_c = '&#%i;'%ord(c) tmp_new_string = tmp_new_string + new_c new_string = tmp_new_string #new_string, num_subst = re.subn(g_xmlIllegalCharPattern, lambda m: '&#%i;'%ord(m.group()), new_string) #Note: use decimal char entity rep because some browsers are broken return new_string SECURE_HTML_ELEMS = ["A", "P", "BR", "B", "I", "DIV", "STRONG", "EM", "BLOCKQUOTE", "UL", "OL", "LI", "DL", "DD", "DT", "TT"] PyXML-0.8.2/xml/dom/html/html_classes.xml0100644000076400001440000005703407123712560017452 0ustar martinusers

    ######################################################################## # # File Name: $FILE$ # # Documentation: http://docs.4suite.com/4DOM/$FILE$.html #
    WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information PyXML-0.8.2/xml/dom/Attr.py0100644000076400001440000001031407244340623014556 0ustar martinusers######################################################################## # # File Name: Attr.py # # Documentation: http://docs.4suite.com/4DOM/Attr.py.html # """ DOM Level 2 Attribute Node WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from DOMImplementation import implementation from FtNode import FtNode from Event import MutationEvent class Attr(FtNode): nodeType = Node.ATTRIBUTE_NODE _allowedChildren = [Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE ] def __init__(self, ownerDocument, name, namespaceURI, prefix, localName): FtNode.__init__(self, ownerDocument, namespaceURI, prefix, localName) self.__dict__['__nodeName'] = name self._ownerElement = None ### Attribute Methods ### def _get_name(self): return self.__dict__['__nodeName'] def _get_specified(self): #True if this attribute was explicitly given a value in the document return self._get_value() != '' def _get_value(self): return reduce(lambda value, child: value + child.nodeValue, self.childNodes, '') def _set_value(self, value): old_value = self.value if value != old_value or len(self.childNodes) > 1: # Remove previous childNodes while self.firstChild: self.removeChild(self.firstChild) if value: self.appendChild(self.ownerDocument.createTextNode(value)) owner = self._ownerElement if owner: owner._4dom_fireMutationEvent('DOMAttrModified', relatedNode=self, prevValue=old_value, newValue=value, attrName=self.name, attrChange=MutationEvent.MODIFICATION) owner._4dom_fireMutationEvent('DOMSubtreeModified') def _get_ownerElement(self): return self._ownerElement ### Overridden Methods ### def _get_nodeValue(self): return self._get_value() def _set_nodeValue(self, value): self._set_value(value) def __repr__(self): return '' % ( id(self), self.name, self.value ) ### Helper Functions For Cloning ### def _4dom_clone(self, owner): a = self.__class__(owner, self.nodeName, self.namespaceURI, self.prefix, self.localName) for child in self.childNodes: a.appendChild(child._4dom_clone(owner)) return a def __getinitargs__(self): return (self.ownerDocument, self.nodeName, self.namespaceURI, self.prefix, self.localName ) def __getstate__(self): return self.childNodes def __setstate__(self, children): self.childNodes.extend(list(children)) for i in range(1, len(children)): children[i]._4dom_setHierarchy(self, children[i-1], None) ### Internal Methods ### def _4dom_setOwnerElement(self, owner): self.__dict__['_ownerElement'] = owner ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({ 'name':_get_name, 'specified':_get_specified, 'ownerElement':_get_ownerElement, 'value':_get_value, 'nodeValue':_get_value }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() _writeComputedAttrs.update({ 'value':_set_value, 'nodeValue':_set_value }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/CDATASection.py0100644000076400001440000000131507244340623016006 0ustar martinusers######################################################################## # # File Name: CDATASection.py # # Documentation: http://docs.4suite.com/4DOM/CDATASection.py.html # """ Implementation of DOM Level 2 CDATASection interface WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from Text import Text class CDATASection(Text): nodeType = Node.CDATA_SECTION_NODE def __init__(self, ownerDocument, data): Text.__init__(self, ownerDocument, data) self.__dict__['__nodeName'] = "#cdata-section" PyXML-0.8.2/xml/dom/COPYRIGHT0100644000076400001440000000451007244607163014573 0ustar martinusers The 4Suite License, Version 1.1 Copyright (c) 2000 Fourthought, Inc.. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Fourthought, Inc. (http://www.fourthought.com)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. * The names "4Suite", "4Suite Server" and "Fourthought" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact info@fourthought.com. * Products derived from this software may not be called "4Suite", nor may "4Suite" appear in their name, without prior written permission of Fourthought, Inc. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FOURTHOGHT, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================== This license is based on the Apache Software License, Version 1.1, Copyright (c) 2000 The Apache Software Foundation. All rights reserved. PyXML-0.8.2/xml/dom/ChangeLog0100644000076400001440000002044507164503224015051 0ustar martinusersChanges in 0.10.2 (R20000724) ----------------------------- - Support wide range of output encodings via wstring - Updated conformance to 20000510 DOM CR - Changed internals to use Node as the clone manager, using a pickle- style interface. - Changed many classes to be generated in the HTML Extension - Other bug-fixes Changes in 0.10.1 (R20000606) ----------------------------- - Fix nasty character-encoding bugs in Printer - Fixed many bugs in demos - Fix Sax2 support for passed-in documents - Other bug-fixes Changes in 0.10.0 (R20000524) ----------------------------- - Moved all static variables to class variables - Fixed printing to work with empty elements - Removed all tabs from files - Change package to xml.dom - major change to the internals to use Node as a Python attribute manager this improves efficiency: cutting down on __g/setattrs__ and simplifies some things - Updated conformance to 19991210 DOM CR (yes, already out of date. Zut!) - Many fixes to HTML output - Support custom Documents in Sax2 reader - Many other fixes to printing and reading Changes in 0.9.3 (R20000216) ---------------------------- - Better UTF-8 handling in printing - Clean up printer whitespace - Fix nasty bug in Sax2 attribute namespace defaulting - Other bug-fixes Changes in 0.9.2 (R20000125) ---------------------------- - Major fixes to namespace code - Other bug-fixes Changes in 0.9.1 (R20000103) ---------------------------- - Fixed HTML reader - Misc. Bug-Fixes Note: There were numerous changes in untagged release 0.9.0, including - Major re-write to match the general consensus DOm binding for Python. Code formerly in the form "node.getChildNodes()" is now to be used in the form "node._get_childNodes()" or simply "node.childNodes". Similarly "text.setData("spam")" becomes "text._set_data("spam")" or text.data = "spam" - Update to full Level 2 support in core and HTML, including namespace-support. - Many bug-fixes Changes in 0.8.2 (R19991019) ---------------------------- - Create a Reader module under Ext for importing strings into 4DOM. Builder is now deprecated and will disappear before version 1.0 o Reader has three drivers currently: Sax and HtmlLib are just modularized versions of the functionality that was formerly in Builder, and Sax2 is a driver for the as-yet experimental SAX 2 specification. - Fixed a Builder/Reader bug for HTML input and empty, unclosed tags such as
    - Fixed a bug in text normalization - Miscellaneous bug-fixes Changes in 0.8.1 (R19990914) ---------------------------- - Added support for Dom Level 2 Core interfaces - Added __repr__ to all Core interfaces - Output character entities where appropriate in Printer.py - Many bug-fixes to Printer.py - Bug-fixes to attribute - Modified Remote factory startup to use environment variables Changes in 0.8.0 (R19990831) ---------------------------- - Major Changes to the organization and Module Namespace o Top-level namespace is Ft.Dom to integrate with other FourThought Packages o Naming of Packages, Classes, Modules etc. has been normalized to "camel-case" with abbreviations counted as word units, e.g. XMLFooBarHTML -> XmlFooBarHtml This normalization is not possible where W3C clashes, e.g. HTMLElement remains as is. o Simplified the access of Node constants, e.g. you can use Ft.Dom.Node.ELEMENT_NODE rather than Ft.Dom.Dom.Node.ELEMENT_NODE - Added extensions to support XML Namespaces (Ext.Namespace) - Added UserList and UserDict interface to NodeList and NamedNodeMap, allowing orbless or local code to use pythonic features such as [], append(), len(), keys(), etc. - Added better ILU Support - Added support for xml:space and turned Ext.Strip into separate functions for stripping HTML and XML. - Fixed a problem with importing mis-matched HTML tags. - Numerous minor bug fixes Changes in 0.7.2 (R19990422) ---------------------------- - "orbless" is now the default target of the Makefile, so most users can just type "make" once installed - DListElement had been left out of the orbless configuration: fixed - Removed the kludge for dynamic addition of tedious HTML Eement attributes Changes in 0.7.1 ------------------------------- - Fixed "make orbless" to instruct the user what to add to PythonPath. - Fixed bug in HTMLTable.getRows, and HTMLTableSection.getRows. Before a call to these functions was using getElementsByTagName to return a list of TR elements. This breaks when a table has a table in one of it cells. - Fixed index error in HTMLTable.insertRow - Removed evals from PrettyPrinter - Fixed index error in HTMLTableRow.insertCell - Removed call to extension functions in PrettyPrinter - Added XCatalog support, if available, to Builder.FromXML - Changed SAX Handler class for Builder.FromXML to a parameter, to allow input filters, etc. - Changed Builder.FromXML to add the read-in tree to the created document, if one is not given. If one is given, just return a fragment, as in version 0.7.0. - Added utility APIs to DOM.Ext.Builder: o FromXMLStream o FromXMLFile o FromXMLURL o FromHTMLFile o FromHTMLStream o FromHTMLURL - Reduced the PrettyPrint indentation from a tab to two spaces. Changes in 0.7.0 (R19990207) ---------------------------- - Added support for "orbless" configuration. Now neither ILU nor Fnorb are requred and 4DOM can be run purely locally, but still with a consistent interface. Naturally, the orbless config is much faster than the ilu or fnorb configs. - Many fixes to improve consistency over an ORB interface (an example using an ORB has been added to demos). - Fixes to NodeList and NamedNodeMap - Added an Ext package for DOM extensions, and moved many of the existing extensions there. See docs/Extensions.html. - Added to Ext an extensive factory interface for creation of nodes, consistent for local and ORB use. - Added to Ext a ReleaseNode helper function to reclaim unused nodes, necessary for ORB usage, and also for local usage because of circular references. - Added NodeIterators and Node Filters from DOM Level 2 - Added a visitor and walker system (to Ext). These generalize the NodeIterator concept for cases where pre-order traversal is not suitable: for instance printing. - Removed the repr functions from Node interfaces in favor of print walker/visitors. - Added Print and PrettyPrint helper functions to Ext for printing and pretty-printing node trees. - Added Strip helper function to Ext to strip all ignorable white-space text nodes from a node tree. - Moved all tools to construct a DOM tree from XML and HTML text to a Builder module in Ext, with two functions: FromXML and FromHTML. - Added options to FromXML that allow specification of whether to keep ignorable whitespce int he resultant node tree, and options on whether to validate. - Innumerable minor and miscellaneous fixes Changes in 0.6.1 (R19981120) ---------------------------- - added ILU support with a series of kludges (all designed to minimize effect on existing DOM code): o Use ILU's python-stubber in makefile rather than fnidl o python-stubber generates *IF__skel rather than fnidl's *IF_skel, so copy the files so bother names are available. o add config modules for DOM core and HTML, globally imported, which creates dummy INTERFACENAME_skel classes because ILU does not append "_skel" to skeleton class names as Fnorb does: it uses module-scoping for the distinction. o Add variables using Fnorb-style constant naming (INTERFACENAME.CONSTANTNAME) to refer to the ILU-style constants (INTERFACENAME_CONSTANTNAME) o Brutally hack all 4DOM source files during make to change Fnorb-style invocations for DOMException (raise DOMException(EXCEPTNAME)) into ILU-style (raise DOMException, DOMException__omgidl_exctype(EXCEPTNAME)) note that this series of kludges slows things down and adds some bloat, but we plan to intelligently convert to better-considered fixes in time. Also, there will be some degree of resolution between Fnorb and ILU as the Python-CORBA mapping gets adopted, so let's avoid baking any fixes prematurely into the code. - added the #pragma prefix "fourthought.com" to all IDL files - Document.repr() now includes the DOCTYPE Version: 0.6.0 (R19981104) -------------------------- - initial public release PyXML-0.8.2/xml/dom/CharacterData.py0100644000076400001440000001011007253474633016335 0ustar martinusers######################################################################## # # File Name: CharacterData.py # # Documentation: http://docs.4suite.com/4DOM/CharacterData.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from DOMImplementation import implementation from FtNode import FtNode from ext import IsDOMString from xml.dom import IndexSizeErr from xml.dom import SyntaxErr class CharacterData(FtNode): def __init__(self, ownerDocument, data): FtNode.__init__(self, ownerDocument) self.__dict__['__nodeValue'] = data self._length = len(data) ### Attribute Methods ### def _get_data(self): return self.__dict__['__nodeValue'] def _set_data(self, data): if not IsDOMString(data): raise SyntaxErr() old_value = self.__dict__['__nodeValue'] self.__dict__['__nodeValue'] = data self._length = len(data) self._4dom_fireMutationEvent('DOMCharacterDataModified', prevValue=old_value, newValue=data) def _get_length(self): return self._length ### Methods ### def appendData(self, arg): if len(arg): self._set_data(self.__dict__['__nodeValue'] + arg) self._4dom_fireMutationEvent('DOMSubtreeModified') return def deleteData(self, offset, count): if count < 0 or offset < 0 or offset > self._length: raise IndexSizeErr() data = self.__dict__['__nodeValue'] data = data[:int(offset)] + data[int(offset+count):] self._set_data(data) self._4dom_fireMutationEvent('DOMSubtreeModified') return def insertData(self, offset, arg): if offset < 0 or offset > self._length: raise IndexSizeErr() if not IsDOMString(arg): raise SyntaxErr() data = self.__dict__['__nodeValue'] data = data[:int(offset)] + arg + data[int(offset):] self._set_data(data) self._4dom_fireMutationEvent('DOMSubtreeModified') return def replaceData(self, offset, count, arg): if not IsDOMString(arg): raise SyntaxErr() if count < 0 or offset < 0 or offset > self._length: raise IndexSizeErr() data = self.__dict__['__nodeValue'] data = data[:int(offset)] + arg + data[int(offset+count):] self._set_data(data) self._4dom_fireMutationEvent('DOMSubtreeModified') return def substringData(self, offset, count): if count < 0 or offset < 0 or offset > self._length: raise IndexSizeErr() return self.data[int(offset):int(offset+count)] ### Helper Functions For Cloning ### def _4dom_clone(self, owner): return self.__class__(owner, self.data) def __getinitargs__(self): return (self.ownerDocument, self.data ) ### Overridden Methods ### def __repr__(self): # Trim to a managable size if len(self.data) > 20: data = self.data[:20] + '...' else: data = self.data # Escape unprintable chars import string for ws in ['\t','\n','\r']: data = string.replace(data, ws, '\\0x%x' % ord(ws)) return "<%s Node at %x: %s>" % ( self.__class__.__name__, id(self), repr(data)) ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({ 'length':_get_length, 'data':_get_data }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() _writeComputedAttrs.update({ 'data':_set_data }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/Comment.py0100644000076400001440000000123707345461577015270 0ustar martinusers######################################################################## # # File Name: Comment.py # # Documentation: http://docs.4suite.org/4DOM/Comment.py.html # """ WWW: http://4suite.org/4DOM e-mail: support@4suite.org Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.dom import Node from CharacterData import CharacterData class Comment(CharacterData): nodeType = Node.COMMENT_NODE def __init__(self,ownerDocument,data): CharacterData.__init__(self, ownerDocument, data) self.__dict__['__nodeName'] = '#comment' PyXML-0.8.2/xml/dom/DOMImplementation.py0100644000076400001440000000373607246244664017215 0ustar martinusers######################################################################## # # File Name: DOMImplementation.py # # Documentation: http://docs.4suite.com/4DOM/DOMImplementation.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string FEATURES_MAP = {'CORE':2.0, 'XML':2.0, 'TRAVERSAL':2.0, 'EVENTS':2.0, 'MUTATIONEVENTS':2.0, } try: import Range except: pass else: FEATURES_MAP['RANGE'] = 2.0 class DOMImplementation: def __init__(self): pass def hasFeature(self, feature, version=''): featureVersion = FEATURES_MAP.get(string.upper(feature)) if featureVersion: if version and float(version) != featureVersion: return 0 return 1 return 0 def createDocumentType(self, qualifiedName, publicId, systemId): import DocumentType dt = DocumentType.DocumentType(qualifiedName, self._4dom_createNamedNodeMap(), self._4dom_createNamedNodeMap(), publicId, systemId) return dt def createDocument(self, namespaceURI, qualifiedName, doctype): import Document doc = Document.Document(doctype) if qualifiedName: el = doc.createElementNS(namespaceURI, qualifiedName) doc.appendChild(el) return doc def _4dom_createNodeList(self, list=None): import NodeList return NodeList.NodeList(list) def _4dom_createNamedNodeMap(self, owner=None): import NamedNodeMap return NamedNodeMap.NamedNodeMap(owner) implementation = DOMImplementation() getDOMImplementation = DOMImplementation PyXML-0.8.2/xml/dom/Document.py0100644000076400001440000002736107420133741015431 0ustar martinusers######################################################################## # # File Name: Document.py # # Documentation: http://docs.4suite.com/4DOM/Document.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import re, string from DOMImplementation import implementation from FtNode import FtNode, get_name_pattern from ext import SplitQName from xml.dom import Node from xml.dom import XML_NAMESPACE from xml.dom import XMLNS_NAMESPACE from xml.dom import EMPTY_NAMESPACE from xml.dom import HierarchyRequestErr from xml.dom import InvalidCharacterErr from xml.dom import NotSupportedErr from xml.dom import NamespaceErr class Document(FtNode): #Base node type for this class nodeType = Node.DOCUMENT_NODE nodeName = "#document" #This is for validation that the proper nodes are added _allowedChildren = [Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.ELEMENT_NODE, Node.DOCUMENT_TYPE_NODE ] def __init__(self, doctype): FtNode.__init__(self, None) self.__dict__['__doctype'] = None self.__dict__['__implementation'] = implementation self.__dict__['__documentElement'] = None self.__dict__['_singleChildren'] = {Node.ELEMENT_NODE:'__documentElement', Node.DOCUMENT_TYPE_NODE:'__doctype' } self._4dom_setDocumentType(doctype) ### Attribute Methods ### def _get_doctype(self): return self.__dict__['__doctype'] def _get_implementation(self): return self.__dict__['__implementation'] def _get_documentElement(self): return self.__dict__['__documentElement'] def _get_ownerDocument(self): return self ### Methods ### def createAttribute(self, name): if not get_name_pattern().match(name): raise InvalidCharacterErr() import Attr return Attr.Attr(self, name, EMPTY_NAMESPACE, None, None) def createCDATASection(self, data): from CDATASection import CDATASection return CDATASection(self, data) def createComment(self, data): from Comment import Comment return Comment(self, data) def createDocumentFragment(self): from DocumentFragment import DocumentFragment return DocumentFragment(self) def createElement(self, tagname): if not get_name_pattern().match(tagname): raise InvalidCharacterErr() from Element import Element return Element(self, tagname, EMPTY_NAMESPACE, None, None) def createEntityReference(self, name): if not get_name_pattern().match(name): raise InvalidCharacterErr() from EntityReference import EntityReference return EntityReference(self, name) def createProcessingInstruction(self, target, data): if not get_name_pattern().match(target): raise InvalidCharacterErr() #FIXME: Unicode support # Technically, chacters from the unicode surrogate blocks are illegal. #for c in target: # if c in unicode_surrogate_blocks: # raise InvalidCharacterErr() from ProcessingInstruction import ProcessingInstruction return ProcessingInstruction(self, target, data); def createTextNode(self, data): from Text import Text return Text(self, data) def getElementById(self, elementId): #FIXME: Must be implemented in the parser first return None def getElementsByTagName(self, tagName): nodeList = implementation._4dom_createNodeList([]) root = self.documentElement if root: if tagName == '*' or root.tagName == tagName: nodeList.append(root) nodeList.extend(list(root.getElementsByTagName(tagName))) return nodeList ### DOM Level 2 Methods ### def createAttributeNS(self, namespaceURI, qualifiedName): if not get_name_pattern().match(qualifiedName): raise InvalidCharacterErr() from Attr import Attr (prefix, localName) = SplitQName(qualifiedName) if prefix == 'xml' and namespaceURI != XML_NAMESPACE: raise NamespaceErr() if localName == 'xmlns': if namespaceURI != XMLNS_NAMESPACE: raise NamespaceErr() return Attr(self, qualifiedName, XMLNS_NAMESPACE, 'xmlns', prefix) elif namespaceURI == '': raise NamespaceErr("Use None instead of '' for empty namespace") else: if (not namespaceURI and prefix) or (not prefix and namespaceURI): raise NamespaceErr() return Attr(self, qualifiedName, namespaceURI, prefix, localName) def importNode(self, importedNode, deep): importType = importedNode.nodeType # No import allow per spec if importType in [Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE]: raise NotSupportedErr() # Only the EntRef itself is copied since the source and destination # documents might have defined the entity differently #FIXME: If the document being imported into provides a definition for # this entity name, its value is assigned. # Need entity support for this!! elif importType == Node.ENTITY_REFERENCE_NODE: deep = 0 return importedNode.cloneNode(deep, newOwner=self) def createElementNS(self, namespaceURI, qualifiedName): from Element import Element if not get_name_pattern().match(qualifiedName): raise InvalidCharacterErr() (prefix, localName) = SplitQName(qualifiedName) if prefix == 'xml' and namespaceURI != XML_NAMESPACE: raise NamespaceErr() if prefix and not namespaceURI: raise NamespaceErr() elif namespaceURI == '': raise NamespaceErr("Use None instead of '' for empty namespace") return Element(self, qualifiedName, namespaceURI, prefix, localName) def getElementsByTagNameNS(self,namespaceURI,localName): if namespaceURI == '': raise NamespaceErr("Use None instead of '' for empty namespace") nodeList = implementation._4dom_createNodeList([]) root = self.documentElement if root: if ((namespaceURI == '*' or namespaceURI == root.namespaceURI) and (localName == '*' or localName == root.localName)): nodeList.append(root) nodeList.extend(list(root.getElementsByTagNameNS(namespaceURI, localName))) return nodeList ### Document Traversal Factory Functions ### def createNodeIterator(self, root, whatToShow, filter, entityReferenceExpansion): from NodeIterator import NodeIterator return NodeIterator(root, whatToShow, filter, entityReferenceExpansion) def createTreeWalker(self, root, whatToShow, filter, entityReferenceExpansion): from TreeWalker import TreeWalker return TreeWalker(root, whatToShow, filter, entityReferenceExpansion) ### Document Event Factory Functions ### def createEvent(self,eventType): import Event if eventType in Event.supportedEvents: #Only mutation events are supported return Event.MutationEvent(eventType) else: raise NotSupportedErr() ### Document Range Factory Functions ### def createRange(self): if not self.implementation.hasFeature('RANGE','2.0'): raise NotSupportedErr() import Range return Range.Range(self) ### Overridden Methods ### def appendChild(self, newChild): self._4dom_addSingle(newChild) return FtNode.appendChild(self, newChild) def insertBefore(self, newChild, oldChild): self._4dom_addSingle(newChild) return FtNode.insertBefore(self, newChild, oldChild) def replaceChild(self, newChild, oldChild): if newChild.nodeType != Node.DOCUMENT_FRAGMENT_NODE: root = self.__dict__['__documentElement'] if root in [oldChild, newChild]: self.__dict__['__documentElement'] = None else: raise HierarchyRequestErr() replaced = FtNode.replaceChild(self, newChild, oldChild) if newChild.nodeType == Node.ELEMENT_NODE: self.__dict__['__documentElement'] = newChild if self.__dict__['__doctype']: self.__dict__['__doctype']._4dom_setName(newChild.nodeName) return replaced def removeChild(self,oldChild): node = FtNode.removeChild(self, oldChild) if self.documentElement == node: self.__dict__['__documentElement'] = None if self.__dict__['__doctype'] == node: self.__dict__['__doctype'] = None return node def cloneNode(self, deep): doc = self.__class__(None) if deep: for child in self.childNodes: clone = child.cloneNode(deep, newOwner=doc) if child.nodeType == Node.DOCUMENT_TYPE_NODE: doc._4dom_setDocumentType(clone) else: doc.appendChild(clone) return doc def __repr__(self): return "<%s Document at %x>" % ( (self.isXml() and 'XML' or 'HTML'), id(self) ) ### Internal Methods ### def _4dom_createEntity(self, publicId, systemId, notationName): from Entity import Entity return Entity(self, publicId, systemId, notationName) def _4dom_createNotation(self, publicId, systemId, name): from Notation import Notation return Notation(self, publicId, systemId, name) def _4dom_setDocumentType(self, doctype): if not self.__dict__['__doctype'] and doctype is not None: self.__dict__['__doctype'] = doctype doctype._4dom_setOwnerDocument(self) return FtNode.appendChild(self, doctype) def _4dom_addSingle(self, node): '''Make sure only one Element node is added to a Document''' if node.nodeType == Node.ELEMENT_NODE: self._4dom_validateNode(node) if node.parentNode != None: node.parentNode.removeChild(node) if self.__dict__['__documentElement']: raise HierarchyRequestErr() self.__dict__['__documentElement'] = node if self.__dict__['__doctype']: self.__dict__['__doctype']._4dom_setName(node.nodeName) ### Helper Functions for Pickling ### def __getinitargs__(self): return (None,) def __getstate__(self): return (self.childNodes, self.doctype, self.documentElement) def __setstate__(self, (children, doctype, root)): FtNode.__setstate__(self, children) self.__dict__['__doctype'] = doctype self.__dict__['__documentElement'] = root return ### Convenience Functions ### def isXml(self): return 1 def isHtml(self): return 0 ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({'doctype':_get_doctype, 'implementation':_get_implementation, 'documentElement':_get_documentElement, 'ownerDocument':_get_ownerDocument, }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/DocumentFragment.py0100644000076400001440000000253507253474633017125 0ustar martinusers######################################################################## # # File Name: DocumentFragment.py # # Documentation: http://docs.4suite.com/4DOM/DocumentFragment.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from FtNode import FtNode class DocumentFragment(FtNode): nodeType = Node.DOCUMENT_FRAGMENT_NODE _allowedChildren = [Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE] def __init__(self, ownerDocument): FtNode.__init__(self, ownerDocument) self.__dict__['__nodeName'] = '#document-fragment' ### Overridden Methods ### def __repr__(self): return '' % ( id(self), len(self.childNodes), ) ### Helper Functions For Cloning ### def _4dom_clone(self, owner): return self.__class__(owner) def __getinitargs__(self): return (self.ownerDocument, ) PyXML-0.8.2/xml/dom/DocumentType.py0100644000076400001440000000662007244340623016271 0ustar martinusers######################################################################## # # File Name: DocumentType.py # # Documentation: http://docs.4suite.org/4DOM/DocumentType.py.html # """ WWW: http://4suite.org/4DOM e-mail: support@4suite.org Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.dom import Node from DOMImplementation import implementation from FtNode import FtNode class DocumentType(FtNode): nodeType = Node.DOCUMENT_TYPE_NODE def __init__(self, name, entities, notations, publicId, systemId): FtNode.__init__(self, None) self.__dict__['__nodeName'] = name self._entities = entities self._notations = notations self._publicId = publicId self._systemId = systemId #FIXME: Text repr of the entities self._internalSubset = '' ### Attribute Methods ### def _get_name(self): return self.__dict__['__nodeName'] def _get_entities(self): return self._entities def _get_notations(self): return self._notations def _get_publicId(self): return self._publicId def _get_systemId(self): return self._systemId def _get_internalSubset(self): return self._internalSubset ### Overridden Methods ### def __repr__(self): return "" % ( id(self), self.nodeName, len(self._entities), len(self._notations) ) ### Internal Methods ### # Behind the back setting of doctype's ownerDocument # Also sets the owner of the NamedNodeMaps def _4dom_setOwnerDocument(self, newOwner): self.__dict__['__ownerDocument'] = newOwner #self._entities._4dom_setOwnerDocument(newOwner) #self._notations._4dom_setOwnerDocument(newOwner) def _4dom_setName(self, name): # Used to keep the root element and doctype in sync self.__dict__['__nodeName'] = name ### Helper Functions For Cloning ### def _4dom_clone(self, owner): return self.__class__(self.name, self.entities._4dom_clone(owner), self.notations._4dom_clone(owner), self._publicId, self._systemId) def __getinitargs__(self): return (self.nodeName, self._entities, self._notations, self._publicId, self._systemId ) ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({'name':_get_name, 'entities':_get_entities, 'notations':_get_notations, 'publicId':_get_publicId, 'systemId':_get_systemId, 'internalSubset':_get_internalSubset }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() _writeComputedAttrs.update({ }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/Element.py0100644000076400001440000002371007420133741015236 0ustar martinusers######################################################################## # # File Name: Element.py # # Documentation: http://docs.4suite.com/4DOM/Element.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from DOMImplementation import implementation from FtNode import FtNode, get_name_pattern import Event from xml.dom import Node from xml.dom import XML_NAMESPACE from xml.dom import EMPTY_NAMESPACE from xml.dom import InvalidCharacterErr from xml.dom import WrongDocumentErr from xml.dom import InuseAttributeErr from xml.dom import NotFoundErr from xml.dom import SyntaxErr from xml.dom import NamespaceErr from ext import SplitQName, IsDOMString class Element(FtNode): nodeType = Node.ELEMENT_NODE _allowedChildren = [Node.ELEMENT_NODE, Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE ] def __init__(self, ownerDocument, nodeName, namespaceURI, prefix, localName): FtNode.__init__(self, ownerDocument, namespaceURI, prefix, localName); #Set our attributes self.__dict__['__attributes'] = implementation._4dom_createNamedNodeMap(ownerDocument) self.__dict__['__nodeName'] = nodeName ### Attribute Methods ### def _get_tagName(self): return self.__dict__['__nodeName'] ### Methods ### def getAttribute(self, name): att = self.attributes.getNamedItem(name) return att and att.value or '' def getAttributeNode(self, name): return self.attributes.getNamedItem(name) def getElementsByTagName(self, tagName): nodeList = implementation._4dom_createNodeList() elements = filter(lambda node, type=Node.ELEMENT_NODE: node.nodeType == type, self.childNodes) for element in elements: if tagName == '*' or element.tagName == tagName: nodeList.append(element) nodeList.extend(list(element.getElementsByTagName(tagName))) return nodeList def hasAttribute(self, name): return self.attributes.getNamedItem(name) is not None def removeAttribute(self, name): # Return silently if no node node = self.attributes.getNamedItem(name) if node: self.removeAttributeNode(node) def removeAttributeNode(self, node): # NamedNodeMap will raise exception if needed try: self.attributes.removeNamedItemNS(node.namespaceURI, node.localName) except NotFoundErr: self.attributes.removeNamedItem(node.name) node._4dom_setOwnerElement(None) self._4dom_fireMutationEvent('DOMAttrModified', relatedNode=node, attrName=node.name, attrChange=Event.MutationEvent.REMOVAL) self._4dom_fireMutationEvent('DOMSubtreeModified') return node def setAttribute(self, name, value): if not IsDOMString(value): raise SyntaxErr() if not get_name_pattern().match(name): raise InvalidCharacterErr() attr = self.attributes.getNamedItem(name) if attr: attr.value = value else: attr = self.ownerDocument.createAttribute(name) attr.value = value self.setAttributeNode(attr) # the mutation event is fired in Attr.py def setAttributeNode(self, node): if node.ownerDocument != self.ownerDocument: raise WrongDocumentErr() if node.ownerElement != None: raise InuseAttributeErr() old = self.attributes.getNamedItem(node.name) if old: self._4dom_fireMutationEvent('DOMAttrModified', relatedNode=old, prevValue=old.value, attrName=old.name, attrChange=Event.MutationEvent.REMOVAL) self.attributes.setNamedItem(node) node._4dom_setOwnerElement(self) self._4dom_fireMutationEvent('DOMAttrModified', relatedNode=node, newValue=node.value, attrName=node.name, attrChange=Event.MutationEvent.ADDITION) self._4dom_fireMutationEvent('DOMSubtreeModified') return old ### DOM Level 2 Methods ### def getAttributeNS(self, namespaceURI, localName): attr = self.attributes.getNamedItemNS(namespaceURI, localName) return attr and attr.value or '' def getAttributeNodeNS(self, namespaceURI, localName): return self.attributes.getNamedItemNS(namespaceURI, localName) def getElementsByTagNameNS(self, namespaceURI, localName): if namespaceURI == '': raise NamespaceErr("Use None instead of '' for empty namespace") nodeList = implementation._4dom_createNodeList() elements = filter(lambda node, type=Node.ELEMENT_NODE: node.nodeType == type, self.childNodes) for element in elements: if ((namespaceURI == '*' or element.namespaceURI == namespaceURI) and (localName == '*' or element.localName == localName)): nodeList.append(element) nodeList.extend(list(element.getElementsByTagNameNS(namespaceURI, localName))) return nodeList def hasAttributeNS(self, namespaceURI, localName): return self.attributes.getNamedItemNS(namespaceURI, localName) is not None def removeAttributeNS(self, namespaceURI, localName): # Silently return if not attribute node = self.attributes.getNamedItemNS(namespaceURI, localName) if node: self.removeAttributeNode(node) return def setAttributeNS(self, namespaceURI, qualifiedName, value): if not IsDOMString(value): raise SyntaxErr() if not get_name_pattern().match(qualifiedName): raise InvalidCharacterErr() prefix, localName = SplitQName(qualifiedName) attr = self.attributes.getNamedItemNS(namespaceURI, localName) if attr: attr.value = value else: attr = self.ownerDocument.createAttributeNS(namespaceURI, qualifiedName) attr.value = value self.setAttributeNodeNS(attr) return def setAttributeNodeNS(self, node): if self.ownerDocument != node.ownerDocument: raise WrongDocumentErr() if node.ownerElement != None: raise InuseAttributeErr() old = self.attributes.getNamedItemNS(node.namespaceURI, node.localName) if old: self._4dom_fireMutationEvent('DOMAttrModified', relatedNode=old, prevValue=old.value, attrName=old.name, attrChange=Event.MutationEvent.REMOVAL) self.attributes.setNamedItemNS(node) node._4dom_setOwnerElement(self) self._4dom_fireMutationEvent('DOMAttrModified', relatedNode=node, newValue=node.value, attrName=node.name, attrChange=Event.MutationEvent.ADDITION) self._4dom_fireMutationEvent('DOMSubtreeModified') return old ### Overridden Methods ### def __repr__(self): return "" % ( id(self), self.nodeName, len(self.attributes), len(self.childNodes) ) # Behind the back setting of element's ownerDocument # Also sets the owner of the NamedNodeMaps def _4dom_setOwnerDocument(self, newOwner): self.__dict__['__ownerDocument'] = newOwner self.__dict__['__attributes']._4dom_setOwnerDocument(newOwner) ### Helper Functions For Cloning ### def _4dom_clone(self, owner): e = self.__class__(owner, self.nodeName, self.namespaceURI, self.prefix, self.localName) for attr in self.attributes: clone = attr._4dom_clone(owner) if clone.localName is None: e.attributes.setNamedItem(clone) else: e.attributes.setNamedItemNS(clone) clone._4dom_setOwnerElement(e) return e def __getinitargs__(self): return (self.ownerDocument, self.nodeName, self.namespaceURI, self.prefix, self.localName ) def __getstate__(self): return (self.childNodes, self.attributes) def __setstate__(self, (children, attrs)): FtNode.__setstate__(self, children) self.__dict__['__attributes'] = attrs for attr in attrs: attr._4dom_setOwnerElement(self) ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({'tagName':_get_tagName, }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() _writeComputedAttrs.update({ }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/Entity.py0100644000076400001440000000516507253474633015141 0ustar martinusers######################################################################## # # File Name: Entity.py # # Documentation: http://docs.4suite.com/4DOM/Entity.py.html # """ Implementation of DOM Level 2 Entity interface WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from DOMImplementation import implementation from FtNode import FtNode class Entity(FtNode): nodeType = Node.ENTITY_NODE _allowedChildren = [Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE ] def __init__(self, ownerDocument, publicId, systemId, notationName): FtNode.__init__(self, ownerDocument) self.__dict__['__nodeName'] = '#entity' self.__dict__['publicId'] = publicId self.__dict__['systemId'] = systemId self.__dict__['notationName'] = notationName ### Attribute Methods ### def _get_systemId(self): return self.systemId def _get_publicId(self): return self.publicId def _get_notationName(self): return self.notationName ### Overridden Methods ### def __repr__(self): return '' % ( id(self), self.publicId, self.systemId, self.notationName) ### Helper Functions For Cloning ### def _4dom_clone(self, owner): return self.__class__(owner, self.publicId, self.systemId, self.notationName) def __getinitargs__(self): return (self.ownerDocument, self.publicId, self.systemId, self.notationName ) ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({'publicId':_get_publicId, 'systemId':_get_systemId, 'notationName':_get_notationName }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/EntityReference.py0100644000076400001440000000267607244340623016753 0ustar martinusers######################################################################## # # File Name: EntityReference.py # # Documentation: http://docs.4suite.com/4DOM/EntityReference.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from DOMImplementation import implementation from FtNode import FtNode class EntityReference(FtNode): nodeType = Node.ENTITY_REFERENCE_NODE _allowedChildren = [Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ] def __init__(self, ownerDocument, name): #Note: the Entity's name is treated as nodeName FtNode.__init__(self, ownerDocument) self.__dict__['__nodeName'] = name ### Helper Functions For Cloning ### def _4dom_clone(self, owner): return self.__class__(owner, self.nodeName) def __getinitargs__(self): return (self.ownerDocument, self.nodeName ) def __repr__(self): return '' % ( id(self), repr(self.nodeName) ) PyXML-0.8.2/xml/dom/Event.py0100644000076400001440000000666007517567472014756 0ustar martinusers######################################################################## # # File Name: Event.py # # Documentation: http://docs.4suite.com/4DOM/Event.py.html # """ Implements DOM level 2 Mutation Events WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ supportedEvents = [ "DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument", "DOMAttrModified", "DOMCharacterDataModified" ] #Event Exception code UNSPECIFIED_EVENT_TYPE_ERR = 0 class EventException: def __init__(self, code): self.code = code class EventTarget: """ """ def __init__(self): self.listeners = {} self.capture_listeners = {} for etype in supportedEvents: self.listeners[etype] = [] self.capture_listeners[etype] = [] def addEventListener(self, etype, listener, useCapture): if useCapture: if listener not in self.capture_listeners[etype]: self.capture_listeners[etype].append(listener) else: if listener not in self.listeners[etype]: self.listeners[etype].append(listener) def removeEventListener(self, etype, listener, useCapture): if useCapture: self.capture_listeners[etype].remove(listener) else: self.listeners[etype].remove(listener) def dispatchEvent(self, evt): # The actual work is done in the implementing class # since EventTarget has no idea of the DOM hierarchy pass class EventListener: def __init__(self): pass def handleEvent(evt): pass class Event: CAPTURING_PHASE = 1 AT_TARGET = 2 BUBBLING_PHASE = 3 def __init__(self, eventType): self.target = None self.currentTarget = None self.eventPhase = Event.CAPTURING_PHASE self.type = eventType self.timeStamp = 0 def stopPropagation(self): self._4dom_propagate = 0 def preventDefault(self): self._4dom_preventDefaultCalled = 1 def initEvent(self, eventTypeArg, canBubbleArg, cancelableArg): self.type = eventTypeArg self.bubbles = canBubbleArg self.cancelable = cancelableArg self._4dom_preventDefaultCalled = 0 self._4dom_propagate = 1 class MutationEvent(Event): #Whether or not the event bubbles MODIFICATION = 1 ADDITION = 2 REMOVAL = 3 eventSpec = { "DOMSubtreeModified": 1, "DOMNodeInserted": 1, "DOMNodeRemoved": 1, "DOMNodeRemovedFromDocument": 0, "DOMNodeInsertedIntoDocument": 0, "DOMAttrModified": 1, "DOMCharacterDataModified": 1 } def __init__(self, eventType): Event.__init__(self,eventType) return def initMutationEvent(self, eventTypeArg, canBubbleArg, cancelableArg, relatedNodeArg, prevValueArg, newValueArg, attrNameArg): Event.initEvent(self,eventTypeArg, canBubbleArg, cancelableArg) # FIXME : make these attributes readonly self.relatedNode = relatedNodeArg self.prevValue = prevValueArg self.newValue = newValueArg self.attrName = attrNameArg #No mutation events are cancelable self.cancelable = 0 PyXML-0.8.2/xml/dom/FtNode.py0100644000076400001440000004046507420133741015032 0ustar martinusers######################################################################## # # File Name: Node.py # # Documentation: http://docs.4suite.com/4DOM/Node.py.html # """ Implements the basic tree structure of DOM WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from DOMImplementation import implementation import Event from xml.dom import Node, EMPTY_NAMESPACE from xml.dom import NoModificationAllowedErr from xml.dom import NamespaceErr from xml.dom import NotFoundErr from xml.dom import NotSupportedErr from xml.dom import HierarchyRequestErr from xml.dom import WrongDocumentErr from xml.dom import InvalidCharacterErr from xml.dom import UnspecifiedEventTypeErr from xml.dom import XML_NAMESPACE import re, copy #FIXME: should allow combining characters: fix when Python gets Unicode g_pattPrefix = re.compile(r'[a-zA-Z_][\w\.\-_]*\Z') _namePattern = None def get_name_pattern(): # delay creating pattern until it is really needed global _namePattern if _namePattern: return _namePattern try: unicode # See whether we have Unicode support except NameError: _namePattern = re.compile('[a-zA-Z_:][\w\.\-_:]*\Z') else: import xml.utils.characters _namePattern = re.compile(xml.utils.characters.Name+'\Z') return _namePattern class FtNode(Event.EventTarget, Node): """ Encapsulates the pieces that DOM builds on the basic tree structure, Which is implemented by composition of TreeNode """ nodeType = None # Children that this node is allowed to have _allowedChildren = [] def __init__(self, ownerDocument, namespaceURI=EMPTY_NAMESPACE, prefix=None, localName=None): Event.EventTarget.__init__(self) self.__dict__['__nodeName'] = None self.__dict__['__nodeValue'] = None self.__dict__['__parentNode'] = None self.__dict__['__childNodes'] = None self.__dict__['__previousSibling'] = None self.__dict__['__nextSibling'] = None self.__dict__['__attributes'] = None self.__dict__['__ownerDocument'] = ownerDocument self.__dict__['__namespaceURI'] = namespaceURI self.__dict__['__prefix'] = prefix self.__dict__['__localName'] = localName self.__dict__['__childNodes'] = implementation._4dom_createNodeList([]) self.__dict__['__readOnly'] = 0 ### Attribute Access Methods -- Node.attr ### def __getattr__(self, name): attrFunc = self._readComputedAttrs.get(name) if attrFunc: return attrFunc(self) else: return getattr(FtNode, name) def __setattr__(self, name, value): #Make sure attribute is not read-only if name in self.__class__._readOnlyAttrs: raise NoModificationAllowedErr() #If it's computed execute that function attrFunc = self.__class__._writeComputedAttrs.get(name) if attrFunc: attrFunc(self, value) #Otherwise, just set the attribute else: self.__dict__[name] = value ### Attribute Methods -- Node._get_attr() ### def _get_nodeName(self): return self.__dict__['__nodeName'] def _get_nodeValue(self): return self.__dict__['__nodeValue'] def _set_nodeValue(self,value): self.__dict__['__nodeValue'] = value def _get_nodeType(self): return getattr(self.__class__, 'nodeType') def _get_parentNode(self): return self.__dict__['__parentNode'] def _get_childNodes(self): return self.__dict__['__childNodes'] def _get_firstChild(self): cn = self.__dict__['__childNodes'] return cn and cn[0] or None def _get_lastChild(self): cn = self.__dict__['__childNodes'] return cn and cn[-1] or None def _get_previousSibling(self): return self.__dict__['__previousSibling'] def _get_nextSibling(self): return self.__dict__['__nextSibling'] def _get_ownerDocument(self): return self.__dict__['__ownerDocument'] def _get_attributes(self): return self.__dict__['__attributes'] def _get_namespaceURI(self): return self.__dict__['__namespaceURI'] def _get_prefix(self): return self.__dict__['__prefix'] def _set_prefix(self, value): # Check for invalid characters if not get_name_pattern().match(value): raise InvalidCharacterErr() if (self.__dict__['__namespaceURI'] is None or ':' in value or (value == 'xml' and self.__dict__['__namespaceURI'] != XML_NAMESPACE)): raise NamespaceErr() self.__dict__['__prefix'] = value self.__dict__['__nodeName'] = '%s:%s' % ( value, self.__dict__['__localName']) def _get_localName(self): return self.__dict__['__localName'] ### Methods ### def insertBefore(self, newChild, refChild): if refChild is None: return self.appendChild(newChild) elif newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE: while newChild.firstChild: self.insertBefore(newChild.firstChild, refChild) else: #Make sure the newChild is all it is cracked up to be self._4dom_validateNode(newChild) #Make sure the refChild is indeed our child try: index = self.__dict__['__childNodes'].index(refChild) except: raise NotFoundErr() #Remove from old parent if newChild.parentNode != None: newChild.parentNode.removeChild(newChild); #Insert it self.__dict__['__childNodes'].insert(index, newChild) #Update the child caches newChild._4dom_setHierarchy(self, refChild.previousSibling, refChild) newChild._4dom_fireMutationEvent('DOMNodeInserted',relatedNode=self) self._4dom_fireMutationEvent('DOMSubtreeModified') return newChild def replaceChild(self, newChild, oldChild): if newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE: refChild = oldChild.nextSibling self.removeChild(oldChild) self.insertBefore(newChild, refChild) else: self._4dom_validateNode(newChild) #Make sure the oldChild is indeed our child try: index = self.__dict__['__childNodes'].index(oldChild) except: raise NotFoundErr() self.__dict__['__childNodes'][index] = newChild if newChild.parentNode is not None: newChild.parentNode.removeChild(newChild) newChild._4dom_setHierarchy(self, oldChild.previousSibling, oldChild.nextSibling) oldChild._4dom_fireMutationEvent('DOMNodeRemoved',relatedNode=self) oldChild._4dom_setHierarchy(None, None, None) newChild._4dom_fireMutationEvent('DOMNodeInserted',relatedNode=self) self._4dom_fireMutationEvent('DOMSubtreeModified') return oldChild def removeChild(self, childNode): #Make sure the childNode is indeed our child #FIXME: more efficient using list.remove() try: self.__dict__['__childNodes'].remove(childNode) except: raise NotFoundErr() childNode._4dom_fireMutationEvent('DOMNodeRemoved',relatedNode=self) self._4dom_fireMutationEvent('DOMSubtreeModified') # Adjust caches prev = childNode.previousSibling next = childNode.nextSibling if prev: prev.__dict__['__nextSibling'] = next if next: next.__dict__['__previousSibling'] = prev childNode._4dom_setHierarchy(None, None, None) return childNode def appendChild(self, newChild): if newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE: while newChild.childNodes: self.appendChild(newChild.childNodes[0]) else: self._4dom_validateNode(newChild) # Remove from old parent if newChild.parentNode != None: newChild.parentNode.removeChild(newChild); last = self.lastChild self.childNodes.append(newChild) newChild._4dom_setHierarchy(self, last, None) newChild._4dom_fireMutationEvent('DOMNodeInserted',relatedNode=self) self._4dom_fireMutationEvent('DOMSubtreeModified') return newChild def hasChildNodes(self): return self.__dict__['__childNodes'].length != 0 def cloneNode(self, deep, newOwner=None, readOnly=0): # Get constructor values clone = self._4dom_clone(newOwner or self.ownerDocument) # Set when cloning EntRef children readOnly and clone._4dom_setReadOnly(readOnly) # Copy the child nodes if deep if deep and self.nodeType != Node.ATTRIBUTE_NODE: # Children of EntRefs are cloned readOnly if self.nodeType == Node.ENTITY_REFERENCE_NODE: readOnly = 1 for child in self.childNodes: new_child = child.cloneNode(1, newOwner, readOnly) clone.appendChild(new_child) return clone def normalize(self): # This one needs to join all adjacent text nodes node = self.firstChild while node: if node.nodeType == Node.TEXT_NODE: next = node.nextSibling while next and next.nodeType == Node.TEXT_NODE: node.appendData(next.data) node.parentNode.removeChild(next) next = node.nextSibling if not node.length: # Remove any empty text nodes node.parentNode.removeChild(node) elif node.nodeType == Node.ELEMENT_NODE: for attr in node.attributes: attr.normalize() node.normalize() node = node.nextSibling def supports(self, feature, version): return implementation.hasFeature(feature,version) # # Event Target interface implementation # def dispatchEvent(self, evt): if not evt.type: raise UnspecifiedEventTypeErr() # the list of my ancestors for capture or bubbling # we are lazy, so we initialize this list only if required if evt._4dom_propagate and \ (evt.eventPhase == evt.CAPTURING_PHASE or evt.bubbles): ancestors = [self] while ancestors[-1].parentNode : ancestors.append(ancestors[-1].parentNode) # event capture if evt._4dom_propagate and evt.eventPhase == evt.CAPTURING_PHASE : ancestors.reverse() for a in ancestors[:-1]: evt.currentTarget = a for captor in a.capture_listeners[evt.type]: captor.handleEvent(evt) if not evt._4dom_propagate: break # let's put back the list in the right order # and move on to the next phase ancestors.reverse() evt.eventPhase = evt.AT_TARGET # event handling by the target if evt._4dom_propagate and evt.eventPhase == evt.AT_TARGET : evt.currentTarget = self for listener in self.listeners[evt.type]: listener.handleEvent(evt) # prepare for the next phase, if necessary if evt.bubbles: evt.eventPhase = evt.BUBBLING_PHASE # event bubbling if evt._4dom_propagate and evt.eventPhase == evt.BUBBLING_PHASE : for a in ancestors[1:]: evt.currentTarget = a for listener in a.listeners[evt.type]: listener.handleEvent(evt) if not evt._4dom_propagate: break return evt._4dom_preventDefaultCalled ### Unsupported, undocumented DOM Level 3 methods ### ### documented in the Python binding ### def isSameNode(self, other): return self == other ### Internal Methods ### #Functions not defined in the standard #All are fourthought internal functions #and should only be called by you if you specifically #don't want your program to run :) def _4dom_setattr(self, name, value): self.__dict__[name] = value def _4dom_fireMutationEvent(self,eventType,target=None, relatedNode=None,prevValue=None, newValue=None,attrName=None,attrChange=None): if self.supports('MutationEvents', 2.0): evt = self.ownerDocument.createEvent(eventType) evt.target = target or self evt.initMutationEvent(eventType,evt.eventSpec[eventType],0, relatedNode,prevValue,newValue,attrName) evt.attrChange = attrChange evt.target.dispatchEvent(evt) def _4dom_validateNode(self, newNode): if not newNode.nodeType in self.__class__._allowedChildren: raise HierarchyRequestErr() self._4dom_raiseIfAncestor(newNode) if self.ownerDocument != newNode.ownerDocument: raise WrongDocumentErr() def _4dom_raiseIfAncestor(self, node): "Helper function that raises if node is an ancestor of self or self." n = self if n is node: raise HierarchyRequestErr() if node.hasChildNodes(): while n is not None: n = n.parentNode if n is node: raise HierarchyRequestErr() def _4dom_setHierarchy(self, parent, previous, next): self.__dict__['__parentNode'] = parent if previous: previous.__dict__['__nextSibling'] = self self.__dict__['__previousSibling'] = previous self.__dict__['__nextSibling'] = next if next: next.__dict__['__previousSibling'] = self return def _4dom_setParentNode(self, parent): self.__dict__['__parentNode'] = parent def _4dom_setNextSibling(self,next): self.__dict__['__nextSibling'] = next def _4dom_setPreviousSibling(self,prev): self.__dict__['__previousSibling'] = prev def _4dom_setOwnerDocument(self, owner): self.__dict__['__ownerDocument'] = owner def _4dom_setReadOnly(self, flag): self.__dict__['__readOnly'] = flag ### Helper Functions For Cloning ### def _4dom_clone(self, owner): raise NotSupportedErr('Subclass must override') def __getinitargs__(self): return (self.__dict__['__ownerDocument'], self.__dict__['__namespaceURI'], self.__dict__['__prefix'], self.__dict__['__localName'] ) def __getstate__(self): return self.__dict__['__childNodes'] def __setstate__(self, children): self.__dict__['__childNodes'].extend(list(children)) prev = None for child in children: child._4dom_setHierarchy(self, prev, None) prev = child ### Attribute Access Mappings ### _readComputedAttrs = {'nodeName':_get_nodeName, 'nodeValue':_get_nodeValue, 'nodeType':_get_nodeType, 'parentNode':_get_parentNode, 'childNodes':_get_childNodes, 'firstChild':_get_firstChild, 'lastChild':_get_lastChild, 'previousSibling':_get_previousSibling, 'nextSibling':_get_nextSibling, 'attributes':_get_attributes, 'ownerDocument':_get_ownerDocument, 'namespaceURI':_get_namespaceURI, 'prefix':_get_prefix, 'localName':_get_localName } _writeComputedAttrs = {'nodeValue':_set_nodeValue, 'prefix':_set_prefix } # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/MessageSource.py0100644000076400001440000000452507517567472016440 0ustar martinusers# DOMException from xml.dom import INDEX_SIZE_ERR, DOMSTRING_SIZE_ERR , HIERARCHY_REQUEST_ERR from xml.dom import WRONG_DOCUMENT_ERR, INVALID_CHARACTER_ERR, NO_DATA_ALLOWED_ERR from xml.dom import NO_MODIFICATION_ALLOWED_ERR, NOT_FOUND_ERR, NOT_SUPPORTED_ERR from xml.dom import INUSE_ATTRIBUTE_ERR, INVALID_STATE_ERR, SYNTAX_ERR from xml.dom import INVALID_MODIFICATION_ERR, NAMESPACE_ERR, INVALID_ACCESS_ERR from xml.dom import VALIDATION_ERR # EventException from xml.dom import UNSPECIFIED_EVENT_TYPE_ERR #Range Exceptions from xml.dom import BAD_BOUNDARYPOINTS_ERR from xml.dom import INVALID_NODE_TYPE_ERR # Fourthought Exceptions from xml.dom import XML_PARSE_ERR try: import os, gettext locale_dir = os.path.split(__file__)[0] gettext.install('4Suite', locale_dir) except (ImportError, AttributeError, IOError): def _(msg): return msg DOMExceptionStrings = { INDEX_SIZE_ERR: _("Index error accessing NodeList or NamedNodeMap"), DOMSTRING_SIZE_ERR: _("DOMString exceeds maximum size"), HIERARCHY_REQUEST_ERR: _("Node manipulation results in invalid parent/child relationship."), WRONG_DOCUMENT_ERR: _("Node is from a different document"), INVALID_CHARACTER_ERR: _("Invalid or illegal character"), NO_DATA_ALLOWED_ERR: _("Node does not support data"), NO_MODIFICATION_ALLOWED_ERR: _("Attempt to modify a read-only object"), NOT_FOUND_ERR: _("Node does not exist in this context"), NOT_SUPPORTED_ERR: _("Object or operation not supported"), INUSE_ATTRIBUTE_ERR: _("Attribute already in use by an element"), INVALID_STATE_ERR: _("Object is not, or is no longer, usable"), SYNTAX_ERR: _("Specified string is invalid or illegal"), INVALID_MODIFICATION_ERR: _("Attempt to modify the type of a node"), NAMESPACE_ERR: _("Invalid or illegal namespace operation"), INVALID_ACCESS_ERR: _("Object does not support this operation or parameter"), VALIDATION_ERR: _("Operation would invalidate partial validity constraint"), } EventExceptionStrings = { UNSPECIFIED_EVENT_TYPE_ERR : _("Uninitialized type in Event object"), } FtExceptionStrings = { XML_PARSE_ERR : _("XML parse error at line %d, column %d: %s"), } RangeExceptionStrings = { BAD_BOUNDARYPOINTS_ERR : _("Invalid Boundary Points specified for Range"), INVALID_NODE_TYPE_ERR : _("Invalid Container Node") } PyXML-0.8.2/xml/dom/NamedNodeMap.py0100644000076400001440000001200507410644304016131 0ustar martinusers######################################################################## # # File Name: NamedNodeMap.py # # Documentation: http://docs.4suite.com/4DOM/NamedNodeMap.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import UserDict class _NamedNodeMapIter: """Iterator class for Python 2.2. The iterator function is .next, the stop-iterator element is the iterator itself.""" def __init__(self,map): self.pos = 0 self.map = map def next(self): try: res = self.map[self.pos] self.pos = self.pos + 1 return res except IndexError: return self from xml.dom import Node from xml.dom import EMPTY_NAMESPACE from xml.dom import NoModificationAllowedErr from xml.dom import NotFoundErr from xml.dom import NotSupportedErr from xml.dom import WrongDocumentErr from xml.dom import InuseAttributeErr from xml.dom import NamespaceErr class NamedNodeMap(UserDict.UserDict): def __init__(self, ownerDoc=None): UserDict.UserDict.__init__(self) self._ownerDocument = ownerDoc self._positions = [] ### Attribute Access Methods ### def __getattr__(self, name): if name == 'length': return len(self) return getattr(NamedNodeMap, name) def __setattr__(self, name, value): if name == 'length': raise NoModificationAllowedErr() self.__dict__[name] = value ### Attribute Methods ### def _get_length(self): return len(self) ### Methods ### def item(self, index): if 0 <= index < len(self): return self[self._positions[int(index)]] return None def getNamedItem(self, name): try: return self[name] except KeyError: # fall-back to namespace API return self.get((EMPTY_NAMESPACE, name)) def removeNamedItem(self, name): old = self.get(name) if not old: # fall-back to namespace API return self.removeNamedItemNS(EMPTY_NAMESPACE, name) del self[name] self._positions.remove(name) return old def setNamedItem(self, arg): if self._ownerDocument != arg.ownerDocument: raise WrongDocumentErr() if arg.nodeType == Node.ATTRIBUTE_NODE and arg.ownerElement != None: raise InuseAttributeErr() name = arg.nodeName retval = self.get(name) UserDict.UserDict.__setitem__(self, name, arg) if not retval: retval = self.get((EMPTY_NAMESPACE, name)) if retval: self._positions.remove((EMPTY_NAMESPACE, name)) del self[(EMPTY_NAMESPACE, name)] self._positions.append(name) return retval def getNamedItemNS(self, namespaceURI, localName): if namespaceURI == '': raise NamespaceErr("Use None instead of '' for empty namespace") return self.get((namespaceURI, localName)) def setNamedItemNS(self, arg): if self._ownerDocument != arg.ownerDocument: raise WrongDocumentErr() if arg.nodeType == Node.ATTRIBUTE_NODE and arg.ownerElement != None: raise InuseAttributeErr() if arg.namespaceURI == '': raise NamespaceErr("Use None instead of '' for empty namespace") name = (arg.namespaceURI, arg.localName) retval = self.get(name) UserDict.UserDict.__setitem__(self, name, arg) if not retval: self._positions.append(name) return retval def removeNamedItemNS(self, namespaceURI, localName): if namespaceURI == '': raise NamespaceErr("Use None instead of '' for empty namespace") name = (namespaceURI, localName) old = self.get(name) if not old: raise NotFoundErr() del self[name] self._positions.remove(name) return old ### Overridden Methods ### def __getitem__(self, index): if type(index) == type(0): index = self._positions[index] return UserDict.UserDict.__getitem__(self, index) def __setitem__(self, index, item): raise NotSupportedErr() def __iter__(self): i = _NamedNodeMapIter(self) return iter(i.next, i) def __repr__(self): st = "' ### Internal Methods ### def _4dom_setOwnerDocument(self, newOwner): self._ownerDocument = newOwner def _4dom_clone(self, owner): nnm = self.__class__(owner) for item in self: if item.localName: nnm.setNamedItemNS(item._4dom_clone(owner)) else: nnm.setNamedItem(item._4dom_clone(owner)) return nnm PyXML-0.8.2/xml/dom/NodeFilter.py0100644000076400001440000000165107614620060015700 0ustar martinusers# This is the Python mapping for interface NodeFilter from # DOM2-Traversal-Range. It contains only constants. class NodeFilter: """ This is the DOM2 NodeFilter interface. It contains only constants. """ FILTER_ACCEPT = 1 FILTER_REJECT = 2 FILTER_SKIP = 3 SHOW_ALL = 0xFFFFFFFFL SHOW_ELEMENT = 0x00000001 SHOW_ATTRIBUTE = 0x00000002 SHOW_TEXT = 0x00000004 SHOW_CDATA_SECTION = 0x00000008 SHOW_ENTITY_REFERENCE = 0x00000010 SHOW_ENTITY = 0x00000020 SHOW_PROCESSING_INSTRUCTION = 0x00000040 SHOW_COMMENT = 0x00000080 SHOW_DOCUMENT = 0x00000100 SHOW_DOCUMENT_TYPE = 0x00000200 SHOW_DOCUMENT_FRAGMENT = 0x00000400 SHOW_NOTATION = 0x00000800 def acceptNode(self, node): raise NotImplementedError PyXML-0.8.2/xml/dom/NodeIterator.py0100644000076400001440000000774707253474633016274 0ustar martinusers######################################################################## # # File Name: NodeIterator.py # # Documentation: http://docs.4suite.com/4DOM/NodeIterator.py.html # """ Node Iterators from DOM Level 2. Allows "flat" iteration over nodes. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from NodeFilter import NodeFilter from xml.dom import NoModificationAllowedErr from xml.dom import InvalidStateErr class NodeIterator: def __init__(self, root, whatToShow, filter, expandEntityReferences): self.__dict__['root'] = root self.__dict__['filter'] = filter self.__dict__['expandEntityReferences'] = expandEntityReferences self.__dict__['whatToShow'] = whatToShow self.__dict__['_atStart'] = 1 self.__dict__['_atEnd'] = 0 self.__dict__['_current'] = root self.__dict__['_nodeStack'] = [] self.__dict__['_detached'] = 0 def __setattr__(self, name, value): if name in ['root', 'filter', 'expandEntityReferences', 'whatToShow']: raise NoModificationAllowedErr() self.__dict__[name] = value def _get_root(self): return self.root def _get_filter(self): return self.filter def _get_expandEntityReferences(self): return self.expandEntityReferences def _get_whatToShow(self): return self.whatToShow def nextNode(self): if self._detached: raise InvalidStateErr() next_node = self._advance() while (next_node and not ( self._checkWhatToShow(next_node) and self._checkFilter(next_node) == NodeFilter.FILTER_ACCEPT)): next_node = self._advance() return next_node def previousNode(self): if self._detached: raise InvalidStateErr() prev_node = self._regress() while (prev_node and not ( self._checkWhatToShow(prev_node) and self._checkFilter(prev_node) == NodeFilter.FILTER_ACCEPT)): prev_node = self._regress() return prev_node def detach(self): self._detached = 1 def _advance(self): node = None if self._atStart: # First time through self._atStart = 0 node = self._current elif not self._atEnd: current = self._current if current.firstChild: # Do children first node = current.firstChild else: # Now try the siblings while current is not self.root: if current.nextSibling: node = current.nextSibling break # We are at the end of a branch, starting going back up current = current.parentNode else: node = None if node: self._current = node else: self._atEnd = 1 return node def _regress(self): node = None if self._atEnd: self._atEnd = 0 node = self._current elif not self._atStart: current = self._current if current is self.root: node = None elif current.previousSibling: node = current.previousSibling if node.lastChild: node = node.lastChild else: node = current.parentNode if node: self._current = node else: self._atStart = 1 return node def _checkWhatToShow(self, node): show_bit = 1 << (node.nodeType - 1) return self.whatToShow & show_bit def _checkFilter(self, node): if self.filter: return self.filter.acceptNode(node) else: return NodeFilter.FILTER_ACCEPT PyXML-0.8.2/xml/dom/NodeList.py0100644000076400001440000000274707253474633015411 0ustar martinusers######################################################################## # # File Name: NodeList.py # # Documentation: http://docs.4suite.com/4DOM/NodeList.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import UserList from xml.dom import NoModificationAllowedErr class NodeList(UserList.UserList): def __init__(self, list=None): UserList.UserList.__init__(self, list) return ### Attribute Access Methods ### def __getattr__(self, name): if name == 'length': return len(self) #Pass-through return getattr(NodeList, name) def __setattr__(self, name, value): if name == 'length': raise NoModificationAllowedErr() #Pass-through self.__dict__[name] = value ### Attribute Methods ### def _get_length(self): return len(self) ### Methods ### def item(self, index): if 0 <= index < len(self): return self[int(index)] return None #Not defined in the standard def contains(self, node): return node in self def __repr__(self): st = "' return st PyXML-0.8.2/xml/dom/Notation.py0100644000076400001440000000411507253474633015452 0ustar martinusers######################################################################## # # File Name: Notation.py # # Documentation: http://docs.4suite.org/4DOM/Notation.py.html # """ Implementation of DOM Level 2 Notation interface WWW: http://4suite.org/4DOM e-mail: support@4suite.org Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.dom import Node from FtNode import FtNode class Notation(FtNode): nodeType = Node.NOTATION_NODE def __init__(self, ownerDocument, publicId, systemId, name): FtNode.__init__(self, ownerDocument) self.__dict__['__nodeName'] = name self.__dict__['publicId'] = publicId self.__dict__['systemId'] = systemId ### Attribute Methods ### def _get_systemId(self): return self.systemId def _get_publicId(self): return self.publicId ### Overridden Methods ### def __repr__(self): return '' % ( id(self), self.publicId, self.systemId, self.nodeName) ### Helper Functions For Cloning ### def _4dom_clone(self, owner): return self.__class__(owner, self.publicId, self.systemId, self.nodeName) def __getinitargs__(self): return (self.ownerDocument, self.publicId, self.systemId, self.nodeName ) ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({'publicId':_get_publicId, 'systemId':_get_systemId }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/ProcessingInstruction.py0100644000076400001440000000416207377133276020241 0ustar martinusers######################################################################## # # File Name: ProcessingInstruction.py # # Documentation: http://docs.4suite.com/4DOM/ProcessingInstruction.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node, EMPTY_NAMESPACE from FtNode import FtNode class ProcessingInstruction(FtNode): nodeType = Node.PROCESSING_INSTRUCTION_NODE def __init__(self,ownerDocument,target,data): FtNode.__init__(self,ownerDocument,EMPTY_NAMESPACE,'','') self.__dict__['__nodeName'] = target self.__dict__['__nodeValue'] = data def _get_target(self): return self.__dict__['__nodeName'] def _get_data(self): return self.__dict__['__nodeValue'] def _set_data(self, newData): self.__dict__['__nodeValue'] = newData ### Overridden Methods ### def __repr__(self): data = self.data if len(data) > 20: data = data[20:] + '...' return "" % ( id(self), self.target, data ) ### Helper Functions For Cloning ### def _4dom_clone(self, owner): return self.__class__(owner, self.target, self.data) def __getinitargs__(self): return (self.ownerDocument, self.target, self.data ) ### Attribute Access Mappings ### _readComputedAttrs = FtNode._readComputedAttrs.copy() _readComputedAttrs.update({'target':_get_target, 'data':_get_data }) _writeComputedAttrs = FtNode._writeComputedAttrs.copy() _writeComputedAttrs.update({'data':_set_data }) # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), FtNode._readOnlyAttrs + _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/README0100644000076400001440000000215207117052605014152 0ustar martinusers4DOM Copyright (C) 2000 Fourthought Inc, USA http://lists.fourthought.com/mailman/listinfo/4suite support@4suite.com Description =========== 4DOM is an implementation of the World-Wide Web Consortium recommended standard document object model for Python. 4DOM implements DOM Core level 2, HTML level 2 and Level 2 Document Traversal. 4DOM should work on all platforms supported by Python. If you have any problems with a particular platform, please e-mail the authors. License/Copyright ================= 4DOM is copyrighted by Fourthought Inc (http://Fourthought.com). Please read the file COPYRIGHT for the complete copyright and terms of license. Documentation ============= Please see the file docs/4DOM.html for general documentation The DOM API is specified at http://www.w3.org/TR/DOM-Level-2/ Known Bugs ========== Contact and Support =================== Please consider joining the 4Suite users and support mailing list http://lists.fourthought.com/mailman/listinfo/4suite Or, if you prefer, you can address the 4Suite developers directly: support@4suite.com PyXML-0.8.2/xml/dom/Range.py0100644000076400001440000011650007335313464014710 0ustar martinusers######################################################################## # # File Name: Range.py # # Documentation: http://docs.4suite.com/4DOM/Range.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import InvalidStateErr from xml.dom import InvalidNodeTypeErr from xml.dom import BadBoundaryPointsErr from xml.dom import IndexSizeErr from xml.dom import WrongDocumentErr from xml.dom import Node class Range: readOnly =['startContainer', 'startOffset', 'endContainer', 'endOffset', 'collapsed', 'commonAncestorContainer', ] POSITION_EQUAL = 1 POSITION_LESS_THAN = 2 POSITION_GREATER_THAN = 3 START_TO_START = 0 START_TO_END = 1 END_TO_END = 2 END_TO_START = 3 def __init__(self,ownerDocument): self._ownerDocument = ownerDocument self.__dict__['startContainer'] = ownerDocument self.__dict__['startOffset'] = 0 self.__dict__['endContainer'] = ownerDocument self.__dict__['endOffset'] = 0 self.__dict__['collapsed'] = 1 self.__dict__['commonAncestorContainer'] = ownerDocument self.__dict__['detached'] = 0 def __setattr__(self,name,value): if name in self.readOnly: raise AttributeError, name self.__dict__[name] = value def __getattr__(self,name): if name in self.readOnly: #Means we are detached raise InvalidStateErr() raise AttributeError, name def cloneContents(self): """Clone the contents defined by this range""" if self.detached: raise InvalidStateErr() df = self._ownerDocument.createDocumentFragment() if self.startContainer == self.endContainer: if self.startOffset == self.endOffset: return df if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data data = self.startContainer.substringData(self.startOffset,1+self.endOffset-self.startOffset) tx = self._ownerDocument.createTextNode(data) df.appendChild(tx) else: #Clone a set number of children numDel = self.endOffset - self.startOffset+1 for ctr in range(numDel): c = self.startContainer.childNodes[self.startOffset+ctr].cloneNode(1) df.appendChild(c) elif self.startContainer == self.commonAncestorContainer: #Clone up the endContainer #From the start to the end lastKids = [] copyData = None if self.endContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data copyData = self.endContainer.substringData(0,self.endOffset) else: numDel = self.endOffset for ctr in range(numDel): lastKids.append(self.endContainer.childNodes[ctr].cloneNode(1)) cur = self.endContainer while cur.parentNode != self.commonAncestorContainer: #Clone all of the way up newCur = cur.cloneNode(0) if copyData: newCur.data = copyData copyData = None for k in lastKids: newCur.appendChild(k) lastKids = [] index = cur.parentNode.childNodes.index(cur) for ctr in range(index): lastKids.append(cur.parentNode.childNodes[ctr].cloneNode(1)) lastKids.append(newCur) cur = cur.parentNode newEnd = cur.cloneNode(0) for k in lastKids: newEnd.appendChild(k) endAncestorChild = cur #Extract up to the ancestor of end for c in self.startContainer.childNodes: if c == endAncestorChild: break df.appendChild(c.cloneNode(1)) df.appendChild(newEnd) elif self.endContainer == self.commonAncestorContainer: lastKids = [] copyData = None if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data copyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) else: numDel = len(self.startContainer.childNodes) - self.startOffset for ctr in range(numDel): c = self.startContainer.childNodes[self.startOffset+ctr].cloneNode(1) lastKids.append(c) cur = self.startContainer while cur.parentNode != self.commonAncestorContainer: #Clone all of the way up newCur = cur.cloneNode(0) if copyData: newCur.data = copyData copyData = None for k in lastKids: newCur.appendChild(k) lastKids = [newCur] index = cur.parentNode.childNodes.index(cur) for ctr in range(index+1,len(cur.parentNode.childNodes)): lastKids.append(cur.parentNode.childNodes[ctr].cloneNode(1)) cur = cur.parentNode startAncestorChild = cur newStart = cur.cloneNode(0) for k in lastKids: newStart.appendChild(k) df.appendChild(newStart) #Extract up to the ancestor of start startAncestorChild = cur startIndex = self.endContainer.childNodes.index(cur) lastAdded = None for ctr in range(startIndex+1,self.endOffset+1): c = self.endContainer.childNodes[ctr].cloneNode(1) df.insertBefore(c,lastAdded) lastAdded = c else: #From the start to the end lastStartKids = [] startCopyData = None if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data startCopyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) else: numDel = len(self.startContainer.childNodes) - self.startOffset for ctr in range(numDel): c = self.startContainer.childNodes[self.startOffset+ctr].cloneNode(1) lastStartKids.append(c) cur = self.startContainer while cur.parentNode != self.commonAncestorContainer: #Clone all of the way up newCur = cur.cloneNode(0) if startCopyData: newCur.data = startCopyData startCopyData = None for k in lastStartKids: newCur.appendChild(k) lastStartKids = [newCur] index = cur.parentNode.childNodes.index(cur) for ctr in range(index+1,len(cur.parentNode.childNodes)): lastStartKids.append(cur.parentNode.childNodes[ctr].cloneNode(1)) cur = cur.parentNode startAncestorChild = cur newStart = cur.cloneNode(0) for k in lastStartKids: newStart.appendChild(k) df.appendChild(newStart) lastEndKids = [] endCopyData = None #Delete up the endContainer #From the start to the end if self.endContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data endCopyData = self.endContainer.substringData(0,self.endOffset) else: numDel = self.endOffset for ctr in range(numDel): c = self.endContainer.childNodes[ctr].cloneNode(1) lastEndKids.append(c) cur = self.endContainer while cur.parentNode != self.commonAncestorContainer: newCur = cur.cloneNode(0) if endCopyData: newCur.data = endCopyData endCopyData = None for k in lastEndKids: newCur.appendChild(k) lastEndKids = [] index = cur.parentNode.childNodes.index(cur) for ctr in range(index): lastEndKids.append(cur.parentNode.childNodes[ctr].cloneNode(1)) lastEndKids.append(newCur) cur = cur.parentNode endAncestorChild = cur newEnd = cur.cloneNode(0) for k in lastEndKids: newEnd.appendChild(k) cur = startAncestorChild #Extract everything between us startIndex = startAncestorChild.parentNode.childNodes.index(startAncestorChild) endIndex = endAncestorChild.parentNode.childNodes.index(endAncestorChild) for ctr in range(startIndex+1,endIndex): c = startAncestorChild.parentNode.childNodes[ctr] df.appendChild(c.cloneNode(1)) df.appendChild(newEnd) #Adjust the containers #FIXME What the heck is the spec talking about?? self.__dict__['endContainer'] = self.startContainer self.__dict__['endOffset'] = self.startContainer self.__dict__['commonAncestorContainer'] = self.startContainer self.__dict__['collapsed'] = 1 return df def cloneRange(self): if self.detached: raise InvalidStateErr() newRange = Range(self._ownerDocument) newRange.setStart(self.startContainer,self.startOffset) newRange.setEnd(self.endContainer,self.endOffset) return newRange def collapse(self,toStart): """Collapse the range""" if self.detached: raise InvalidStateErr() if toStart: self.__dict__['endContainer'] = self.startContainer self.__dict__['endOffset'] = self.startOffset else: self.__dict__['startContainer'] = self.endContainer self.__dict__['startOffset'] = self.endOffset self.__dict__['collapsed'] = 1 self.__dict__['commonAncestorContainer'] = self.startContainer def compareBoundaryPoints(self,how,sourceRange): if self.detached: raise InvalidStateErr() if not hasattr(sourceRange,'_ownerDocument') or sourceRange._ownerDocument != self._ownerDocument or not isinstance(sourceRange,Range): raise WrongDocumentErr() if how == self.START_TO_START: ac = self.startContainer ao = self.startOffset bc = sourceRange.startContainer bo = sourceRange.startOffset elif how == self.START_TO_END: ac = self.startContainer ao = self.startOffset bc = sourceRange.endContainer bo = sourceRange.endOffset elif how == self.END_TO_END: ac = self.endContainer ao = self.endOffset bc = sourceRange.endContainer bo = sourceRange.endOffset elif how == self.END_TO_START: ac = self.endContainer ao = self.endOffset bc = sourceRange.startContainer bo = sourceRange.startOffset else: raise TypeError, how pos = self.__comparePositions(ac,ao,bc,bo) if pos == self.POSITION_EQUAL: return 0 elif pos == self.POSITION_LESS_THAN: return -1 return 1 def deleteContents(self): """Delete the contents defined by this range""" #NOTE Use 4DOM ReleaseNode cause it is interface safe from xml.dom.ext import ReleaseNode if self.detached: raise InvalidStateErr() if self.startContainer == self.endContainer: if self.startOffset == self.endOffset: return if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data self.startContainer.deleteData(self.startOffset,1+self.endOffset-self.startOffset) else: #Delete a set number of children numDel = self.endOffset - self.startOffset+1 for ctr in range(numDel): c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset]) ReleaseNode(c) self.__dict__['endContainer'] = self.startContainer self.__dict__['endOffset'] = self.endContainer self.__dict__['commonAncestorContainer'] = self.endContainer self.__dict__['collapsed'] = 1 elif self.startContainer == self.commonAncestorContainer: #Delete up the endContainer #From the start to the end if self.endContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data self.endContainer.deleteData(0,self.endOffset) else: numDel = self.endOffset for ctr in range(numDel): c = self.endContainer.removeChild(self.endContainer.childNodes[0]) ReleaseNode(c) cur = self.endContainer while cur.parentNode != self.commonAncestorContainer: while cur.previousSibling: c = cur.parentNode.removeChild(cur.previousSibling) ReleaseNode(c) cur = cur.parentNode #Delete up to the ancestor of end endAncestorChild = cur while self.startContainer.firstChild != endAncestorChild: c = self.startContainer.removeChild(self.startContainer.firstChild) ReleaseNode(c) elif self.endContainer == self.commonAncestorContainer: if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) else: numDel = len(self.startContainer.childNodes) - self.startOffset for ctr in range(numDel): c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset]) ReleaseNode(c) cur = self.startContainer while cur.parentNode != self.commonAncestorContainer: while cur.nextSibling: c = cur.parentNode.removeChild(cur.nextSibling) ReleaseNode(c) cur = cur.parentNode startAncestorChild = cur #Delete up to the ancestor of start startAncestorChild = cur startIndex = self.endContainer.childNodes.index(cur) numDel = self.endOffset - startIndex for ctr in range(numDel): c = self.endContainer.removeChild(startAncestorChild.nextSibling) ReleaseNode(c) else: #From the start to the end if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) else: numDel = len(self.startContainer.childNodes) - self.startOffset for ctr in range(numDel): c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset]) ReleaseNode(c) cur = self.startContainer while cur.parentNode != self.commonAncestorContainer: while cur.nextSibling: c = cur.parentNode.removeChild(cur.nextSibling) ReleaseNode(c) cur = cur.parentNode startAncestorChild = cur #Delete up the endContainer #From the start to the end if self.endContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data self.endContainer.deleteData(0,self.endOffset) else: numDel = self.endOffset for ctr in range(numDel): c = self.endContainer.removeChild(self.endContainer.childNodes[0]) ReleaseNode(c) cur = self.endContainer while cur.parentNode != self.commonAncestorContainer: while cur.previousSibling: c = cur.parentNode.removeChild(cur.previousSibling) ReleaseNode(c) cur = cur.parentNode endAncestorChild = cur cur = startAncestorChild #Delete everything between us while cur.nextSibling != endAncestorChild: c = cur.parentNode.removeChild(cur.nextSibling) ReleaseNode(c) #Adjust the containers #FIXME What the heck is the spec talking about?? self.__dict__['endContainer'] = self.startContainer self.__dict__['endOffset'] = self.startContainer self.__dict__['commonAncestorContainer'] = self.startContainer self.__dict__['collapsed'] = 1 return None def detach(self): self.detached = 1 del self.startContainer del self.endContainer del self.startOffset del self.endOffset del self.collapsed del self.commonAncestorContainer def extractContents(self): """Extract the contents defined by this range""" if self.detached: raise InvalidStateErr() df = self._ownerDocument.createDocumentFragment() if self.startContainer == self.endContainer: if self.startOffset == self.endOffset: return df if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data data = self.startContainer.substringData(self.startOffset,1+self.endOffset-self.startOffset) self.startContainer.deleteData(self.startOffset,1+self.endOffset-self.startOffset) tx = self._ownerDocument.createTextNode(data) df.appendChild(tx) else: #Extrace a set number of children numDel = self.endOffset - self.startOffset+1 for ctr in range(numDel): c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset]) df.appendChild(c) elif self.startContainer == self.commonAncestorContainer: #Delete up the endContainer #From the start to the end lastKids = [] copyData = None #Delete up the endContainer #From the start to the end if self.endContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data copyData = self.endContainer.substringData(0,self.endOffset) self.endContainer.deleteData(0,self.endOffset) else: numDel = self.endOffset for ctr in range(numDel): c = self.endContainer.removeChild(self.endContainer.childNodes[0]) lastKids.append(c) cur = self.endContainer while cur.parentNode != self.commonAncestorContainer: #Clone all of the way up newCur = cur.cloneNode(0) if copyData: newCur.data = copyData copyData = None for k in lastKids: newCur.appendChild(k) lastKids = [newCur] while cur.previousSibling: c = cur.parentNode.removeChild(cur.previousSibling) lastKids = [c] + lastKids cur = cur.parentNode newEnd = cur.cloneNode(0) for k in lastKids: newEnd.appendChild(k) endAncestorChild = cur #Extract up to the ancestor of end while self.startContainer.firstChild != endAncestorChild: c = self.startContainer.removeChild(self.startContainer.firstChild) df.appendChild(c) df.appendChild(newEnd) elif self.endContainer == self.commonAncestorContainer: lastKids = [] copyData = None if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data copyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) else: numDel = len(self.startContainer.childNodes) - self.startOffset for ctr in range(numDel): c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset]) lastKids.append(c) cur = self.startContainer while cur.parentNode != self.commonAncestorContainer: #Clone all of the way up newCur = cur.cloneNode(0) if copyData: newCur.data = copyData copyData = None for k in lastKids: newCur.appendChild(k) lastKids = [newCur] while cur.nextSibling: c = cur.parentNode.removeChild(cur.nextSibling) lastKids.append(c) cur = cur.parentNode startAncestorChild = cur newStart = cur.cloneNode(0) for k in lastKids: newStart.appendChild(k) df.appendChild(newStart) #Extract up to the ancestor of start startAncestorChild = cur startIndex = self.endContainer.childNodes.index(cur) lastAdded = None numDel = self.endOffset - startIndex for ctr in range(numDel): c = self.endContainer.removeChild(startAncestorChild.nextSibling) df.insertBefore(c,lastAdded) lastAdded = c else: #From the start to the end lastStartKids = [] startCopyData = None if self.startContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data startCopyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset) else: numDel = len(self.startContainer.childNodes) - self.startOffset for ctr in range(numDel): c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset]) lastStartKids.append(c) cur = self.startContainer while cur.parentNode != self.commonAncestorContainer: #Clone all of the way up newCur = cur.cloneNode(0) if startCopyData: newCur.data = startCopyData startCopyData = None for k in lastStartKids: newCur.appendChild(k) lastStartKids = [newCur] while cur.nextSibling: c = cur.parentNode.removeChild(cur.nextSibling) lastStartKids.append(c) cur = cur.parentNode startAncestorChild = cur newStart = cur.cloneNode(0) for k in lastStartKids: newStart.appendChild(k) if startCopyData: newStart.data = startCopyData startCopyData = None df.appendChild(newStart) lastEndKids = [] endCopyData = None #Delete up the endContainer #From the start to the end if self.endContainer.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Adjust the character data endCopyData = self.endContainer.substringData(0,self.endOffset) self.endContainer.deleteData(0,self.endOffset) else: numDel = self.endOffset for ctr in range(numDel): c = self.endContainer.removeChild(self.endContainer.childNodes[0]) lastEndKids.append(c) cur = self.endContainer while cur.parentNode != self.commonAncestorContainer: newCur = cur.cloneNode(0) if endCopyData: newCur.data = endCopyData endCopyData = None for k in lastEndKids: newCur.appendChild(k) lastEndKids = [newCur] while cur.previousSibling: c = cur.parentNode.removeChild(cur.previousSibling) lastEndKids = [c] + lastEndKids cur = cur.parentNode endAncestorChild = cur newEnd = cur.cloneNode(0) for k in lastEndKids: newEnd.appendChild(k) if endCopyData: newEnd.data = endCopyData endCopyData = None cur = startAncestorChild #Extract everything between us while cur.nextSibling != endAncestorChild: c = cur.parentNode.removeChild(cur.nextSibling) df.appendChild(c) df.appendChild(newEnd) #Adjust the containers #FIXME What the heck is the spec talking about?? self.__dict__['endContainer'] = self.startContainer self.__dict__['endOffset'] = self.startOffset self.__dict__['commonAncestorContainer'] = self.startContainer self.__dict__['collapsed'] = 1 return df def insertNode(self,newNode): """Insert a node at the starting point""" if self.detached: raise InvalidStateErr() if newNode.nodeType in [Node.ATTRIBUTE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE, Node.DOCUMENT_NODE, ]: raise InvalidNodeTypeErr() if self.startContainer.nodeType == Node.TEXT_NODE: #Split the text at the boundary. Insert the node after this otherText = self.startContainer.substringData(self.startOffset,len(self.startContainer.data)) self.startContainer.deleteData(self.startOffset,len(self.startContainer.data)) newText = self._ownerDocument.createTextNode(otherText) self.startContainer.parentNode.insertBefore(newText,self.startContainer.nextSibling) newText.parentNode.insertBefore(newNode,newText) elif self.startContainer.nodeType in [Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: raise HierarchyRequestErr() else: curNode = self.startContainer.childNodes[self.startOffset] self.startContainer.insertBefore(newNode,curNode.nextSibling) def selectNode(self,refNode): """Select a node""" if self.detached: raise InvalidStateErr() self.__validateRefNode(refNode) self.__dict__['startContainer'] = refNode.parentNode self.__dict__['endContainer'] = refNode.parentNode index = refNode.parentNode.childNodes.index(refNode) self.__dict__['startOffset'] = index self.__dict__['endOffset'] = index+1 self.__dict__['collapsed'] = 0 self.__dict__['commonAncestorContainer'] = refNode.parentNode def selectNodeContents(self,refNode): """Select a node""" if self.detached: raise InvalidStateErr() self.__validateBoundary(refNode,0) self.__dict__['startContainer'] = refNode self.__dict__['endContainer'] = refNode self.__dict__['startOffset'] = 0 self.__dict__['endOffset'] = len(refNode.childNodes) self.__dict__['collapsed'] = self.startOffset == self.endOffset self.__dict__['commonAncestorContainer'] = refNode def setEnd(self,parent,offset): """Set the ranges end container and offset""" #Check for errors if self.detached: raise InvalidStateErr() self.__validateBoundary(parent,offset) self.__dict__['endContainer'] = parent self.__dict__['endOffset'] = offset self.__dict__['collapsed'] = 0 pos = self.__comparePositions(parent,offset,self.startContainer,self.startOffset) self.__dict__['collapsed'] = (pos == self.POSITION_EQUAL) if pos == self.POSITION_LESS_THAN: self.__dict__['startContainer'] = parent self.__dict__['startOffset'] = offset self.__dict__['collapsed'] = 1 self.__calculateCommonAncestor() def setEndAfter(self,node): self.__validateRefNode(node) cont = node.parentNode index = cont.childNodes.index(node) self.setEnd(cont,index+1) def setEndBefore(self,node): self.__validateRefNode(node) cont = node.parentNode index = cont.childNodes.index(node) self.setEnd(cont,index) def setStart(self,parent,offset): """Set the ranges start container and offset""" #Check for errors if self.detached: raise InvalidStateErr() self.__validateBoundary(parent,offset) self.__dict__['startContainer'] = parent self.__dict__['startOffset'] = offset pos = self.__comparePositions(parent,offset,self.endContainer,self.endOffset) self.__dict__['collapsed'] = (pos == self.POSITION_EQUAL) if pos == self.POSITION_GREATER_THAN: self.__dict__['endContainer'] = parent self.__dict__['endOffset'] = offset self.__dict__['collapsed'] = 1 self.__calculateCommonAncestor() def setStartAfter(self,node): self.__validateRefNode(node) cont = node.parentNode index = cont.childNodes.index(node) self.setStart(cont,index+1) def setStartBefore(self,node): self.__validateRefNode(node) cont = node.parentNode index = cont.childNodes.index(node) self.setStart(cont,index) def surroundContents(self,newParent): """Surround the range with this node""" if self.detached: raise InvalidStateErr() if newParent.nodeType in [Node.ATTRIBUTE_NODE, Node.ENTITY_NODE, Node.DOCUMENT_TYPE_NODE, Node.NOTATION_NODE, Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE]: raise InvalidNodeTypeErr() #See is we have element nodes that are partially selected if self.startContainer.nodeType not in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: if self.commonAncestorContainer not in [self.startContainer,self.startContainer.parentNode]: #This is partially selected because our parent is not the common ancestor raise BadBoundaryPointsErr() if self.endContainer.nodeType not in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: if self.commonAncestorContainer not in [self.endContainer,self.endContainer.parentNode]: #This is partially selected because our parent is not the common ancestor raise BadBoundaryPointsErr() #All good, do the insert #Remove children from newPArent for c in newParent.childNodes: newParent.removeChild(c) df = self.extractContents() self.insertNode(newParent) newParent.appendChild(df) self.selectNode(newParent) def toString(self): if self.detached: raise InvalidStateErr() df = self.cloneContents() res = self.__recurseToString(df) from xml.dom.ext import ReleaseNode ReleaseNode(df) return res #Internal Functions# def __validateBoundary(self,node,offset): """Make sure the node is a legal boundary""" if not hasattr(node,'nodeType'): raise InvalidNodeTypeErr() #Check for proper node type curNode = node while curNode: if curNode.nodeType in [Node.ENTITY_NODE, Node.NOTATION_NODE, Node.DOCUMENT_TYPE_NODE, ]: raise InvalidNodeTypeErr() curNode = curNode.parentNode #Check number of cild units if offset < 0: raise IndexSizeErr() if node.nodeType in [Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE]: #Child units are characters if offset > len(node.data): raise IndexSizeErr() else: if offset > len(node.childNodes): raise IndexSizeErr() def __validateRefNode(self,node): if not hasattr(node,'nodeType'): raise InvalidNodeTypeErr() cur = node while cur.parentNode: cur = cur.parentNode if cur.nodeType not in [Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE, ]: raise InvalidNodeTypeErr() if node.nodeType in [Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE, Node.ATTRIBUTE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE, ]: raise InvalidNodeTypeErr() def __comparePositions(self,aContainer,aOffset,bContainer,bOffset): """Compare Boundary Positions Section 2.5""" if aContainer == bContainer: #CASE 1 if aOffset == bOffset: return self.POSITION_EQUAL elif aOffset < bOffset: return self.POSITION_LESS_THAN else: return self.POSITION_GREATER_THAN #CASE 2 bAncestors = [] cur = bContainer while cur: bAncestors.append(cur) cur = cur.parentNode for ctr in range(len(aContainer.childNodes)): c = aContainer.childNodes[ctr] if c in bAncestors: if aOffset <= ctr: return self.POSITION_LESS_THAN else: return self.POSITION_GREATER_THAN #CASE 3 aAncestors = [] cur = aContainer while cur: aAncestors.append(cur) cur = cur.parentNode for ctr in range(len(bContainer.childNodes)): c = bContainer.childNodes[ctr] if c in aAncestors: if ctr < bOffset: return self.POSITION_LESS_THAN else: return self.POSITION_GREATER_THAN #CASE 4 #Check the "Following axis" of A. #If B is in the axis, then A is before B curr = aContainer while curr != aContainer.ownerDocument: sibling = curr.nextSibling while sibling: if curr == bContainer: return self.POSITION_LESS_THAN rt = self.__checkDescendants(sibling,bContainer) if rt: return self.POSITION_LESS_THAN sibling = sibling.nextSibling curr = ((curr.nodeType == Node.ATTRIBUTE_NODE) and curr.ownerElement or curr.parentNode) #Not in the following, return POSITION_LESS_THAN return self.POSITION_GREATER_THAN def __checkDescendants(self,sib,b): for c in sib.childNodes: if c == b: return 1 if self.__checkDescendants(c,b): return 1 return 0 def __calculateCommonAncestor(self): if self.startContainer == self.endContainer: self.__dict__['commonAncestorContainer'] = self.startContainer startAncestors = [] cur = self.startContainer while cur: startAncestors.append(cur) cur = cur.parentNode cur = self.endContainer while cur: if cur in startAncestors: self.__dict__['commonAncestorContainer'] = cur return cur = cur.parentNode #Hmm no ancestor raise BadBoundaryPointsErr() def __recurseToString(self,node): if node.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]: return node.data else: res = "" for c in node.childNodes: res = res + self.__recurseToString(c) return res PyXML-0.8.2/xml/dom/TODO0100644000076400001440000000032507244607163013770 0ustar martinusers-- Consider xml:include -- Consider xml:base -- Consider xml:lang -- Fix Attr defaultValue and specified -- More optimization? -- Complete document on 4TH interpretations of the DOM -- Convert string to DOMString PyXML-0.8.2/xml/dom/Text.py0100644000076400001440000000235407253474633014606 0ustar martinusers######################################################################## # # File Name: Text.py # # Documentation: http://docs.4suite.com/4DOM/Text.py.html # """ WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from CharacterData import CharacterData from xml.dom import Node from xml.dom import IndexSizeErr class Text(CharacterData): nodeType = Node.TEXT_NODE def __init__(self, ownerDocument, data): CharacterData.__init__(self, ownerDocument, data) self.__dict__['__nodeName'] = '#text' ### Methods ### def splitText(self, offset): if not (0 < offset < self.length): raise IndexSizeErr() data = self.data first = data[:int(offset)] second = data[int(offset):] node = self.ownerDocument.createTextNode(second) self._set_data(first) parent = self.parentNode if parent: sibling = self.nextSibling if sibling: parent.insertBefore(node, self.nextSibling) else: parent.appendChild(node) return node PyXML-0.8.2/xml/dom/TreeWalker.py0100644000076400001440000001563207550506777015737 0ustar martinusers######################################################################## # # File Name: TreeWalker.py # # Documentation: http://docs.4suite.com/4DOM/TreeWalker.py.html # """ Tree Walker from DOM Level 2. Allows multi-directional iteration over nodes. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from NodeFilter import NodeFilter from xml.dom import NoModificationAllowedErr from xml.dom import NotSupportedErr class TreeWalker: def __init__(self, root, whatToShow, filter, expandEntityReferences): self.__dict__['__root'] = root self.__dict__['__whatToShow'] = whatToShow self.__dict__['__filter'] = filter self.__dict__['__expandEntityReferences'] = expandEntityReferences self.__dict__['__currentNode'] = root ### Attribute Access Methods -- xxx.attr ### def __getattr__(self, name): attrFunc = self._readComputedAttrs.get(name) if attrFunc: return attrFunc(self) def __setattr__(self, name, value): #Make sure attribute is not read-only if name in self.__class__._readOnlyAttrs: raise NoModificationAllowedErr() #If it's computed execute that function attrFunc = self.__class__._writeComputedAttrs.get(name) if attrFunc: attrFunc(self, value) #Otherwise, just set the attribute else: self.__dict__[name] = value ### Attribute Methods -- xxx._get_attr() ### def _get_root(self): return self.__dict__['__root'] def _get_filter(self): return self.__dict__['__filter'] def _get_whatToShow(self): return self.__dict__['__whatToShow'] def _get_expandEntityReferences(self): return self.__dict__['__expandEntityReferences'] def _get_currentNode(self): return self.__dict__['__currentNode'] def _set_currentNode(self, value): if value == None: raise NotSupportedErr() self.__dict__['__currentNode'] = value ### Methods ### def parentNode(self): next_node = None if self.__dict__['__currentNode'] != self.__dict__['__root']: next_node = self.__dict__['__currentNode']._get_parentNode() while next_node and next_node != self.__dict__['__root'] \ and not (self.__checkWhatToShow(next_node) \ and self.__checkFilter(next_node) == NodeFilter.FILTER_ACCEPT): next_node = next_node._get_parentNode() if next_node: self.__dict__['__currentNode'] = next_node return next_node def firstChild(self): next_node = None if self.__checkFilter(self.__dict__['__currentNode']) != NodeFilter.FILTER_REJECT: next_node = self.__dict__['__currentNode']._get_firstChild() while next_node and not (self.__checkWhatToShow(next_node) \ and self.__checkFilter(next_node) == NodeFilter.FILTER_ACCEPT): next_node = next_node._get_nextSibling() if next_node: self.__dict__['__currentNode'] = next_node return next_node def lastChild(self): next_node = None if self.__checkFilter(self.__dict__['__currentNode']) != NodeFilter.FILTER_REJECT: next_node = self.__dict__['__currentNode']._get_lastChild() while next_node and not (self.__checkWhatToShow(next_node) \ and self.__checkFilter(next_node) == NodeFilter.FILTER_ACCEPT): next_node = next_node._get_previousSibling() if next_node: self.__dict__['__currentNode'] = next_node return next_node def previousSibling(self): prev_node = None if self.__dict__['__currentNode'] != self.__root: prev_node = self.__dict__['__currentNode']._get_previousSibling() while prev_node and not (self.__checkWhatToShow(prev_node) \ and self.__checkFilter(prev_node) == NodeFilter.FILTER_ACCEPT): prev_node = prev_node._get_previousSibling() if prev_node: self.__dict__['__currentNode'] = prev_node return prev_node def nextSibling(self): next_node = None if self.__dict__['__currentNode'] != self.__root: next_node = self.__dict__['__currentNode']._get_nextSibling() while next_node and not (self.__checkWhatToShow(next_node) and self.__checkFilter(next_node) == NodeFilter.FILTER_ACCEPT): next_node = next_node._get_nextSibling() if next_node: self.__dict__['__currentNode'] = next_node return next_node def nextNode(self): next_node = self.__advance() while next_node and not (self.__checkWhatToShow(next_node) and self.__checkFilter(next_node) == NodeFilter.FILTER_ACCEPT): next_node = self.__advance() return next_node def previousNode(self): prev_node = self.__regress() while prev_node and not (self.__checkWhatToShow(prev_node) and self.__checkFilter(prev_node) == NodeFilter.FILTER_ACCEPT): prev_node = self.__regress() return prev_node def __advance(self): if self.firstChild(): return self.__dict__['__currentNode'] if self.nextSibling(): return self.__dict__['__currentNode'] while self.parentNode(): tmpnode = self.nextSibling() if tmpnode: return tmpnode return None def __regress(self): if self.previousSibling(): while self.lastChild(): pass return self.__dict__['__currentNode'] if self.parentNode(): return self.__dict__['__currentNode'] return None def __checkWhatToShow(self, node): show_bit = 1 << (node._get_nodeType() - 1) return self.__dict__['__whatToShow'] & show_bit def __checkFilter(self, node): if self.__dict__['__filter']: return self.__dict__['__filter'].acceptNode(node) else: return NodeFilter.FILTER_ACCEPT def __iter__(self): return self def next(self): node = self.nextNode() if node is None: raise StopIteration return node ### Attribute Access Mappings ### _readComputedAttrs = {'root':_get_root, 'whatToShow':_get_whatToShow, 'filter':_get_filter, 'expandEntityReferences':_get_expandEntityReferences, 'currentNode':_get_currentNode } _writeComputedAttrs = {'currentNode': _set_currentNode } # Create the read-only list of attributes _readOnlyAttrs = filter(lambda k,m=_writeComputedAttrs: not m.has_key(k), _readComputedAttrs.keys()) PyXML-0.8.2/xml/dom/__init__.py0100644000076400001440000001667607517567472015444 0ustar martinusers######################################################################## # # File Name: __init__.py # # Documentation: http://docs.4suite.com/4DOM/__init__.py.html # """ WWW: http://4suite.org/4DOM e-mail: support@4suite.org Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ class Node: """Class giving the nodeType and tree-position constants.""" # DOM implementations may use this as a base class for their own # Node implementations. If they don't, the constants defined here # should still be used as the canonical definitions as they match # the values given in the W3C recommendation. Client code can # safely refer to these values in all tests of Node.nodeType # values. ELEMENT_NODE = 1 ATTRIBUTE_NODE = 2 TEXT_NODE = 3 CDATA_SECTION_NODE = 4 ENTITY_REFERENCE_NODE = 5 ENTITY_NODE = 6 PROCESSING_INSTRUCTION_NODE = 7 COMMENT_NODE = 8 DOCUMENT_NODE = 9 DOCUMENT_TYPE_NODE = 10 DOCUMENT_FRAGMENT_NODE = 11 NOTATION_NODE = 12 # Based on DOM Level 3 (WD 9 April 2025) TREE_POSITION_PRECEDING = 0x01 TREE_POSITION_FOLLOWING = 0x02 TREE_POSITION_ANCESTOR = 0x04 TREE_POSITION_DESCENDENT = 0x08 TREE_POSITION_EQUIVALENT = 0x10 TREE_POSITION_SAME_NODE = 0x20 TREE_POSITION_DISCONNECTED = 0x00 class UserDataHandler: """Class giving the operation constants for UserDataHandler.handle().""" # Based on DOM Level 3 (WD 9 April 2025) NODE_CLONED = 1 NODE_IMPORTED = 2 NODE_DELETED = 3 NODE_RENAMED = 4 class DOMError: """Class giving constants for error severity.""" # Based on DOM Level 3 (WD 9 April 2025) SEVERITY_WARNING = 0 SEVERITY_ERROR = 1 SEVERITY_FATAL_ERROR = 2 # DOMException codes INDEX_SIZE_ERR = 1 DOMSTRING_SIZE_ERR = 2 HIERARCHY_REQUEST_ERR = 3 WRONG_DOCUMENT_ERR = 4 INVALID_CHARACTER_ERR = 5 NO_DATA_ALLOWED_ERR = 6 NO_MODIFICATION_ALLOWED_ERR = 7 NOT_FOUND_ERR = 8 NOT_SUPPORTED_ERR = 9 INUSE_ATTRIBUTE_ERR = 10 # DOM Level 2 INVALID_STATE_ERR = 11 SYNTAX_ERR = 12 INVALID_MODIFICATION_ERR = 13 NAMESPACE_ERR = 14 INVALID_ACCESS_ERR = 15 # DOM Level 3 VALIDATION_ERR = 16 # EventException codes UNSPECIFIED_EVENT_TYPE_ERR = 0 # Fourthought specific codes FT_EXCEPTION_BASE = 1000 XML_PARSE_ERR = FT_EXCEPTION_BASE + 1 #RangeException codes BAD_BOUNDARYPOINTS_ERR = 1 INVALID_NODE_TYPE_ERR = 2 class DOMException(Exception): def __init__(self, code, msg=''): self.code = code self.msg = msg or DOMExceptionStrings[code] def __str__(self): return self.msg class EventException(Exception): def __init__(self, code, msg=''): self.code = code self.msg = msg or EventExceptionStrings[code] return def __str__(self): return self.msg class RangeException(Exception): def __init__(self, code, msg): self.code = code self.msg = msg or RangeExceptionStrings[code] Exception.__init__(self, self.msg) class FtException(Exception): def __init__(self, code, *args): self.code = code self.msg = FtExceptionStrings[code] % args return def __str__(self): return self.msg class IndexSizeErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, INDEX_SIZE_ERR, msg) class DomstringSizeErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, DOMSTRING_SIZE_ERR, msg) # DOMStringSizeErr was accidentally introduced in rev 1.14 of this # file, and was released as part of PyXML 0.6.4, 0.6.5, 0.6.6, 0.7, # and 0.7.1. It has never been part of the Python DOM API, although # it better matches the W3C recommendation. It should remain for # compatibility, unfortunately. # DOMStringSizeErr = DomstringSizeErr class HierarchyRequestErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, HIERARCHY_REQUEST_ERR, msg) class WrongDocumentErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, WRONG_DOCUMENT_ERR, msg) class InvalidCharacterErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, INVALID_CHARACTER_ERR, msg) class NoDataAllowedErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, NO_DATA_ALLOWED_ERR, msg) class NoModificationAllowedErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, NO_MODIFICATION_ALLOWED_ERR, msg) class NotFoundErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, NOT_FOUND_ERR, msg) class NotSupportedErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, NOT_SUPPORTED_ERR, msg) class InuseAttributeErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, INUSE_ATTRIBUTE_ERR, msg) class InvalidStateErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, INVALID_STATE_ERR, msg) class SyntaxErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, SYNTAX_ERR, msg) class InvalidModificationErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, INVALID_MODIFICATION_ERR, msg) class NamespaceErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, NAMESPACE_ERR, msg) class InvalidAccessErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, INVALID_ACCESS_ERR, msg) class ValidationErr(DOMException): def __init__(self, msg=''): DOMException.__init__(self, VALIDATION_ERR, msg) class UnspecifiedEventTypeErr(EventException): def __init__(self, msg=''): EventException.__init__(self, UNSPECIFIED_EVENT_TYPE_ERR, msg) class XmlParseErr(FtException): def __init__(self, msg=''): FtException.__init__(self, XML_PARSE_ERR, msg) #Specific Range Exceptions class BadBoundaryPointsErr(RangeException): def __init__(self, msg=''): RangeException.__init__(self, BAD_BOUNDARYPOINTS_ERR, msg) class InvalidNodeTypeErr(RangeException): def __init__(self, msg=''): RangeException.__init__(self, INVALID_NODE_TYPE_ERR, msg) from xml.dom import DOMImplementation try: from xml.dom.html import HTMLDOMImplementation implementation = HTMLDOMImplementation.HTMLDOMImplementation() HTMLDOMImplementation.implementation = implementation except ImportError: implementation = DOMImplementation.DOMImplementation() DOMImplementation.implementation = implementation XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace" XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/" XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml" EMPTY_NAMESPACE = None EMPTY_PREFIX = None import MessageSource DOMExceptionStrings = MessageSource.__dict__['DOMExceptionStrings'] EventExceptionStrings = MessageSource.__dict__['EventExceptionStrings'] FtExceptionStrings = MessageSource.__dict__['FtExceptionStrings'] RangeExceptionStrings = MessageSource.__dict__['RangeExceptionStrings'] from domreg import getDOMImplementation,registerDOMImplementation PyXML-0.8.2/xml/dom/de.po0100644000076400001440000000562107244340623014227 0ustar martinusers# 4Suite Dom German message catalog. # Copyright (C) 2001 Fourthought, Inc. # Martin v. Lwis , 2001. # msgid "" msgstr "" "Project-Id-Version: Dom\n" "PO-Revision-Date: 2025-01-31 08:09+01:00\n" "Last-Translator: Martin v. Lwis \n" "Language-Team: German \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8-bit\n" "Generated-By: pygettext.py 1.1\n" #: Dom/MessageSource.py:33 msgid "Attempt to modify a read-only object" msgstr "nderung eines unvernderbaren Objekts versucht." #: Dom/MessageSource.py:29 msgid "Node manipulation results in invalid parent/child relationship." msgstr "Knotennderung resultiert in ungltiger Eltern-Kind-Beziehung." #: Dom/MessageSource.py:49 msgid "XML parse error at line %d, column %d: %s" msgstr "XML-Parser-Fehler in Zeile %d, Spalte %d: %s" #: Dom/MessageSource.py:32 msgid "Node does not support data" msgstr "Knoten untersttzt keine Daten." #: Dom/MessageSource.py:28 msgid "DOMString exceeds maximum size" msgstr "Der DOMString ist grer als maximal erlaubt." #: Dom/MessageSource.py:41 msgid "Object does not support this operation or parameter" msgstr "Das Objekt untersttzt diese Operation oder diesen Parameter nicht." #: Dom/MessageSource.py:45 msgid "Uninitialized type in Event object" msgstr "Nicht-initialisierter Typ in Event-Objekt." #: Dom/MessageSource.py:35 msgid "Object or operation not supported" msgstr "Das Objekt oder die Operation ist nicht untersttzt." #: Dom/MessageSource.py:31 msgid "Invalid or illegal character" msgstr "Ungltiges oder unerlaubtes Zeichen." #: Dom/MessageSource.py:30 msgid "Node is from a different document" msgstr "Der Knoten stammt aus einem anderen Dokument." #: Dom/MessageSource.py:36 msgid "Attribute already in use by an element" msgstr "Das Attribut wird bereits von einem Element verwendet." #: Dom/MessageSource.py:54 msgid "Invalid Container Node" msgstr "Ungltiger Container-Knoten." #: Dom/MessageSource.py:37 msgid "Object is not, or is no longer, usable" msgstr "Das Objekt ist nicht oder nicht mehr nutzbar." #: Dom/MessageSource.py:40 msgid "Invalid or illegal namespace operation" msgstr "Ungltige oder unerlaubte Namespace-Operation." #: Dom/MessageSource.py:38 msgid "Specified string is invalid or illegal" msgstr "Der angegebene String ist ungltig oder nicht erlaubt." #: Dom/MessageSource.py:27 msgid "Index error accessing NodeList or NamedNodeMap" msgstr "Indexfehler bei Zugriff auf NodeList- oder NamedNodeMap-Objekt." #: Dom/MessageSource.py:39 msgid "Attempt to modify the type of a node" msgstr "Typnderung eines Knotens versucht." #: Dom/MessageSource.py:53 msgid "Invalid Boundary Points specified for Range" msgstr "Ungltige Endpunkte fr Range angegeben." #: Dom/MessageSource.py:34 msgid "Node does not exist in this context" msgstr "Knoten existiert in diesem Kontext nicht." PyXML-0.8.2/xml/dom/domreg.py0100644000076400001440000000663107611541423015127 0ustar martinusers"""Registration facilities for DOM. This module should not be used directly. Instead, the functions getDOMImplementation and registerDOMImplementation should be imported from xml.dom.""" from xml.dom.minicompat import * # isinstance, StringTypes # This is a list of well-known implementations. Well-known names # should be published by posting to xml-sig@python.org, and are # subsequently recorded in this file. well_known_implementations = { 'minidom':'xml.dom.minidom', '4DOM': 'xml.dom.DOMImplementation', } # DOM implementations not officially registered should register # themselves with their registered = {} def registerDOMImplementation(name, factory): """registerDOMImplementation(name, factory) Register the factory function with the name. The factory function should return an object which implements the DOMImplementation interface. The factory function can either return the same object, or a new one (e.g. if that implementation supports some customization).""" registered[name] = factory def _good_enough(dom, features): "_good_enough(dom, features) -> Return 1 if the dom offers the features" for f,v in features: if not dom.hasFeature(f,v): return 0 return 1 def getDOMImplementation(name = None, features = ()): """getDOMImplementation(name = None, features = ()) -> DOM implementation. Return a suitable DOM implementation. The name is either well-known, the module name of a DOM implementation, or None. If it is not None, imports the corresponding module and returns DOMImplementation object if the import succeeds. If name is not given, consider the available implementations to find one with the required feature set. If no implementation can be found, raise an ImportError. The features list must be a sequence of (feature, version) pairs which are passed to hasFeature.""" import os creator = None mod = well_known_implementations.get(name) if mod: mod = __import__(mod, {}, {}, ['getDOMImplementation']) return mod.getDOMImplementation() elif name: return registered[name]() elif os.environ.has_key("PYTHON_DOM"): return getDOMImplementation(name = os.environ["PYTHON_DOM"]) # User did not specify a name, try implementations in arbitrary # order, returning the one that has the required features if isinstance(features, StringTypes): features = _parse_feature_string(features) for creator in registered.values(): dom = creator() if _good_enough(dom, features): return dom for creator in well_known_implementations.keys(): try: dom = getDOMImplementation(name = creator) except StandardError: # typically ImportError, or AttributeError continue if _good_enough(dom, features): return dom raise ImportError,"no suitable DOM implementation found" def _parse_feature_string(s): features = [] parts = s.split() i = 0 length = len(parts) while i < length: feature = parts[i] if feature[0] in "0123456789": raise ValueError, "bad feature name: " + `feature` i = i + 1 version = None if i < length: v = parts[i] if v[0] in "0123456789": i = i + 1 version = v features.append((feature, version)) return tuple(features) PyXML-0.8.2/xml/dom/en_US.po0100644000076400001440000000377007244340623014653 0ustar martinusers# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: Sun Feb 18 17:52:04 2001\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" "Generated-By: pygettext.py 1.1\n" #: Dom/MessageSource.py:33 msgid "Attempt to modify a read-only object" msgstr "" #: Dom/MessageSource.py:29 msgid "Node manipulation results in invalid parent/child relationship." msgstr "" #: Dom/MessageSource.py:49 msgid "XML parse error at line %d, column %d: %s" msgstr "" #: Dom/MessageSource.py:32 msgid "Node does not support data" msgstr "" #: Dom/MessageSource.py:28 msgid "DOMString exceeds maximum size" msgstr "" #: Dom/MessageSource.py:41 msgid "Object does not support this operation or parameter" msgstr "" #: Dom/MessageSource.py:45 msgid "Uninitialized type in Event object" msgstr "" #: Dom/MessageSource.py:35 msgid "Object or operation not supported" msgstr "" #: Dom/MessageSource.py:31 msgid "Invalid or illegal character" msgstr "" #: Dom/MessageSource.py:30 msgid "Node is from a different document" msgstr "" #: Dom/MessageSource.py:36 msgid "Attribute already in use by an element" msgstr "" #: Dom/MessageSource.py:54 msgid "Invalid Container Node" msgstr "" #: Dom/MessageSource.py:37 msgid "Object is not, or is no longer, usable" msgstr "" #: Dom/MessageSource.py:40 msgid "Invalid or illegal namespace operation" msgstr "" #: Dom/MessageSource.py:38 msgid "Specified string is invalid or illegal" msgstr "" #: Dom/MessageSource.py:27 msgid "Index error accessing NodeList or NamedNodeMap" msgstr "" #: Dom/MessageSource.py:39 msgid "Attempt to modify the type of a node" msgstr "" #: Dom/MessageSource.py:53 msgid "Invalid Boundary Points specified for Range" msgstr "" #: Dom/MessageSource.py:34 msgid "Node does not exist in this context" msgstr "" PyXML-0.8.2/xml/dom/expatbuilder.py0100644000076400001440000010702607614720571016350 0ustar martinusers"""Facility to use the Expat parser to load a minidom instance from a string or file. This avoids all the overhead of SAX and pulldom to gain performance. """ # Warning! # # This module is tightly bound to the implementation details of the # minidom DOM and can't be used with other DOM implementations. This # is due, in part, to a lack of appropriate methods in the DOM (there is # no way to create Entity and Notation nodes via the DOM Level 2 # interface), and for performance. The later is the cause of some fairly # cryptic code. # # Performance hacks: # # - .character_data_handler() has an extra case in which continuing # data is appended to an existing Text node; this can be a # speedup since pyexpat can break up character data into multiple # callbacks even though we set the buffer_text attribute on the # parser. This also gives us the advantage that we don't need a # separate normalization pass. # # - Determining that a node exists is done using an identity comparison # with None rather than a truth test; this avoids searching for and # calling any methods on the node object if it exists. (A rather # nice speedup is achieved this way as well!) from xml.dom import xmlbuilder, minidom, Node from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE from xml.parsers import expat from xml.dom.minidom import _append_child, _set_attribute_node from xml.dom.NodeFilter import NodeFilter from xml.dom.minicompat import * TEXT_NODE = Node.TEXT_NODE CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE DOCUMENT_NODE = Node.DOCUMENT_NODE FILTER_ACCEPT = xmlbuilder.DOMBuilderFilter.FILTER_ACCEPT FILTER_REJECT = xmlbuilder.DOMBuilderFilter.FILTER_REJECT FILTER_SKIP = xmlbuilder.DOMBuilderFilter.FILTER_SKIP FILTER_INTERRUPT = xmlbuilder.DOMBuilderFilter.FILTER_INTERRUPT theDOMImplementation = minidom.getDOMImplementation() # Expat typename -> TypeInfo _typeinfo_map = { "CDATA": minidom.TypeInfo(None, "cdata"), "ENUM": minidom.TypeInfo(None, "enumeration"), "ENTITY": minidom.TypeInfo(None, "entity"), "ENTITIES": minidom.TypeInfo(None, "entities"), "ID": minidom.TypeInfo(None, "id"), "IDREF": minidom.TypeInfo(None, "idref"), "IDREFS": minidom.TypeInfo(None, "idrefs"), "NMTOKEN": minidom.TypeInfo(None, "nmtoken"), "NMTOKENS": minidom.TypeInfo(None, "nmtokens"), } class ElementInfo(NewStyle): __slots__ = '_attr_info', '_model', 'tagName' def __init__(self, tagName, model=None): self.tagName = tagName self._attr_info = [] self._model = model def __getstate__(self): return self._attr_info, self._model, self.tagName def __setstate__(self, state): self._attr_info, self._model, self.tagName = state def getAttributeType(self, aname): for info in self._attr_info: if info[1] == aname: t = info[-2] if t[0] == "(": return _typeinfo_map["ENUM"] else: return _typeinfo_map[info[-2]] return minidom._no_type def getAttributeTypeNS(self, namespaceURI, localName): return minidom._no_type def isElementContent(self): if self._model: type = self._model[0] return type not in (expat.model.XML_CTYPE_ANY, expat.model.XML_CTYPE_MIXED) else: return False def isEmpty(self): if self._model: return self._model[0] == expat.model.XML_CTYPE_EMPTY else: return False def isId(self, aname): for info in self._attr_info: if info[1] == aname: return info[-2] == "ID" return False def isIdNS(self, euri, ename, auri, aname): # not sure this is meaningful return self.isId((auri, aname)) def _intern(builder, s): return builder._intern_setdefault(s, s) def _parse_ns_name(builder, name): assert ' ' in name parts = name.split(' ') intern = builder._intern_setdefault if len(parts) == 3: uri, localname, prefix = parts prefix = intern(prefix, prefix) qname = "%s:%s" % (prefix, localname) qname = intern(qname, qname) localname = intern(localname, localname) else: uri, localname = parts prefix = EMPTY_PREFIX qname = localname = intern(localname, localname) return intern(uri, uri), localname, prefix, qname class ExpatBuilder: """Document builder that uses Expat to build a ParsedXML.DOM document instance.""" def __init__(self, options=None): if options is None: options = xmlbuilder.Options() self._options = options if self._options.filter is not None: self._filter = FilterVisibilityController(self._options.filter) else: self._filter = None # This *really* doesn't do anything in this case, so # override it with something fast & minimal. self._finish_start_element = id self._parser = None self.reset() def createParser(self): """Create a new parser object.""" return expat.ParserCreate() def getParser(self): """Return the parser object, creating a new one if needed.""" if not self._parser: self._parser = self.createParser() self._intern_setdefault = self._parser.intern.setdefault self._parser.buffer_text = True self._parser.ordered_attributes = True self._parser.specified_attributes = True self.install(self._parser) return self._parser def reset(self): """Free all data structures used during DOM construction.""" self.document = theDOMImplementation.createDocument( EMPTY_NAMESPACE, None, None) self.curNode = self.document self._elem_info = self.document._elem_info self._cdata = False def install(self, parser): """Install the callbacks needed to build the DOM into the parser.""" # This creates circular references! parser.StartDoctypeDeclHandler = self.start_doctype_decl_handler parser.StartElementHandler = self.first_element_handler parser.EndElementHandler = self.end_element_handler parser.ProcessingInstructionHandler = self.pi_handler if self._options.entities: parser.EntityDeclHandler = self.entity_decl_handler parser.NotationDeclHandler = self.notation_decl_handler if self._options.comments: parser.CommentHandler = self.comment_handler if self._options.cdata_sections: parser.StartCdataSectionHandler = self.start_cdata_section_handler parser.EndCdataSectionHandler = self.end_cdata_section_handler parser.CharacterDataHandler = self.character_data_handler_cdata else: parser.CharacterDataHandler = self.character_data_handler parser.ExternalEntityRefHandler = self.external_entity_ref_handler parser.XmlDeclHandler = self.xml_decl_handler parser.ElementDeclHandler = self.element_decl_handler parser.AttlistDeclHandler = self.attlist_decl_handler def parseFile(self, file): """Parse a document from a file object, returning the document node.""" parser = self.getParser() first_buffer = True try: while 1: buffer = file.read(16*1024) if not buffer: break parser.Parse(buffer, 0) if first_buffer and self.document.documentElement: self._setup_subset(buffer) first_buffer = False parser.Parse("", True) except ParseEscape: pass doc = self.document self.reset() self._parser = None return doc def parseString(self, string): """Parse a document from a string, returning the document node.""" parser = self.getParser() try: parser.Parse(string, True) self._setup_subset(string) except ParseEscape: pass doc = self.document self.reset() self._parser = None return doc def _setup_subset(self, buffer): """Load the internal subset if there might be one.""" if self.document.doctype: extractor = InternalSubsetExtractor() extractor.parseString(buffer) subset = extractor.getSubset() self.document.doctype.internalSubset = subset def start_doctype_decl_handler(self, doctypeName, systemId, publicId, has_internal_subset): doctype = self.document.implementation.createDocumentType( doctypeName, publicId, systemId) doctype.ownerDocument = self.document self.document.childNodes.append(doctype) self.document.doctype = doctype if self._filter and self._filter.acceptNode(doctype) == FILTER_REJECT: self.document.doctype = None del self.document.childNodes[-1] doctype = None self._parser.EntityDeclHandler = None self._parser.NotationDeclHandler = None if has_internal_subset: if doctype is not None: doctype.entities._seq = [] doctype.notations._seq = [] self._parser.CommentHandler = None self._parser.ProcessingInstructionHandler = None self._parser.EndDoctypeDeclHandler = self.end_doctype_decl_handler def end_doctype_decl_handler(self): if self._options.comments: self._parser.CommentHandler = self.comment_handler self._parser.ProcessingInstructionHandler = self.pi_handler if not (self._elem_info or self._filter): self._finish_end_element = id def pi_handler(self, target, data): node = self.document.createProcessingInstruction(target, data) _append_child(self.curNode, node) if self._filter and self._filter.acceptNode(node) == FILTER_REJECT: curNode.removeChild(node) def character_data_handler_cdata(self, data): childNodes = self.curNode.childNodes if self._cdata: if ( self._cdata_continue and childNodes[-1].nodeType == CDATA_SECTION_NODE): childNodes[-1].appendData(data) return node = self.document.createCDATASection(data) self._cdata_continue = True elif childNodes and childNodes[-1].nodeType == TEXT_NODE: node = childNodes[-1] value = node.data + data d = node.__dict__ d['data'] = d['nodeValue'] = value return else: node = minidom.Text() d = node.__dict__ d['data'] = d['nodeValue'] = data d['ownerDocument'] = self.document _append_child(self.curNode, node) def character_data_handler(self, data): childNodes = self.curNode.childNodes if childNodes and childNodes[-1].nodeType == TEXT_NODE: node = childNodes[-1] d = node.__dict__ d['data'] = d['nodeValue'] = node.data + data return node = minidom.Text() d = node.__dict__ d['data'] = d['nodeValue'] = node.data + data d['ownerDocument'] = self.document _append_child(self.curNode, node) def entity_decl_handler(self, entityName, is_parameter_entity, value, base, systemId, publicId, notationName): if is_parameter_entity: # we don't care about parameter entities for the DOM return if not self._options.entities: return node = self.document._create_entity(entityName, publicId, systemId, notationName) if value is not None: # internal entity # node *should* be readonly, but we'll cheat child = self.document.createTextNode(value) node.childNodes.append(child) self.document.doctype.entities._seq.append(node) if self._filter and self._filter.acceptNode(node) == FILTER_REJECT: del self.document.doctype.entities._seq[-1] def notation_decl_handler(self, notationName, base, systemId, publicId): node = self.document._create_notation(notationName, publicId, systemId) self.document.doctype.notations._seq.append(node) if self._filter and self._filter.acceptNode(node) == FILTER_ACCEPT: del self.document.doctype.notations._seq[-1] def comment_handler(self, data): node = self.document.createComment(data) _append_child(self.curNode, node) if self._filter and self._filter.acceptNode(node) == FILTER_REJECT: self.curNode.removeChild(node) def start_cdata_section_handler(self): self._cdata = True self._cdata_continue = False def end_cdata_section_handler(self): self._cdata = False self._cdata_continue = False def external_entity_ref_handler(self, context, base, systemId, publicId): return 1 def first_element_handler(self, name, attributes): if self._filter is None and not self._elem_info: self._finish_end_element = id self.getParser().StartElementHandler = self.start_element_handler self.start_element_handler(name, attributes) def start_element_handler(self, name, attributes): node = self.document.createElement(name) _append_child(self.curNode, node) self.curNode = node if attributes: for i in range(0, len(attributes), 2): a = minidom.Attr(attributes[i], EMPTY_NAMESPACE, None, EMPTY_PREFIX) value = attributes[i+1] d = a.childNodes[0].__dict__ d['data'] = d['nodeValue'] = value d = a.__dict__ d['value'] = d['nodeValue'] = value d['ownerDocument'] = self.document _set_attribute_node(node, a) if node is not self.document.documentElement: self._finish_start_element(node) def _finish_start_element(self, node): if self._filter: # To be general, we'd have to call isSameNode(), but this # is sufficient for minidom: if node is self.document.documentElement: return filt = self._filter.startContainer(node) if filt == FILTER_REJECT: # ignore this node & all descendents Rejecter(self) elif filt == FILTER_SKIP: # ignore this node, but make it's children become # children of the parent node Skipper(self) else: return self.curNode = node.parentNode node.parentNode.removeChild(node) node.unlink() # If this ever changes, Namespaces.end_element_handler() needs to # be changed to match. # def end_element_handler(self, name): curNode = self.curNode self.curNode = curNode.parentNode self._finish_end_element(curNode) def _finish_end_element(self, curNode): info = self._elem_info.get(curNode.tagName) if info: self._handle_white_text_nodes(curNode, info) if self._filter: if curNode is self.document.documentElement: return if self._filter.acceptNode(curNode) == FILTER_REJECT: self.curNode.removeChild(curNode) curNode.unlink() def _handle_white_text_nodes(self, node, info): if (self._options.whitespace_in_element_content or not info.isElementContent()): return # We have element type information and should remove ignorable # whitespace; identify for text nodes which contain only # whitespace. L = [] for child in node.childNodes: if child.nodeType == TEXT_NODE and not child.data.strip(): L.append(child) # Remove ignorable whitespace from the tree. for child in L: node.removeChild(child) def element_decl_handler(self, name, model): info = self._elem_info.get(name) if info is None: self._elem_info[name] = ElementInfo(name, model) else: assert info._model is None info._model = model def attlist_decl_handler(self, elem, name, type, default, required): info = self._elem_info.get(elem) if info is None: info = ElementInfo(elem) self._elem_info[elem] = info info._attr_info.append( [None, name, None, None, default, 0, type, required]) def xml_decl_handler(self, version, encoding, standalone): self.document.version = version self.document.encoding = encoding # This is still a little ugly, thanks to the pyexpat API. ;-( if standalone >= 0: if standalone: self.document.standalone = True else: self.document.standalone = False # Don't include FILTER_INTERRUPT, since that's checked separately # where allowed. _ALLOWED_FILTER_RETURNS = (FILTER_ACCEPT, FILTER_REJECT, FILTER_SKIP) class FilterVisibilityController(NewStyle): """Wrapper around a DOMBuilderFilter which implements the checks to make the whatToShow filter attribute work.""" __slots__ = 'filter', def __init__(self, filter): self.filter = filter def startContainer(self, node): mask = self._nodetype_mask[node.nodeType] if self.filter.whatToShow & mask: val = self.filter.startContainer(node) if val == FILTER_INTERRUPT: raise ParseEscape if val not in _ALLOWED_FILTER_RETURNS: raise ValueError, \ "startContainer() returned illegal value: " + repr(val) return val else: return FILTER_ACCEPT def acceptNode(self, node): mask = self._nodetype_mask[node.nodeType] if self.filter.whatToShow & mask: val = self.filter.acceptNode(node) if val == FILTER_INTERRUPT: raise ParseEscape if val == FILTER_SKIP: # move all child nodes to the parent, and remove this node parent = node.parentNode for child in node.childNodes[:]: parent.appendChild(child) # node is handled by the caller return FILTER_REJECT if val not in _ALLOWED_FILTER_RETURNS: raise ValueError, \ "acceptNode() returned illegal value: " + repr(val) return val else: return FILTER_ACCEPT _nodetype_mask = { Node.ELEMENT_NODE: NodeFilter.SHOW_ELEMENT, Node.ATTRIBUTE_NODE: NodeFilter.SHOW_ATTRIBUTE, Node.TEXT_NODE: NodeFilter.SHOW_TEXT, Node.CDATA_SECTION_NODE: NodeFilter.SHOW_CDATA_SECTION, Node.ENTITY_REFERENCE_NODE: NodeFilter.SHOW_ENTITY_REFERENCE, Node.ENTITY_NODE: NodeFilter.SHOW_ENTITY, Node.PROCESSING_INSTRUCTION_NODE: NodeFilter.SHOW_PROCESSING_INSTRUCTION, Node.COMMENT_NODE: NodeFilter.SHOW_COMMENT, Node.DOCUMENT_NODE: NodeFilter.SHOW_DOCUMENT, Node.DOCUMENT_TYPE_NODE: NodeFilter.SHOW_DOCUMENT_TYPE, Node.DOCUMENT_FRAGMENT_NODE: NodeFilter.SHOW_DOCUMENT_FRAGMENT, Node.NOTATION_NODE: NodeFilter.SHOW_NOTATION, } class FilterCrutch(NewStyle): __slots__ = '_builder', '_level', '_old_start', '_old_end' def __init__(self, builder): self._level = 0 self._builder = builder parser = builder._parser self._old_start = parser.StartElementHandler self._old_end = parser.EndElementHandler parser.StartElementHandler = self.start_element_handler parser.EndElementHandler = self.end_element_handler class Rejecter(FilterCrutch): __slots__ = () def __init__(self, builder): FilterCrutch.__init__(self, builder) parser = builder._parser for name in ("ProcessingInstructionHandler", "CommentHandler", "CharacterDataHandler", "StartCdataSectionHandler", "EndCdataSectionHandler", "ExternalEntityRefHandler", ): setattr(parser, name, None) def start_element_handler(self, *args): self._level = self._level + 1 def end_element_handler(self, *args): if self._level == 0: # restore the old handlers parser = self._builder._parser self._builder.install(parser) parser.StartElementHandler = self._old_start parser.EndElementHandler = self._old_end else: self._level = self._level - 1 class Skipper(FilterCrutch): __slots__ = () def start_element_handler(self, *args): node = self._builder.curNode self._old_start(*args) if self._builder.curNode is not node: self._level = self._level + 1 def end_element_handler(self, *args): if self._level == 0: # We're popping back out of the node we're skipping, so we # shouldn't need to do anything but reset the handlers. self._builder._parser.StartElementHandler = self._old_start self._builder._parser.EndElementHandler = self._old_end self._builder = None else: self._level = self._level - 1 self._old_end(*args) # framework document used by the fragment builder. # Takes a string for the doctype, subset string, and namespace attrs string. _FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID = \ "http://xml.python.org/entities/fragment-builder/internal" _FRAGMENT_BUILDER_TEMPLATE = ( '''\ %%s ]> &fragment-builder-internal;''' % _FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID) class FragmentBuilder(ExpatBuilder): """Builder which constructs document fragments given XML source text and a context node. The context node is expected to provide information about the namespace declarations which are in scope at the start of the fragment. """ def __init__(self, context, options=None): if context.nodeType == DOCUMENT_NODE: self.originalDocument = context self.context = context else: self.originalDocument = context.ownerDocument self.context = context ExpatBuilder.__init__(self, options) def reset(self): ExpatBuilder.reset(self) self.fragment = None def parseFile(self, file): """Parse a document fragment from a file object, returning the fragment node.""" return self.parseString(file.read()) def parseString(self, string): """Parse a document fragment from a string, returning the fragment node.""" self._source = string parser = self.getParser() doctype = self.originalDocument.doctype ident = "" if doctype: subset = doctype.internalSubset or self._getDeclarations() if doctype.publicId: ident = ('PUBLIC "%s" "%s"' % (doctype.publicId, doctype.systemId)) elif doctype.systemId: ident = 'SYSTEM "%s"' % doctype.systemId else: subset = "" nsattrs = self._getNSattrs() # get ns decls from node's ancestors document = _FRAGMENT_BUILDER_TEMPLATE % (ident, subset, nsattrs) try: parser.Parse(document, 1) except: self.reset() raise fragment = self.fragment self.reset() ## self._parser = None return fragment def _getDeclarations(self): """Re-create the internal subset from the DocumentType node. This is only needed if we don't already have the internalSubset as a string. """ doctype = self.context.ownerDocument.doctype s = "" if doctype: for i in range(doctype.notations.length): notation = doctype.notations.item(i) if s: s = s + "\n " s = "%s' \ % (s, notation.publicId, notation.systemId) else: s = '%s SYSTEM "%s">' % (s, notation.systemId) for i in range(doctype.entities.length): entity = doctype.entities.item(i) if s: s = s + "\n " s = "%s" return s def _getNSattrs(self): return "" def external_entity_ref_handler(self, context, base, systemId, publicId): if systemId == _FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID: # this entref is the one that we made to put the subtree # in; all of our given input is parsed in here. old_document = self.document old_cur_node = self.curNode parser = self._parser.ExternalEntityParserCreate(context) # put the real document back, parse into the fragment to return self.document = self.originalDocument self.fragment = self.document.createDocumentFragment() self.curNode = self.fragment try: parser.Parse(self._source, 1) finally: self.curNode = old_cur_node self.document = old_document self._source = None return -1 else: return ExpatBuilder.external_entity_ref_handler( self, context, base, systemId, publicId) class Namespaces: """Mix-in class for builders; adds support for namespaces.""" def _initNamespaces(self): # list of (prefix, uri) ns declarations. Namespace attrs are # constructed from this and added to the element's attrs. self._ns_ordered_prefixes = [] def createParser(self): """Create a new namespace-handling parser.""" parser = expat.ParserCreate(namespace_separator=" ") parser.namespace_prefixes = True return parser def install(self, parser): """Insert the namespace-handlers onto the parser.""" ExpatBuilder.install(self, parser) if self._options.namespace_declarations: parser.StartNamespaceDeclHandler = ( self.start_namespace_decl_handler) def start_namespace_decl_handler(self, prefix, uri): """Push this namespace declaration on our storage.""" self._ns_ordered_prefixes.append((prefix, uri)) def start_element_handler(self, name, attributes): if ' ' in name: uri, localname, prefix, qname = _parse_ns_name(self, name) else: uri = EMPTY_NAMESPACE qname = name localname = None prefix = EMPTY_PREFIX node = minidom.Element(qname, uri, prefix, localname) node.ownerDocument = self.document _append_child(self.curNode, node) self.curNode = node if self._ns_ordered_prefixes: for prefix, uri in self._ns_ordered_prefixes: if prefix: a = minidom.Attr(_intern(self, 'xmlns:' + prefix), XMLNS_NAMESPACE, prefix, "xmlns") else: a = minidom.Attr("xmlns", XMLNS_NAMESPACE, "xmlns", EMPTY_PREFIX) d = a.childNodes[0].__dict__ d['data'] = d['nodeValue'] = uri d = a.__dict__ d['value'] = d['nodeValue'] = uri d['ownerDocument'] = self.document _set_attribute_node(node, a) del self._ns_ordered_prefixes[:] if attributes: _attrs = node._attrs _attrsNS = node._attrsNS for i in range(0, len(attributes), 2): aname = attributes[i] value = attributes[i+1] if ' ' in aname: uri, localname, prefix, qname = _parse_ns_name(self, aname) a = minidom.Attr(qname, uri, localname, prefix) _attrs[qname] = a _attrsNS[(uri, localname)] = a else: a = minidom.Attr(aname, EMPTY_NAMESPACE, aname, EMPTY_PREFIX) _attrs[aname] = a _attrsNS[(EMPTY_NAMESPACE, aname)] = a d = a.childNodes[0].__dict__ d['data'] = d['nodeValue'] = value d = a.__dict__ d['ownerDocument'] = self.document d['value'] = d['nodeValue'] = value d['ownerElement'] = node if __debug__: # This only adds some asserts to the original # end_element_handler(), so we only define this when -O is not # used. If changing one, be sure to check the other to see if # it needs to be changed as well. # def end_element_handler(self, name): curNode = self.curNode if ' ' in name: uri, localname, prefix, qname = _parse_ns_name(self, name) assert (curNode.namespaceURI == uri and curNode.localName == localname and curNode.prefix == prefix), \ "element stack messed up! (namespace)" else: assert curNode.nodeName == name, \ "element stack messed up - bad nodeName" assert curNode.namespaceURI == EMPTY_NAMESPACE, \ "element stack messed up - bad namespaceURI" self.curNode = curNode.parentNode self._finish_end_element(curNode) class ExpatBuilderNS(Namespaces, ExpatBuilder): """Document builder that supports namespaces.""" def reset(self): ExpatBuilder.reset(self) self._initNamespaces() class FragmentBuilderNS(Namespaces, FragmentBuilder): """Fragment builder that supports namespaces.""" def reset(self): FragmentBuilder.reset(self) self._initNamespaces() def _getNSattrs(self): """Return string of namespace attributes from this element and ancestors.""" # XXX This needs to be re-written to walk the ancestors of the # context to build up the namespace information from # declarations, elements, and attributes found in context. # Otherwise we have to store a bunch more data on the DOM # (though that *might* be more reliable -- not clear). attrs = "" context = self.context L = [] while context: if hasattr(context, '_ns_prefix_uri'): for prefix, uri in context._ns_prefix_uri.items(): # add every new NS decl from context to L and attrs string if prefix in L: continue L.append(prefix) if prefix: declname = "xmlns:" + prefix else: declname = "xmlns" if attrs: attrs = "%s\n %s='%s'" % (attrs, declname, uri) else: attrs = " %s='%s'" % (declname, uri) context = context.parentNode return attrs class ParseEscape(Exception): """Exception raised to short-circuit parsing in InternalSubsetExtractor.""" pass class InternalSubsetExtractor(ExpatBuilder): """XML processor which can rip out the internal document type subset.""" subset = None def getSubset(self): """Return the internal subset as a string.""" return self.subset def parseFile(self, file): try: ExpatBuilder.parseFile(self, file) except ParseEscape: pass def parseString(self, string): try: ExpatBuilder.parseString(self, string) except ParseEscape: pass def install(self, parser): parser.StartDoctypeDeclHandler = self.start_doctype_decl_handler parser.StartElementHandler = self.start_element_handler def start_doctype_decl_handler(self, name, publicId, systemId, has_internal_subset): if has_internal_subset: parser = self.getParser() self.subset = [] parser.DefaultHandler = self.subset.append parser.EndDoctypeDeclHandler = self.end_doctype_decl_handler else: raise ParseEscape() def end_doctype_decl_handler(self): s = ''.join(self.subset).replace('\r\n', '\n').replace('\r', '\n') self.subset = s raise ParseEscape() def start_element_handler(self, name, attrs): raise ParseEscape() def parse(file, namespaces=1): """Parse a document, returning the resulting Document node. 'file' may be either a file name or an open file object. """ if namespaces: builder = ExpatBuilderNS() else: builder = ExpatBuilder() if isinstance(file, StringTypes): fp = open(file, 'rb') try: result = builder.parseFile(fp) finally: fp.close() else: result = builder.parseFile(file) return result def parseString(string, namespaces=1): """Parse a document from a string, returning the resulting Document node. """ if namespaces: builder = ExpatBuilderNS() else: builder = ExpatBuilder() return builder.parseString(string) def parseFragment(file, context, namespaces=1): """Parse a fragment of a document, given the context from which it was originally extracted. context should be the parent of the node(s) which are in the fragment. 'file' may be either a file name or an open file object. """ if namespaces: builder = FragmentBuilderNS(context) else: builder = FragmentBuilder(context) if isinstance(file, StringTypes): fp = open(file, 'rb') try: result = builder.parseFile(fp) finally: fp.close() else: result = builder.parseFile(file) return result def parseFragmentString(string, context, namespaces=1): """Parse a fragment of a document from a string, given the context from which it was originally extracted. context should be the parent of the node(s) which are in the fragment. """ if namespaces: builder = FragmentBuilderNS(context) else: builder = FragmentBuilder(context) return builder.parseString(string) def makeBuilder(options): """Create a builder based on an Options object.""" if options.namespaces: return ExpatBuilderNS(options) else: return ExpatBuilder(options) PyXML-0.8.2/xml/dom/fr_FR.po0100644000076400001440000000547707244340623014646 0ustar martinusers# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: Tue Jan 30 09:09:32 2001\n" "Last-Translator: Alexandre Fayolle \n" "Language-Team: FRENCH \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" "Generated-By: pygettext.py 1.1\n" #: Dom/MessageSource.py:33 msgid "Attempt to modify a read-only object" msgstr "Tentative de modification d'un objet accessible en lecture seule" #: Dom/MessageSource.py:29 msgid "Node manipulation results in invalid parent/child relationship." msgstr "La manipulation du noeud cause une relation parent/enfant invalide." #: Dom/MessageSource.py:49 msgid "XML parse error at line %d, column %d: %s" msgstr "Erreur XML ligne %d, colonne %d: %s" #: Dom/MessageSource.py:32 msgid "Node does not support data" msgstr "Ce noeud ne peut contenir de donnes" #: Dom/MessageSource.py:28 msgid "" msgstr "La DOMString a dpass la taille maximale" #: Dom/MessageSource.py:41 msgid "Object does not support this operation or parameter" msgstr "L'objet ne supporte pas cette opration ou ce paramtre" #: Dom/MessageSource.py:45 msgid "Uninitialized type in Event object" msgstr "Le chanmp type de l'objet Event n'a pas t initiali" #: Dom/MessageSource.py:35 msgid "Object or operation not supported" msgstr "Objet ou opration non support" #: Dom/MessageSource.py:31 msgid "Invalid or illegal character" msgstr "Charactre invalide ou illgal" #: Dom/MessageSource.py:30 msgid "Node is from a different document" msgstr "Le noeud appartient un autre document" #: Dom/MessageSource.py:36 msgid "Attribute already in use by an element" msgstr "L'attribut est dj utilis par un autre lment" #: Dom/MessageSource.py:54 msgid "Invalid Container Node" msgstr "Noeud conteneur invalide" #: Dom/MessageSource.py:37 msgid "Object is not, or is no longer, usable" msgstr "Cet objet n'est pas ou plus utilisable" #: Dom/MessageSource.py:40 msgid "Invalid or illegal namespace operation" msgstr "Opration sur les domaines nominaux invalide ou illgale" #: Dom/MessageSource.py:38 msgid "Specified string is invalid or illegal" msgstr "La chaine est invalide ou illgale" #: Dom/MessageSource.py:27 msgid "Index error accessing NodeList or NamedNodeMap" msgstr "Erreur d'indexe pour l'accs la NodeList ou la NamedNodeMap" #: Dom/MessageSource.py:39 msgid "Attempt to modify the type of a node" msgstr "Tentative de modification du type d'un noeud" #: Dom/MessageSource.py:53 msgid "Invalid Boundary Points specified for Range" msgstr "Des bornes invalides ont t passes l'intervalles" #: Dom/MessageSource.py:34 msgid "Node does not exist in this context" msgstr "Le noeud n'existe pas dans ce contexte" PyXML-0.8.2/xml/dom/javadom.py0100644000076400001440000004552207244235016015275 0ustar martinusers"""An adapter for Java DOM implementations that makes it possible to access them through the same interface as the Python DOM implementations. Supports: - Sun's Java Project X - Xerces - David Brownell's SAX 2.0 Utilities / DOM2 - Indelv DOM - SXP - OpenXML $Id: javadom.py,v 1.7 2025/02/19 15:21:50 fdrake Exp $ """ # Todo: # - extend test suite # - start using _set_up_attributes, or give up as too slow? # - support level 2 import string # --- Supported Java DOM implementations class BaseDomImplementation: """An abstract DomImplementation with some reusable implementations of build* methods that depend on a lower-level _parse_from_source method.""" def buildDocumentString(self, string): from java.io import StringReader from org.xml.sax import InputSource return self._parse_from_source(InputSource(StringReader(string))) def buildDocumentUrl(self, url): return self._parse_from_source(url) def buildDocumentFile(self, filename): return self.buildDocumentUrl(filetourl(filename)) class SunDomImplementation: def createDocument(self): from com.sun.xml.tree import XmlDocument return Document(XmlDocument()) def buildDocumentString(self, string): from com.sun.xml.tree import XmlDocumentBuilder return Document(XmlDocumentBuilder.createXmlDocument(string)) def buildDocumentUrl(self, url): from com.sun.xml.tree import XmlDocument return Document(XmlDocument.createXmlDocument(url)) def buildDocumentFile(self, filename): return self.buildDocumentUrl(filetourl(filename)) class XercesDomImplementation(BaseDomImplementation): def createDocument(self): from org.apache.xerces.dom import DocumentImpl return Document(DocumentImpl()) def _parse_from_source(self, source): from org.apache.xerces.parsers import DOMParser p = DOMParser() p.parse(source) return Document(p.getDocument()) class BrownellDomImplementation(BaseDomImplementation): def createDocument(self): from org.brownell.xml.dom import DomDocument return Document(DomDocument()) def _parse_from_source(self, source): from org.brownell.xml import DomBuilder return Document(DomBuilder.createDocument(source)) class IndelvDomImplementation(BaseDomImplementation): def createDocument(self): from com.indelv.dom import DOMImpl return Document(DOMImpl.createNewDocument()) def _parse_from_source(self, source): from com.indelv.dom.util import XMLReader from org.xml.sax import InputSource return Document(XMLReader.parseDocument(InputSource(source))) class SxpDomImplementation(BaseDomImplementation): def createDocument(self): from fr.loria.xml import DOMFactory return Document(DOMFactory().createDocument()) def _parse_from_source(self, source): from fr.loria.xml import DocumentLoader loader = DocumentLoader() if type(source) == type(""): doc = loader.loadDocument(source) elif source.getCharacterStream() != None: doc = loader.loadDocument(source.getCharacterStream()) elif source.getByteStream() != None: doc = loader.loadDocument(source.getByteStream()) elif source.getSystemId() != None: doc = loader.loadDocument(source.getSystemId()) return Document(doc) class OpenXmlDomImplementation(BaseDomImplementation): def createDocument(self): from org.openxml.dom import DocumentImpl return Document(DocumentImpl()) def _parse_from_source(self, source): from org.openxml.dom import SAXBuilder from org.openxml.parser import XMLSAXParser builder = SAXBuilder() parser = XMLSAXParser() parser.setDocumentHandler(builder) parser.parse(source) return Document(builder.getDocument()) # ===== Utilities def filetourl(file): # A Python port of James Clark's fileToURL from XMLTest.java. from java.io import File from java.net import URL from java.lang import System file = File(file).getAbsolutePath() sep = System.getProperty("file.separator") if sep != None and len(sep) == 1: file = file.replace(sep[0], '/') if len(file) > 0 and file[0] != '/': file = '/' + file return URL('file', None, file).toString() def _wrap_node(node): if node == None: return None return NODE_CLASS_MAP[node.getNodeType()] (node) # ===== Constants ELEMENT_NODE = 1 ATTRIBUTE_NODE = 2 TEXT_NODE = 3 CDATA_SECTION_NODE = 4 ENTITY_REFERENCE_NODE = 5 ENTITY_NODE = 6 PROCESSING_INSTRUCTION_NODE = 7 COMMENT_NODE = 8 DOCUMENT_NODE = 9 DOCUMENT_TYPE_NODE = 10 DOCUMENT_FRAGMENT_NODE = 11 NOTATION_NODE = 12 # ===== DOMException try: from org.w3c.dom import DOMException except ImportError, e: pass # ===== DOMImplementation class DOMImplementation: def __init__(self, impl): self._impl = impl def hasFeature(self, feature, version): if version == None or version == "1.0": return string.lower(feature) == "xml" and \ self._impl.hasFeature(feature, version) else: return 0 def __repr__(self): return "" % self._impl # ===== Node class Node: def __init__(self, impl): self.__dict__['_impl'] = impl # attributes def _get_nodeName(self): return self._impl.getNodeName() def _get_nodeValue(self): return self._impl.getNodeValue() def _get_nodeType(self): return self._impl.getNodeType() def _get_parentNode(self): return _wrap_node(self._impl.getParentNode()) def _get_childNodes(self): children = self._impl.getChildNodes() if children is None: return children else: return NodeList(children) def _get_firstChild(self): return _wrap_node(self._impl.getFirstChild()) def _get_lastChild(self): return _wrap_node(self._impl.getLastChild()) def _get_previousSibling(self): return _wrap_node(self._impl.getPreviousSibling()) def _get_nextSibling(self): return _wrap_node(self._impl.getNextSibling()) def _get_ownerDocument(self): return _wrap_node(self._impl.getOwnerDocument()) def _get_attributes(self): atts = self._impl.getAttributes() if atts is None: return None else: return NamedNodeMap(atts) # methods def insertBefore(self, new, neighbour): self._impl.insertBefore(new._impl, neighbour._impl) def replaceChild(self, new, old): self._impl.replaceChild(new._impl, old._impl) return old def removeChild(self, old): self._impl.removeChild(old._impl) return old def appendChild(self, new): return self._impl.appendChild(new._impl) def hasChildNodes(self): return self._impl.hasChildNodes() def cloneNode(self): return _wrap_node(self._impl.cloneNode()) # python def __getattr__(self, name): if name[ : 5] != '_get_': return getattr(self, '_get_' + name) () raise AttributeError, name def __setattr__(self, name, value): getattr(self, '_set_' + name) (value) # ===== Document class Document(Node): def __init__(self, impl): Node.__init__(self, impl) # methods def createTextNode(self, data): return Text(self._impl.createTextNode(data)) def createEntityReference(self, name): return EntityReference(self._impl.createEntityReference(name)) def createElement(self, name): return Element(self._impl.createElement(name)) def createDocumentFragment(self): return DocumentFragment(self._impl.createDocumentFragment()) def createComment(self, data): return Comment(self._impl.createComment(data)) def createCDATASection(self, data): return CDATASection(self._impl.createCDATASection(data)) def createProcessingInstruction(self, target, data): return ProcessingInstruction(self._impl.createProcessingInstruction(target, data)) def createAttribute(self, name): return Attr(self._impl.createAttribute(name)) def getElementsByTagName(self, name): return NodeList(self._impl.getElementsByTagName(name)) # attributes def _get_doctype(self): return self._impl.getDoctype() def _get_implementation(self): return DOMImplementation(self._impl.getImplementation()) def _get_documentElement(self): return _wrap_node(self._impl.getDocumentElement()) # python def __repr__(self): docelm = self._impl.getDocumentElement() if docelm: return "" % docelm.getTagName() else: return "" # ===== Element class Element(Node): def __init__(self, impl): Node.__init__(self, impl) self.__dict__['_get_tagName'] = self._impl.getTagName self.__dict__['getAttribute'] = self._impl.getAttribute self.__dict__['setAttribute'] = self._impl.setAttribute self.__dict__['removeAttribute'] = self._impl.removeAttribute self.__dict__['normalize'] = self._impl.normalize # methods def getAttributeNode(self, name): node = self._impl.getAttributeNode(name) if node == None: return node else: return Attr(node) def setAttributeNode(self, attr): self._impl.setAttributeNode(attr._impl) def removeAttributeNode(self, attr): self._impl.removeAttributeNode(attr._impl) def getElementsByTagName(self, name): return NodeList(self._impl.getElementsByTagName(name)) # python def __repr__(self): return "" % \ (self._impl.getTagName(), self._impl.getAttributes().getLength(), self._impl.getChildNodes().getLength()) # ===== CharacterData class CharacterData(Node): def __init__(self, impl): Node.__init__(self, impl) self.__dict__['_get_data'] = self._impl.getData self.__dict__['_set_data'] = self._impl.setData self.__dict__['_get_length'] = self._impl.getLength self.__dict__['substringData'] = self._impl.substringData self.__dict__['appendData'] = self._impl.appendData self.__dict__['insertData'] = self._impl.insertData self.__dict__['deleteData'] = self._impl.deleteData self.__dict__['replaceData'] = self._impl.replaceData # ===== Comment class Comment(CharacterData): def __repr__(self): return "" % self.getLength() # ===== ProcessingInstruction class ProcessingInstruction(Node): def __init__(self, impl): Node.__init__(self, impl) self.__dict__['_get_target'] = self._impl.getTarget self.__dict__['_get_data'] = self._impl.getData self.__dict__['_set_data'] = self._impl.setData def __repr__(self): return "" % self._impl.getTarget() # ===== Text class Text(CharacterData): def splitText(self, offset): return Text(self._impl.splitText(offset)) def __repr__(self): return "" % self._impl.getLength() # ===== CDATASection class CDATASection(Text): def __repr__(self): return "" % self._impl.getLength() # ===== Attr class Attr(Node): def __init__(self, impl): Node.__init__(self, impl) self.__dict__['_get_name'] = self._impl.getName self.__dict__['_get_specified'] = self._impl.getSpecified self.__dict__['_get_value'] = self._impl.getValue self.__dict__['_set_value'] = self._impl.setValue def __repr__(self): return "" % self._impl.getName() # ===== EntityReference class EntityReference(Node): def __repr__(self): return "" % self.getNodeName() # ===== DocumentType class DocumentType(Node): def __init__(self, impl): Node.__init__(self, impl) self.__dict__['_get_name'] = self._impl.getName def _get_entities(self): return NamedNodeMap(self._impl.getEntities()) def _get_notations(self): return NamedNodeMap(self._impl.getNotations()) def __repr__(self): return "" % self._impl.getNodeName() # ===== Notation class Notation(Node): def __init__(self, impl): Node.__init__(self, impl) self.__dict__['_get_publicId'] = self._impl.getPublicId self.__dict__['_get_systemId'] = self._impl.getSystemId def __repr__(self): return "" % self._impl.getNodeName() # ===== Entity class Entity(Node): def __init__(self, impl): Node.__init__(self, impl) self.__dict__['_get_publicId'] = self._impl.getPublicId self.__dict__['_get_systemId'] = self._impl.getSystemId self.__dict__['_get_notationName'] = self._impl.getNotationName def __repr__(self): return "" % self._impl.getNodeName() # ===== DocumentFragment class DocumentFragment(Node): def __repr__(self): return "" # ===== NodeList class NodeList: def __init__(self, impl): self._impl = impl self.__dict__['__len__'] = self._impl.getLength self.__dict__['_get_length'] = self._impl.getLength self.__dict__['item'] = self._impl.item # Python list methods def __getitem__(self, ix): if ix < 0: ix = len(self) + ix node = self._impl.item(ix) if node == None: raise IndexError, ix else: return _wrap_node(node) def __setitem__(self, ix, item): raise TypeError, "NodeList instances don't support item assignment" def __delitem__(self, ix, item): raise TypeError, "NodeList instances don't support item deletion" def __setslice__(self, i, j, list): raise TypeError, "NodeList instances don't support slice assignment" def __delslice__(self, i, j): raise TypeError, "NodeList instances don't support slice deletion" def append(self, item): raise TypeError, "NodeList instances don't support .append()" def insert(self, i, item): raise TypeError, "NodeList instances don't support .insert()" def pop(self, i=-1): raise TypeError, "NodeList instances don't support .pop()" def remove(self, item): raise TypeError, "NodeList instances don't support .remove()" def reverse(self): raise TypeError, "NodeList instances don't support .reverse()" def sort(self, *args): raise TypeError, "NodeList instances don't support .sort()" def __add__(self, *args): raise TypeError, "NodeList instances don't support +" def __radd__(self, *args): raise TypeError, "NodeList instances don't support +" def __mul__(self, *args): raise TypeError, "NodeList instances don't support *" def __rmul__(self, *args): raise TypeError, "NodeList instances don't support *" def count(self, *args): raise TypeError, "NodeList instances can't support count without equality" def count(self, *args): raise TypeError, "NodeList instances can't support index without equality" def __getslice__(self, i, j): if i < len(self): i = len(self) + i if j < len(self): j = len(self) + j slice = [] for ix in range(i, min(j, len(self))): slice.append(self[ix]) return slice def __repr__(self): return "" % string.join(map(repr, self), ", ") # ===== NamedNodeMap class NamedNodeMap: def __init__(self, impl): self._impl = impl self.__dict__['_get_length'] = self._impl.getLength self.__dict__['__len__'] = self._impl.getLength # methods def getNamedItem(self, name): return _wrap_node(self._impl.getNamedItem(name)) def setNamedItem(self, node): return _wrap_node(self._impl.setNamedItem(node._impl)) def removeNamedItem(self, name): return _wrap_node(self._impl.removeNamedItem(name)) def item(self, index): return _wrap_node(self._impl.item(index)) # Python dictionary methods def __getitem__(self, key): node = self._impl.getNamedItem(key) if node is None: raise KeyError, key else: return _wrap_node(node) def get(self, key, alternative = None): node = self._impl.getNamedItem(key) if node is None: return alternative else: return _wrap_node(node) def has_key(self, key): return self._impl.getNamedItem(key) != None def items(self): list = [] for ix in range(self._impl.getLength()): node = self._impl.item(ix) list.append((node.getNodeName(), _wrap_node(node))) return list def keys(self): list = [] for ix in range(self._impl.getLength()): list.append(self._impl.item(ix)._get_nodeName()) return list def values(self): list = [] for ix in range(self._impl.getLength()): list.append(_wrap_node(self._impl.item(ix))) return list def __setitem__(self, key, item): assert key == item._impl._get_nodeName() self._impl.setNamedItem(item._impl) def update(self, nnm): for v in nnm.values(): self._impl.setNamedItem(v._impl) def __repr__(self): pairs = [] for pair in self.items(): pairs.append("'%s' : %s" % pair) return "" % string.join(pairs, ", ") # ===== Various stuff NODE_CLASS_MAP = { ELEMENT_NODE : Element, ATTRIBUTE_NODE : Attr, TEXT_NODE : Text, CDATA_SECTION_NODE : CDATASection, ENTITY_REFERENCE_NODE : EntityReference, ENTITY_NODE : Entity, PROCESSING_INSTRUCTION_NODE : ProcessingInstruction, COMMENT_NODE : Comment, DOCUMENT_NODE : Document, DOCUMENT_TYPE_NODE : DocumentType, DOCUMENT_FRAGMENT_NODE : DocumentFragment, NOTATION_NODE : Notation } # ===== Self-test if __name__ == "__main__": impl = BrownellDomImplementation() #XercesDomImplementation() #SunDomImplementation() doc2 = impl.createDocument() print doc2 print doc2._get_implementation() root = doc2.createElement("doc") print root doc2.appendChild(root) txt = doc2.createTextNode("This is a simple sample \n") print txt root.appendChild(txt) print root._get_childNodes()[0] print root._get_childNodes() root.setAttribute("huba", "haba") print root print root._get_attributes() PyXML-0.8.2/xml/dom/minicompat.py0100644000076400001440000001224707614524250016014 0ustar martinusers"""Python version compatibility support for minidom.""" # This module should only be imported using "import *". # # The following names are defined: # # isinstance -- version of the isinstance() function that accepts # tuples as the second parameter regardless of the # Python version # # NodeList -- lightest possible NodeList implementation # # EmptyNodeList -- lightest possible NodeList that is guarateed to # remain empty (immutable) # # StringTypes -- tuple of defined string types # # GetattrMagic -- base class used to make _get_ be magically # invoked when available # defproperty -- function used in conjunction with GetattrMagic; # using these together is needed to make them work # as efficiently as possible in both Python 2.2+ # and older versions. For example: # # class MyClass(GetattrMagic): # def _get_myattr(self): # return something # # defproperty(MyClass, "myattr", # "return some value") # # For Python 2.2 and newer, this will construct a # property object on the class, which avoids # needing to override __getattr__(). It will only # work for read-only attributes. # # For older versions of Python, inheriting from # GetattrMagic will use the traditional # __getattr__() hackery to achieve the same effect, # but less efficiently. # # defproperty() should be used for each version of # the relevant _get_() function. # # NewStyle -- base class to cause __slots__ to be honored in # the new world # # True, False -- only for Python 2.2 and earlier __all__ = ["NodeList", "EmptyNodeList", "NewStyle", "StringTypes", "defproperty", "GetattrMagic"] import xml.dom try: unicode except NameError: StringTypes = type(''), else: StringTypes = type(''), type(unicode('')) # define True and False only if not defined as built-ins try: True except NameError: True = 1 False = 0 __all__.extend(["True", "False"]) try: isinstance('', StringTypes) except TypeError: # # Wrap isinstance() to make it compatible with the version in # Python 2.2 and newer. # _isinstance = isinstance def isinstance(obj, type_or_seq): try: return _isinstance(obj, type_or_seq) except TypeError: for t in type_or_seq: if _isinstance(obj, t): return 1 return 0 __all__.append("isinstance") if list is type([]): class NodeList(list): __slots__ = () def item(self, index): if 0 <= index < len(self): return self[index] def _get_length(self): return len(self) def _set_length(self, value): raise xml.dom.NoModificationAllowedErr( "attempt to modify read-only attribute 'length'") length = property(_get_length, _set_length, doc="The number of nodes in the NodeList.") def __getstate__(self): return list(self) def __setstate__(self, state): self[:] = state class EmptyNodeList(tuple): __slots__ = () def __add__(self, other): NL = NodeList() NL.extend(other) return NL def __radd__(self, other): NL = NodeList() NL.extend(other) return NL def item(self, index): return None def _get_length(self): return 0 def _set_length(self, value): raise xml.dom.NoModificationAllowedErr( "attempt to modify read-only attribute 'length'") length = property(_get_length, _set_length, doc="The number of nodes in the NodeList.") else: def NodeList(): return [] def EmptyNodeList(): return [] try: property except NameError: def defproperty(klass, name, doc): # taken care of by the base __getattr__() pass class GetattrMagic: def __getattr__(self, key): if key.startswith("_"): raise AttributeError, key try: get = getattr(self, "_get_" + key) except AttributeError: raise AttributeError, key return get() class NewStyle: pass else: def defproperty(klass, name, doc): get = getattr(klass, ("_get_" + name)).im_func def set(self, value, name=name): raise xml.dom.NoModificationAllowedErr( "attempt to modify read-only attribute " + repr(name)) assert not hasattr(klass, "_set_" + name), \ "expected not to find _set_" + name prop = property(get, set, doc=doc) setattr(klass, name, prop) class GetattrMagic: pass NewStyle = object PyXML-0.8.2/xml/dom/minidom.py0100644000076400001440000020073007614721001015275 0ustar martinusers"""\ minidom.py -- a lightweight DOM implementation. parse("foo.xml") parseString("") Todo: ===== * convenience methods for getting elements and text. * more testing * bring some of the writer and linearizer code into conformance with this interface * SAX 2 namespaces """ import xml.dom from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg from xml.dom.minicompat import * from xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS _TupleType = type(()) # This is used by the ID-cache invalidation checks; the list isn't # actually complete, since the nodes being checked will never be the # DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE. (The node being checked is # the node being added or removed, not the node being modified.) # _nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE, xml.dom.Node.ENTITY_REFERENCE_NODE) class Node(xml.dom.Node, GetattrMagic): namespaceURI = None # this is non-null only for elements and attributes parentNode = None ownerDocument = None nextSibling = None previousSibling = None prefix = EMPTY_PREFIX # non-null only for NS elements and attributes def __nonzero__(self): return True def toxml(self, encoding = None): return self.toprettyxml("", "", encoding) def toprettyxml(self, indent="\t", newl="\n", encoding = None): # indent = the indentation string to prepend, per level # newl = the newline string to append writer = _get_StringIO() if encoding is not None: import codecs # Can't use codecs.getwriter to preserve 2.0 compatibility writer = codecs.lookup(encoding)[3](writer) if self.nodeType == Node.DOCUMENT_NODE: # Can pass encoding only to document, to put it into XML header self.writexml(writer, "", indent, newl, encoding) else: self.writexml(writer, "", indent, newl) return writer.getvalue() def hasChildNodes(self): if self.childNodes: return True else: return False def _get_childNodes(self): return self.childNodes def _get_firstChild(self): if self.childNodes: return self.childNodes[0] def _get_lastChild(self): if self.childNodes: return self.childNodes[-1] def insertBefore(self, newChild, refChild): if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE: for c in tuple(newChild.childNodes): self.insertBefore(c, refChild) ### The DOM does not clearly specify what to return in this case return newChild if newChild.nodeType not in self._child_node_types: raise xml.dom.HierarchyRequestErr( "%s cannot be child of %s" % (repr(newChild), repr(self))) if newChild.parentNode is not None: newChild.parentNode.removeChild(newChild) if refChild is None: self.appendChild(newChild) else: try: index = self.childNodes.index(refChild) except ValueError: raise xml.dom.NotFoundErr() if newChild.nodeType in _nodeTypes_with_children: _clear_id_cache(self) self.childNodes.insert(index, newChild) newChild.nextSibling = refChild refChild.previousSibling = newChild if index: node = self.childNodes[index-1] node.nextSibling = newChild newChild.previousSibling = node else: newChild.previousSibling = None newChild.parentNode = self return newChild def appendChild(self, node): if node.nodeType == self.DOCUMENT_FRAGMENT_NODE: for c in tuple(node.childNodes): self.appendChild(c) ### The DOM does not clearly specify what to return in this case return node if node.nodeType not in self._child_node_types: raise xml.dom.HierarchyRequestErr( "%s cannot be child of %s" % (repr(node), repr(self))) elif node.nodeType in _nodeTypes_with_children: _clear_id_cache(self) if node.parentNode is not None: node.parentNode.removeChild(node) _append_child(self, node) node.nextSibling = None return node def replaceChild(self, newChild, oldChild): if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE: refChild = oldChild.nextSibling self.removeChild(oldChild) return self.insertBefore(newChild, refChild) if newChild.nodeType not in self._child_node_types: raise xml.dom.HierarchyRequestErr( "%s cannot be child of %s" % (repr(newChild), repr(self))) if newChild.parentNode is not None: newChild.parentNode.removeChild(newChild) if newChild is oldChild: return try: index = self.childNodes.index(oldChild) except ValueError: raise xml.dom.NotFoundErr() self.childNodes[index] = newChild newChild.parentNode = self oldChild.parentNode = None if (newChild.nodeType in _nodeTypes_with_children or oldChild.nodeType in _nodeTypes_with_children): _clear_id_cache(self) newChild.nextSibling = oldChild.nextSibling newChild.previousSibling = oldChild.previousSibling oldChild.nextSibling = None oldChild.previousSibling = None if newChild.previousSibling: newChild.previousSibling.nextSibling = newChild if newChild.nextSibling: newChild.nextSibling.previousSibling = newChild return oldChild def removeChild(self, oldChild): try: self.childNodes.remove(oldChild) except ValueError: raise xml.dom.NotFoundErr() if oldChild.nextSibling is not None: oldChild.nextSibling.previousSibling = oldChild.previousSibling if oldChild.previousSibling is not None: oldChild.previousSibling.nextSibling = oldChild.nextSibling oldChild.nextSibling = oldChild.previousSibling = None if oldChild.nodeType in _nodeTypes_with_children: _clear_id_cache(self) oldChild.parentNode = None return oldChild def normalize(self): L = [] for child in self.childNodes: if child.nodeType == Node.TEXT_NODE: data = child.data if data and L and L[-1].nodeType == child.nodeType: # collapse text node node = L[-1] node.data = node.data + child.data node.nextSibling = child.nextSibling child.unlink() elif data: if L: L[-1].nextSibling = child child.previousSibling = L[-1] else: child.previousSibling = None L.append(child) else: # empty text node; discard child.unlink() else: if L: L[-1].nextSibling = child child.previousSibling = L[-1] else: child.previousSibling = None L.append(child) if child.nodeType == Node.ELEMENT_NODE: child.normalize() self.childNodes[:] = L def cloneNode(self, deep): return _clone_node(self, deep, self.ownerDocument or self) def isSupported(self, feature, version): return self.ownerDocument.implementation.hasFeature(feature, version) def _get_localName(self): # Overridden in Element and Attr where localName can be Non-Null return None # Node interfaces from Level 3 (WD 9 April 2025) def isSameNode(self, other): return self is other def getInterface(self, feature): if self.isSupported(feature, None): return self else: return None # The "user data" functions use a dictionary that is only present # if some user data has been set, so be careful not to assume it # exists. def getUserData(self, key): try: return self._user_data[key][0] except (AttributeError, KeyError): return None def setUserData(self, key, data, handler): old = None try: d = self._user_data except AttributeError: d = {} self._user_data = d if d.has_key(key): old = d[key][0] if data is None: # ignore handlers passed for None handler = None if old is not None: del d[key] else: d[key] = (data, handler) return old def _call_user_data_handler(self, operation, src, dst): if hasattr(self, "_user_data"): for key, (data, handler) in self._user_data.items(): if handler is not None: handler.handle(operation, key, data, src, dst) # minidom-specific API: def unlink(self): self.parentNode = self.ownerDocument = None if self.childNodes: for child in self.childNodes: child.unlink() self.childNodes = NodeList() self.previousSibling = None self.nextSibling = None defproperty(Node, "firstChild", doc="First child node, or None.") defproperty(Node, "lastChild", doc="Last child node, or None.") defproperty(Node, "localName", doc="Namespace-local name of this node.") def _append_child(self, node): # fast path with less checks; usable by DOM builders if careful childNodes = self.childNodes if childNodes: last = childNodes[-1] node.__dict__["previousSibling"] = last last.__dict__["nextSibling"] = node childNodes.append(node) node.__dict__["parentNode"] = self def _in_document(node): # return True iff node is part of a document tree while node is not None: if node.nodeType == Node.DOCUMENT_NODE: return True node = node.parentNode return False def _write_data(writer, data): "Writes datachars to writer." data = data.replace("&", "&").replace("<", "<") data = data.replace("\"", """).replace(">", ">") writer.write(data) def _get_elements_by_tagName_helper(parent, name, rc): for node in parent.childNodes: if node.nodeType == Node.ELEMENT_NODE and \ (name == "*" or node.tagName == name): rc.append(node) _get_elements_by_tagName_helper(node, name, rc) return rc def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc): for node in parent.childNodes: if node.nodeType == Node.ELEMENT_NODE: if ((localName == "*" or node.localName == localName) and (nsURI == "*" or node.namespaceURI == nsURI)): rc.append(node) _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc) return rc class DocumentFragment(Node): nodeType = Node.DOCUMENT_FRAGMENT_NODE nodeName = "#document-fragment" nodeValue = None attributes = None parentNode = None _child_node_types = (Node.ELEMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.NOTATION_NODE) def __init__(self): self.childNodes = NodeList() class Attr(Node): nodeType = Node.ATTRIBUTE_NODE attributes = None ownerElement = None specified = False _is_id = False _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE) def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None, prefix=None): # skip setattr for performance d = self.__dict__ d["nodeName"] = d["name"] = qName d["namespaceURI"] = namespaceURI d["prefix"] = prefix d['childNodes'] = NodeList() # Add the single child node that represents the value of the attr self.childNodes.append(Text()) # nodeValue and value are set elsewhere def _get_localName(self): return self.nodeName.split(":", 1)[-1] def _get_name(self): return self.name def _get_specified(self): return self.specified def __setattr__(self, name, value): d = self.__dict__ if name in ("value", "nodeValue"): d["value"] = d["nodeValue"] = value d2 = self.childNodes[0].__dict__ d2["data"] = d2["nodeValue"] = value if self.ownerElement is not None: _clear_id_cache(self.ownerElement) elif name in ("name", "nodeName"): d["name"] = d["nodeName"] = value if self.ownerElement is not None: _clear_id_cache(self.ownerElement) else: d[name] = value def _set_prefix(self, prefix): nsuri = self.namespaceURI if prefix == "xmlns": if nsuri and nsuri != XMLNS_NAMESPACE: raise xml.dom.NamespaceErr( "illegal use of 'xmlns' prefix for the wrong namespace") d = self.__dict__ d['prefix'] = prefix if prefix is None: newName = self.localName else: newName = "%s:%s" % (prefix, self.localName) if self.ownerElement: _clear_id_cache(self.ownerElement) d['nodeName'] = d['name'] = newName def _set_value(self, value): d = self.__dict__ d['value'] = d['nodeValue'] = value if self.ownerElement: _clear_id_cache(self.ownerElement) self.childNodes[0].data = value def unlink(self): # This implementation does not call the base implementation # since most of that is not needed, and the expense of the # method call is not warranted. We duplicate the removal of # children, but that's all we needed from the base class. elem = self.ownerElement if elem is not None: del elem._attrs[self.nodeName] del elem._attrsNS[(self.namespaceURI, self.localName)] if self._is_id: self._is_id = False elem._magic_id_nodes -= 1 self.ownerDocument._magic_id_count -= 1 for child in self.childNodes: child.unlink() del self.childNodes[:] def _get_isId(self): if self._is_id: return True doc = self.ownerDocument elem = self.ownerElement if doc is None or elem is None: return False info = doc._get_elem_info(elem) if info is None: return False if self.namespaceURI: return info.isIdNS(self.namespaceURI, self.localName) else: return info.isId(self.nodeName) def _get_schemaType(self): doc = self.ownerDocument elem = self.ownerElement if doc is None or elem is None: return _no_type info = doc._get_elem_info(elem) if info is None: return _no_type if self.namespaceURI: return info.getAttributeTypeNS(self.namespaceURI, self.localName) else: return info.getAttributeType(self.nodeName) defproperty(Attr, "isId", doc="True if this attribute is an ID.") defproperty(Attr, "localName", doc="Namespace-local name of this attribute.") defproperty(Attr, "schemaType", doc="Schema type for this attribute.") class NamedNodeMap(NewStyle, GetattrMagic): """The attribute list is a transient interface to the underlying dictionaries. Mutations here will change the underlying element's dictionary. Ordering is imposed artificially and does not reflect the order of attributes as found in an input document. """ __slots__ = ('_attrs', '_attrsNS', '_ownerElement') def __init__(self, attrs, attrsNS, ownerElement): self._attrs = attrs self._attrsNS = attrsNS self._ownerElement = ownerElement def _get_length(self): return len(self._attrs) def item(self, index): try: return self[self._attrs.keys()[index]] except IndexError: return None def items(self): L = [] for node in self._attrs.values(): L.append((node.nodeName, node.value)) return L def itemsNS(self): L = [] for node in self._attrs.values(): L.append(((node.namespaceURI, node.localName), node.value)) return L def has_key(self, key): if isinstance(key, StringTypes): return self._attrs.has_key(key) else: return self._attrsNS.has_key(key) def keys(self): return self._attrs.keys() def keysNS(self): return self._attrsNS.keys() def values(self): return self._attrs.values() def get(self, name, value=None): return self._attrs.get(name, value) __len__ = _get_length def __cmp__(self, other): if self._attrs is getattr(other, "_attrs", None): return 0 else: return cmp(id(self), id(other)) def __getitem__(self, attname_or_tuple): if isinstance(attname_or_tuple, _TupleType): return self._attrsNS[attname_or_tuple] else: return self._attrs[attname_or_tuple] # same as set def __setitem__(self, attname, value): if isinstance(value, StringTypes): try: node = self._attrs[attname] except KeyError: node = Attr(attname) node.ownerDocument = self._ownerElement.ownerDocument self.setNamedItem(node) node.value = value else: if not isinstance(value, Attr): raise TypeError, "value must be a string or Attr object" node = value self.setNamedItem(node) def getNamedItem(self, name): try: return self._attrs[name] except KeyError: return None def getNamedItemNS(self, namespaceURI, localName): try: return self._attrsNS[(namespaceURI, localName)] except KeyError: return None def removeNamedItem(self, name): n = self.getNamedItem(name) if n is not None: _clear_id_cache(self._ownerElement) del self._attrs[n.nodeName] del self._attrsNS[(n.namespaceURI, n.localName)] if n.__dict__.has_key('ownerElement'): n.__dict__['ownerElement'] = None return n else: raise xml.dom.NotFoundErr() def removeNamedItemNS(self, namespaceURI, localName): n = self.getNamedItemNS(namespaceURI, localName) if n is not None: _clear_id_cache(self._ownerElement) del self._attrsNS[(n.namespaceURI, n.localName)] del self._attrs[n.nodeName] if n.__dict__.has_key('ownerElement'): n.__dict__['ownerElement'] = None return n else: raise xml.dom.NotFoundErr() def setNamedItem(self, node): if not isinstance(node, Attr): raise xml.dom.HierarchyRequestErr( "%s cannot be child of %s" % (repr(node), repr(self))) old = self._attrs.get(node.name) if old: old.unlink() self._attrs[node.name] = node self._attrsNS[(node.namespaceURI, node.localName)] = node node.ownerElement = self._ownerElement _clear_id_cache(node.ownerElement) return old def setNamedItemNS(self, node): return self.setNamedItem(node) def __delitem__(self, attname_or_tuple): node = self[attname_or_tuple] _clear_id_cache(node.ownerElement) node.unlink() def __getstate__(self): return self._attrs, self._attrsNS, self._ownerElement def __setstate__(self, state): self._attrs, self._attrsNS, self._ownerElement = state defproperty(NamedNodeMap, "length", doc="Number of nodes in the NamedNodeMap.") AttributeList = NamedNodeMap class TypeInfo(NewStyle): __slots__ = 'namespace', 'name' def __init__(self, namespace, name): self.namespace = namespace self.name = name def __repr__(self): if self.namespace: return "" % (`self.name`, `self.namespace`) else: return "" % `self.name` def _get_name(self): return self.name def _get_namespace(self): return self.namespace _no_type = TypeInfo(None, None) class Element(Node): nodeType = Node.ELEMENT_NODE nodeValue = None schemaType = _no_type _magic_id_nodes = 0 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE) def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None, localName=None): self.tagName = self.nodeName = tagName self.prefix = prefix self.namespaceURI = namespaceURI self.childNodes = NodeList() self._attrs = {} # attributes are double-indexed: self._attrsNS = {} # tagName -> Attribute # URI,localName -> Attribute # in the future: consider lazy generation # of attribute objects this is too tricky # for now because of headaches with # namespaces. def _get_localName(self): return self.tagName.split(":", 1)[-1] def _get_tagName(self): return self.tagName def unlink(self): for attr in self._attrs.values(): attr.unlink() self._attrs = None self._attrsNS = None Node.unlink(self) def getAttribute(self, attname): try: return self._attrs[attname].value except KeyError: return "" def getAttributeNS(self, namespaceURI, localName): try: return self._attrsNS[(namespaceURI, localName)].value except KeyError: return "" def setAttribute(self, attname, value): attr = self.getAttributeNode(attname) if attr is None: attr = Attr(attname) # for performance d = attr.__dict__ d["value"] = d["nodeValue"] = value d["ownerDocument"] = self.ownerDocument self.setAttributeNode(attr) elif value != attr.value: d = attr.__dict__ d["value"] = d["nodeValue"] = value if attr.isId: _clear_id_cache(self) def setAttributeNS(self, namespaceURI, qualifiedName, value): prefix, localname = _nssplit(qualifiedName) attr = self.getAttributeNodeNS(namespaceURI, localname) if attr is None: # for performance attr = Attr(qualifiedName, namespaceURI, localname, prefix) d = attr.__dict__ d["prefix"] = prefix d["nodeName"] = qualifiedName d["value"] = d["nodeValue"] = value d["ownerDocument"] = self.ownerDocument self.setAttributeNode(attr) else: d = attr.__dict__ if value != attr.value: d["value"] = d["nodeValue"] = value if attr.isId: _clear_id_cache(self) if attr.prefix != prefix: d["prefix"] = prefix d["nodeName"] = qualifiedName def getAttributeNode(self, attrname): return self._attrs.get(attrname) def getAttributeNodeNS(self, namespaceURI, localName): return self._attrsNS.get((namespaceURI, localName)) def setAttributeNode(self, attr): if attr.ownerElement not in (None, self): raise xml.dom.InuseAttributeErr("attribute node already owned") old1 = self._attrs.get(attr.name, None) if old1 is not None: self.removeAttributeNode(old1) old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None) if old2 is not None and old2 is not old1: self.removeAttributeNode(old2) _set_attribute_node(self, attr) if old1 is not attr: # It might have already been part of this node, in which case # it doesn't represent a change, and should not be returned. return old1 if old2 is not attr: return old2 setAttributeNodeNS = setAttributeNode def removeAttribute(self, name): try: attr = self._attrs[name] except KeyError: raise xml.dom.NotFoundErr() self.removeAttributeNode(attr) def removeAttributeNS(self, namespaceURI, localName): try: attr = self._attrsNS[(namespaceURI, localName)] except KeyError: raise xml.dom.NotFoundErr() self.removeAttributeNode(attr) def removeAttributeNode(self, node): if node is None: raise xml.dom.NotFoundErr() try: self._attrs[node.name] except KeyError: raise xml.dom.NotFoundErr() _clear_id_cache(self) node.unlink() # Restore this since the node is still useful and otherwise # unlinked node.ownerDocument = self.ownerDocument removeAttributeNodeNS = removeAttributeNode def hasAttribute(self, name): return self._attrs.has_key(name) def hasAttributeNS(self, namespaceURI, localName): return self._attrsNS.has_key((namespaceURI, localName)) def getElementsByTagName(self, name): return _get_elements_by_tagName_helper(self, name, NodeList()) def getElementsByTagNameNS(self, namespaceURI, localName): return _get_elements_by_tagName_ns_helper( self, namespaceURI, localName, NodeList()) def __repr__(self): return "" % (self.tagName, id(self)) def writexml(self, writer, indent="", addindent="", newl=""): # indent = current indentation # addindent = indentation to add to higher levels # newl = newline string writer.write(indent+"<" + self.tagName) attrs = self._get_attributes() a_names = attrs.keys() a_names.sort() for a_name in a_names: writer.write(" %s=\"" % a_name) _write_data(writer, attrs[a_name].value) writer.write("\"") if self.childNodes: writer.write(">%s"%(newl)) for node in self.childNodes: node.writexml(writer,indent+addindent,addindent,newl) writer.write("%s%s" % (indent,self.tagName,newl)) else: writer.write("/>%s"%(newl)) def _get_attributes(self): return NamedNodeMap(self._attrs, self._attrsNS, self) def hasAttributes(self): if self._attrs: return True else: return False # DOM Level 3 attributes, based on the 22 Oct 2025 draft def setIdAttribute(self, name): idAttr = self.getAttributeNode(name) self.setIdAttributeNode(idAttr) def setIdAttributeNS(self, namespaceURI, localName): idAttr = self.getAttributeNodeNS(namespaceURI, localName) self.setIdAttributeNode(idAttr) def setIdAttributeNode(self, idAttr): if idAttr is None or not self.isSameNode(idAttr.ownerElement): raise xml.dom.NotFoundErr() if _get_containing_entref(self) is not None: raise xml.dom.NoModificationAllowedErr() if not idAttr._is_id: idAttr.__dict__['_is_id'] = True self._magic_id_nodes += 1 self.ownerDocument._magic_id_count += 1 _clear_id_cache(self) defproperty(Element, "attributes", doc="NamedNodeMap of attributes on the element.") defproperty(Element, "localName", doc="Namespace-local name of this element.") def _set_attribute_node(element, attr): _clear_id_cache(element) element._attrs[attr.name] = attr element._attrsNS[(attr.namespaceURI, attr.localName)] = attr # This creates a circular reference, but Element.unlink() # breaks the cycle since the references to the attribute # dictionaries are tossed. attr.__dict__['ownerElement'] = element class Childless: """Mixin that makes childless-ness easy to implement and avoids the complexity of the Node methods that deal with children. """ attributes = None childNodes = EmptyNodeList() firstChild = None lastChild = None def _get_firstChild(self): return None def _get_lastChild(self): return None def appendChild(self, node): raise xml.dom.HierarchyRequestErr( self.nodeName + " nodes cannot have children") def hasChildNodes(self): return False def insertBefore(self, newChild, refChild): raise xml.dom.HierarchyRequestErr( self.nodeName + " nodes do not have children") def removeChild(self, oldChild): raise xml.dom.NotFoundErr( self.nodeName + " nodes do not have children") def replaceChild(self, newChild, oldChild): raise xml.dom.HierarchyRequestErr( self.nodeName + " nodes do not have children") class ProcessingInstruction(Childless, Node): nodeType = Node.PROCESSING_INSTRUCTION_NODE def __init__(self, target, data): self.target = self.nodeName = target self.data = self.nodeValue = data def _get_data(self): return self.data def _set_data(self, value): d = self.__dict__ d['data'] = d['nodeValue'] = value def _get_target(self): return self.target def _set_target(self, value): d = self.__dict__ d['target'] = d['nodeName'] = value def __setattr__(self, name, value): if name == "data" or name == "nodeValue": self.__dict__['data'] = self.__dict__['nodeValue'] = value elif name == "target" or name == "nodeName": self.__dict__['target'] = self.__dict__['nodeName'] = value else: self.__dict__[name] = value def writexml(self, writer, indent="", addindent="", newl=""): writer.write("%s%s" % (indent,self.target, self.data, newl)) class CharacterData(Childless, Node): def _get_length(self): return len(self.data) __len__ = _get_length def _get_data(self): return self.__dict__['data'] def _set_data(self, data): d = self.__dict__ d['data'] = d['nodeValue'] = data _get_nodeValue = _get_data _set_nodeValue = _set_data def __setattr__(self, name, value): if name == "data" or name == "nodeValue": self.__dict__['data'] = self.__dict__['nodeValue'] = value else: self.__dict__[name] = value def __repr__(self): data = self.data if len(data) > 10: dotdotdot = "..." else: dotdotdot = "" return "" % ( self.__class__.__name__, data[0:10], dotdotdot) def substringData(self, offset, count): if offset < 0: raise xml.dom.IndexSizeErr("offset cannot be negative") if offset >= len(self.data): raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") if count < 0: raise xml.dom.IndexSizeErr("count cannot be negative") return self.data[offset:offset+count] def appendData(self, arg): self.data = self.data + arg def insertData(self, offset, arg): if offset < 0: raise xml.dom.IndexSizeErr("offset cannot be negative") if offset >= len(self.data): raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") if arg: self.data = "%s%s%s" % ( self.data[:offset], arg, self.data[offset:]) def deleteData(self, offset, count): if offset < 0: raise xml.dom.IndexSizeErr("offset cannot be negative") if offset >= len(self.data): raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") if count < 0: raise xml.dom.IndexSizeErr("count cannot be negative") if count: self.data = self.data[:offset] + self.data[offset+count:] def replaceData(self, offset, count, arg): if offset < 0: raise xml.dom.IndexSizeErr("offset cannot be negative") if offset >= len(self.data): raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") if count < 0: raise xml.dom.IndexSizeErr("count cannot be negative") if count: self.data = "%s%s%s" % ( self.data[:offset], arg, self.data[offset+count:]) defproperty(CharacterData, "length", doc="Length of the string data.") class Text(CharacterData): # Make sure we don't add an instance __dict__ if we don't already # have one, at least when that's possible: # XXX this does not work, CharacterData is an old-style class # __slots__ = () nodeType = Node.TEXT_NODE nodeName = "#text" attributes = None def splitText(self, offset): if offset < 0 or offset > len(self.data): raise xml.dom.IndexSizeErr("illegal offset value") newText = self.__class__() newText.data = self.data[offset:] newText.ownerDocument = self.ownerDocument next = self.nextSibling if self.parentNode and self in self.parentNode.childNodes: if next is None: self.parentNode.appendChild(newText) else: self.parentNode.insertBefore(newText, next) self.data = self.data[:offset] return newText def writexml(self, writer, indent="", addindent="", newl=""): _write_data(writer, "%s%s%s"%(indent, self.data, newl)) # DOM Level 3 (WD 9 April 2025) def _get_wholeText(self): L = [self.data] n = self.previousSibling while n is not None: if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): L.insert(0, n.data) n = n.previousSibling else: break n = self.nextSibling while n is not None: if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): L.append(n.data) n = n.nextSibling else: break return ''.join(L) def replaceWholeText(self, content): # XXX This needs to be seriously changed if minidom ever # supports EntityReference nodes. parent = self.parentNode n = self.previousSibling while n is not None: if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): next = n.previousSibling parent.removeChild(n) n = next else: break n = self.nextSibling if not content: parent.removeChild(self) while n is not None: if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): next = n.nextSibling parent.removeChild(n) n = next else: break if content: d = self.__dict__ d['data'] = content d['nodeValue'] = content return self else: return None def _get_isWhitespaceInElementContent(self): if self.data.strip(): return False elem = _get_containing_element(self) if elem is None: return False info = self.ownerDocument._get_elem_info(elem) if info is None: return False else: return info.isElementContent() defproperty(Text, "isWhitespaceInElementContent", doc="True iff this text node contains only whitespace" " and is in element content.") defproperty(Text, "wholeText", doc="The text of all logically-adjacent text nodes.") def _get_containing_element(node): c = node.parentNode while c is not None: if c.nodeType == Node.ELEMENT_NODE: return c c = c.parentNode return None def _get_containing_entref(node): c = node.parentNode while c is not None: if c.nodeType == Node.ENTITY_REFERENCE_NODE: return c c = c.parentNode return None class Comment(Childless, CharacterData): nodeType = Node.COMMENT_NODE nodeName = "#comment" def __init__(self, data): self.data = self.nodeValue = data def writexml(self, writer, indent="", addindent="", newl=""): writer.write("%s%s" % (indent, self.data, newl)) class CDATASection(Text): # Make sure we don't add an instance __dict__ if we don't already # have one, at least when that's possible: # XXX this does not work, Text is an old-style class # __slots__ = () nodeType = Node.CDATA_SECTION_NODE nodeName = "#cdata-section" def writexml(self, writer, indent="", addindent="", newl=""): if self.data.find("]]>") >= 0: raise ValueError("']]>' not allowed in a CDATA section") writer.write("" % self.data) class ReadOnlySequentialNamedNodeMap(NewStyle, GetattrMagic): __slots__ = '_seq', def __init__(self, seq=()): # seq should be a list or tuple self._seq = seq def __len__(self): return len(self._seq) def _get_length(self): return len(self._seq) def getNamedItem(self, name): for n in self._seq: if n.nodeName == name: return n def getNamedItemNS(self, namespaceURI, localName): for n in self._seq: if n.namespaceURI == namespaceURI and n.localName == localName: return n def __getitem__(self, name_or_tuple): if isinstance(name_or_tuple, _TupleType): node = self.getNamedItemNS(*name_or_tuple) else: node = self.getNamedItem(name_or_tuple) if node is None: raise KeyError, name_or_tuple return node def item(self, index): if index < 0: return None try: return self._seq[index] except IndexError: return None def removeNamedItem(self, name): raise xml.dom.NoModificationAllowedErr( "NamedNodeMap instance is read-only") def removeNamedItemNS(self, namespaceURI, localName): raise xml.dom.NoModificationAllowedErr( "NamedNodeMap instance is read-only") def setNamedItem(self, node): raise xml.dom.NoModificationAllowedErr( "NamedNodeMap instance is read-only") def setNamedItemNS(self, node): raise xml.dom.NoModificationAllowedErr( "NamedNodeMap instance is read-only") def __getstate__(self): return [self._seq] def __setstate__(self, state): self._seq = state[0] defproperty(ReadOnlySequentialNamedNodeMap, "length", doc="Number of entries in the NamedNodeMap.") class Identified: """Mix-in class that supports the publicId and systemId attributes.""" # XXX this does not work, this is an old-style class # __slots__ = 'publicId', 'systemId' def _identified_mixin_init(self, publicId, systemId): self.publicId = publicId self.systemId = systemId def _get_publicId(self): return self.publicId def _get_systemId(self): return self.systemId class DocumentType(Identified, Childless, Node): nodeType = Node.DOCUMENT_TYPE_NODE nodeValue = None name = None publicId = None systemId = None internalSubset = None def __init__(self, qualifiedName): self.entities = ReadOnlySequentialNamedNodeMap() self.notations = ReadOnlySequentialNamedNodeMap() if qualifiedName: prefix, localname = _nssplit(qualifiedName) self.name = localname self.nodeName = self.name def _get_internalSubset(self): return self.internalSubset def cloneNode(self, deep): if self.ownerDocument is None: # it's ok clone = DocumentType(None) clone.name = self.name clone.nodeName = self.name operation = xml.dom.UserDataHandler.NODE_CLONED if deep: clone.entities._seq = [] clone.notations._seq = [] for n in self.notations._seq: notation = Notation(n.nodeName, n.publicId, n.systemId) clone.notations._seq.append(notation) n._call_user_data_handler(operation, n, notation) for e in self.entities._seq: entity = Entity(e.nodeName, e.publicId, e.systemId, e.notationName) entity.actualEncoding = e.actualEncoding entity.encoding = e.encoding entity.version = e.version clone.entities._seq.append(entity) e._call_user_data_handler(operation, n, entity) self._call_user_data_handler(operation, self, clone) return clone else: return None def writexml(self, writer, indent="", addindent="", newl=""): writer.write("\n") class Entity(Identified, Node): attributes = None nodeType = Node.ENTITY_NODE nodeValue = None actualEncoding = None encoding = None version = None def __init__(self, name, publicId, systemId, notation): self.nodeName = name self.notationName = notation self.childNodes = NodeList() self._identified_mixin_init(publicId, systemId) def _get_actualEncoding(self): return self.actualEncoding def _get_encoding(self): return self.encoding def _get_version(self): return self.version def appendChild(self, newChild): raise xml.dom.HierarchyRequestErr( "cannot append children to an entity node") def insertBefore(self, newChild, refChild): raise xml.dom.HierarchyRequestErr( "cannot insert children below an entity node") def removeChild(self, oldChild): raise xml.dom.HierarchyRequestErr( "cannot remove children from an entity node") def replaceChild(self, newChild, oldChild): raise xml.dom.HierarchyRequestErr( "cannot replace children of an entity node") class Notation(Identified, Childless, Node): nodeType = Node.NOTATION_NODE nodeValue = None def __init__(self, name, publicId, systemId): self.nodeName = name self._identified_mixin_init(publicId, systemId) class DOMImplementation(DOMImplementationLS): _features = [("core", "1.0"), ("core", "2.0"), ("core", "3.0"), ("core", None), ("xml", "1.0"), ("xml", "2.0"), ("xml", "3.0"), ("xml", None), ("ls-load", "3.0"), ("ls-load", None), ] def hasFeature(self, feature, version): if version == "": version = None return (feature.lower(), version) in self._features def createDocument(self, namespaceURI, qualifiedName, doctype): if doctype and doctype.parentNode is not None: raise xml.dom.WrongDocumentErr( "doctype object owned by another DOM tree") doc = self._create_document() add_root_element = not (namespaceURI is None and qualifiedName is None and doctype is None) if not qualifiedName and add_root_element: # The spec is unclear what to raise here; SyntaxErr # would be the other obvious candidate. Since Xerces raises # InvalidCharacterErr, and since SyntaxErr is not listed # for createDocument, that seems to be the better choice. # XXX: need to check for illegal characters here and in # createElement. # DOM Level III clears this up when talking about the return value # of this function. If namespaceURI, qName and DocType are # Null the document is returned without a document element # Otherwise if doctype or namespaceURI are not None # Then we go back to the above problem raise xml.dom.InvalidCharacterErr("Element with no name") if add_root_element: prefix, localname = _nssplit(qualifiedName) if prefix == "xml" \ and namespaceURI != "http://www.w3.org/XML/1998/namespace": raise xml.dom.NamespaceErr("illegal use of 'xml' prefix") if prefix and not namespaceURI: raise xml.dom.NamespaceErr( "illegal use of prefix without namespaces") element = doc.createElementNS(namespaceURI, qualifiedName) if doctype: doc.appendChild(doctype) doc.appendChild(element) if doctype: doctype.parentNode = doctype.ownerDocument = doc doc.doctype = doctype doc.implementation = self return doc def createDocumentType(self, qualifiedName, publicId, systemId): doctype = DocumentType(qualifiedName) doctype.publicId = publicId doctype.systemId = systemId return doctype # DOM Level 3 (WD 9 April 2025) def getInterface(self, feature): if self.hasFeature(feature, None): return self else: return None # internal def _create_document(self): return Document() class ElementInfo(NewStyle): """Object that represents content-model information for an element. This implementation is not expected to be used in practice; DOM builders should provide implementations which do the right thing using information available to it. """ __slots__ = 'tagName', def __init__(self, name): self.tagName = name def getAttributeType(self, aname): return _no_type def getAttributeTypeNS(self, namespaceURI, localName): return _no_type def isElementContent(self): return False def isEmpty(self): """Returns true iff this element is declared to have an EMPTY content model.""" return False def isId(self, aname): """Returns true iff the named attribte is a DTD-style ID.""" return False def isIdNS(self, namespaceURI, localName): """Returns true iff the identified attribute is a DTD-style ID.""" return False def __getstate__(self): return self.tagName def __setstate__(self, state): self.tagName = state def _clear_id_cache(node): if node.nodeType == Node.DOCUMENT_NODE: node._id_cache.clear() node._id_search_stack = None elif _in_document(node): node.ownerDocument._id_cache.clear() node.ownerDocument._id_search_stack= None class Document(Node, DocumentLS): _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE) nodeType = Node.DOCUMENT_NODE nodeName = "#document" nodeValue = None attributes = None doctype = None parentNode = None previousSibling = nextSibling = None implementation = DOMImplementation() # Document attributes from Level 3 (WD 9 April 2025) actualEncoding = None encoding = None standalone = None version = None strictErrorChecking = False errorHandler = None documentURI = None _magic_id_count = 0 def __init__(self): self.childNodes = NodeList() # mapping of (namespaceURI, localName) -> ElementInfo # and tagName -> ElementInfo self._elem_info = {} self._id_cache = {} self._id_search_stack = None def _get_elem_info(self, element): if element.namespaceURI: key = element.namespaceURI, element.localName else: key = element.tagName return self._elem_info.get(key) def _get_actualEncoding(self): return self.actualEncoding def _get_doctype(self): return self.doctype def _get_documentURI(self): return self.documentURI def _get_encoding(self): return self.encoding def _get_errorHandler(self): return self.errorHandler def _get_standalone(self): return self.standalone def _get_strictErrorChecking(self): return self.strictErrorChecking def _get_version(self): return self.version def appendChild(self, node): if node.nodeType not in self._child_node_types: raise xml.dom.HierarchyRequestErr( "%s cannot be child of %s" % (repr(node), repr(self))) if node.parentNode is not None: # This needs to be done before the next test since this # may *be* the document element, in which case it should # end up re-ordered to the end. node.parentNode.removeChild(node) if node.nodeType == Node.ELEMENT_NODE \ and self._get_documentElement(): raise xml.dom.HierarchyRequestErr( "two document elements disallowed") return Node.appendChild(self, node) def removeChild(self, oldChild): try: self.childNodes.remove(oldChild) except ValueError: raise xml.dom.NotFoundErr() oldChild.nextSibling = oldChild.previousSibling = None oldChild.parentNode = None if self.documentElement is oldChild: self.documentElement = None return oldChild def _get_documentElement(self): for node in self.childNodes: if node.nodeType == Node.ELEMENT_NODE: return node def unlink(self): if self.doctype is not None: self.doctype.unlink() self.doctype = None Node.unlink(self) def cloneNode(self, deep): if not deep: return None clone = self.implementation.createDocument(None, None, None) clone.encoding = self.encoding clone.standalone = self.standalone clone.version = self.version for n in self.childNodes: childclone = _clone_node(n, deep, clone) assert childclone.ownerDocument.isSameNode(clone) clone.childNodes.append(childclone) if childclone.nodeType == Node.DOCUMENT_NODE: assert clone.documentElement is None elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE: assert clone.doctype is None clone.doctype = childclone childclone.parentNode = clone self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED, self, clone) return clone def createDocumentFragment(self): d = DocumentFragment() d.ownerDocument = self return d def createElement(self, tagName): e = Element(tagName) e.ownerDocument = self return e def createTextNode(self, data): if not isinstance(data, StringTypes): raise TypeError, "node contents must be a string" t = Text() t.data = data t.ownerDocument = self return t def createCDATASection(self, data): if not isinstance(data, StringTypes): raise TypeError, "node contents must be a string" c = CDATASection() c.data = data c.ownerDocument = self return c def createComment(self, data): c = Comment(data) c.ownerDocument = self return c def createProcessingInstruction(self, target, data): p = ProcessingInstruction(target, data) p.ownerDocument = self return p def createAttribute(self, qName): a = Attr(qName) a.ownerDocument = self a.value = "" return a def createElementNS(self, namespaceURI, qualifiedName): prefix, localName = _nssplit(qualifiedName) e = Element(qualifiedName, namespaceURI, prefix) e.ownerDocument = self return e def createAttributeNS(self, namespaceURI, qualifiedName): prefix, localName = _nssplit(qualifiedName) a = Attr(qualifiedName, namespaceURI, localName, prefix) a.ownerDocument = self a.value = "" return a # A couple of implementation-specific helpers to create node types # not supported by the W3C DOM specs: def _create_entity(self, name, publicId, systemId, notationName): e = Entity(name, publicId, systemId, notationName) e.ownerDocument = self return e def _create_notation(self, name, publicId, systemId): n = Notation(name, publicId, systemId) n.ownerDocument = self return n def getElementById(self, id): if self._id_cache.has_key(id): return self._id_cache[id] if not (self._elem_info or self._magic_id_count): return None stack = self._id_search_stack if stack is None: # we never searched before, or the cache has been cleared stack = [self.documentElement] self._id_search_stack = stack elif not stack: # Previous search was completed and cache is still valid; # no matching node. return None result = None while stack: node = stack.pop() # add child elements to stack for continued searching stack.extend([child for child in node.childNodes if child.nodeType in _nodeTypes_with_children]) # check this node info = self._get_elem_info(node) if info: # We have to process all ID attributes before # returning in order to get all the attributes set to # be IDs using Element.setIdAttribute*(). for attr in node.attributes.values(): if attr.namespaceURI: if info.isIdNS(attr.namespaceURI, attr.localName): self._id_cache[attr.value] = node if attr.value == id: result = node elif not node._magic_id_nodes: break elif info.isId(attr.name): self._id_cache[attr.value] = node if attr.value == id: result = node elif not node._magic_id_nodes: break elif attr._is_id: self._id_cache[attr.value] = node if attr.value == id: result = node elif node._magic_id_nodes == 1: break elif node._magic_id_nodes: for attr in node.attributes.values(): if attr._is_id: self._id_cache[attr.value] = node if attr.value == id: result = node if result is not None: break return result def getElementsByTagName(self, name): return _get_elements_by_tagName_helper(self, name, NodeList()) def getElementsByTagNameNS(self, namespaceURI, localName): return _get_elements_by_tagName_ns_helper( self, namespaceURI, localName, NodeList()) def isSupported(self, feature, version): return self.implementation.hasFeature(feature, version) def importNode(self, node, deep): if node.nodeType == Node.DOCUMENT_NODE: raise xml.dom.NotSupportedErr("cannot import document nodes") elif node.nodeType == Node.DOCUMENT_TYPE_NODE: raise xml.dom.NotSupportedErr("cannot import document type nodes") return _clone_node(node, deep, self) def writexml(self, writer, indent="", addindent="", newl="", encoding = None): if encoding is None: writer.write('\n') else: writer.write('\n' % encoding) for node in self.childNodes: node.writexml(writer, indent, addindent, newl) # DOM Level 3 (WD 9 April 2025) def renameNode(self, n, namespaceURI, name): if n.ownerDocument is not self: raise xml.dom.WrongDocumentErr( "cannot rename nodes from other documents;\n" "expected %s,\nfound %s" % (self, n.ownerDocument)) if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE): raise xml.dom.NotSupportedErr( "renameNode() only applies to element and attribute nodes") if namespaceURI != EMPTY_NAMESPACE: if ':' in name: prefix, localName = name.split(':', 1) if ( prefix == "xmlns" and namespaceURI != xml.dom.XMLNS_NAMESPACE): raise xml.dom.NamespaceErr( "illegal use of 'xmlns' prefix") else: if ( name == "xmlns" and namespaceURI != xml.dom.XMLNS_NAMESPACE and n.nodeType == Node.ATTRIBUTE_NODE): raise xml.dom.NamespaceErr( "illegal use of the 'xmlns' attribute") prefix = None localName = name else: prefix = None localName = None if n.nodeType == Node.ATTRIBUTE_NODE: element = n.ownerElement if element is not None: is_id = n._is_id element.removeAttributeNode(n) else: element = None # avoid __setattr__ d = n.__dict__ d['prefix'] = prefix d['localName'] = localName d['namespaceURI'] = namespaceURI d['nodeName'] = name if n.nodeType == Node.ELEMENT_NODE: d['tagName'] = name else: # attribute node d['name'] = name if element is not None: element.setAttributeNode(n) if is_id: element.setIdAttributeNode(n) # It's not clear from a semantic perspective whether we should # call the user data handlers for the NODE_RENAMED event since # we're re-using the existing node. The draft spec has been # interpreted as meaning "no, don't call the handler unless a # new node is created." return n defproperty(Document, "documentElement", doc="Top-level element of this document.") def _clone_node(node, deep, newOwnerDocument): """ Clone a node and give it the new owner document. Called by Node.cloneNode and Document.importNode """ if node.ownerDocument.isSameNode(newOwnerDocument): operation = xml.dom.UserDataHandler.NODE_CLONED else: operation = xml.dom.UserDataHandler.NODE_IMPORTED if node.nodeType == Node.ELEMENT_NODE: clone = newOwnerDocument.createElementNS(node.namespaceURI, node.nodeName) for attr in node.attributes.values(): clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName) a.specified = attr.specified if deep: for child in node.childNodes: c = _clone_node(child, deep, newOwnerDocument) clone.appendChild(c) elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE: clone = newOwnerDocument.createDocumentFragment() if deep: for child in node.childNodes: c = _clone_node(child, deep, newOwnerDocument) clone.appendChild(c) elif node.nodeType == Node.TEXT_NODE: clone = newOwnerDocument.createTextNode(node.data) elif node.nodeType == Node.CDATA_SECTION_NODE: clone = newOwnerDocument.createCDATASection(node.data) elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: clone = newOwnerDocument.createProcessingInstruction(node.target, node.data) elif node.nodeType == Node.COMMENT_NODE: clone = newOwnerDocument.createComment(node.data) elif node.nodeType == Node.ATTRIBUTE_NODE: clone = newOwnerDocument.createAttributeNS(node.namespaceURI, node.nodeName) clone.specified = True clone.value = node.value elif node.nodeType == Node.DOCUMENT_TYPE_NODE: assert node.ownerDocument is not newOwnerDocument operation = xml.dom.UserDataHandler.NODE_IMPORTED clone = newOwnerDocument.implementation.createDocumentType( node.name, node.publicId, node.systemId) clone.ownerDocument = newOwnerDocument if deep: clone.entities._seq = [] clone.notations._seq = [] for n in node.notations._seq: notation = Notation(n.nodeName, n.publicId, n.systemId) notation.ownerDocument = newOwnerDocument clone.notations._seq.append(notation) if hasattr(n, '_call_user_data_handler'): n._call_user_data_handler(operation, n, notation) for e in node.entities._seq: entity = Entity(e.nodeName, e.publicId, e.systemId, e.notationName) entity.actualEncoding = e.actualEncoding entity.encoding = e.encoding entity.version = e.version entity.ownerDocument = newOwnerDocument clone.entities._seq.append(entity) if hasattr(e, '_call_user_data_handler'): e._call_user_data_handler(operation, n, entity) else: # Note the cloning of Document and DocumentType nodes is # implemenetation specific. minidom handles those cases # directly in the cloneNode() methods. raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node)) # Check for _call_user_data_handler() since this could conceivably # used with other DOM implementations (one of the FourThought # DOMs, perhaps?). if hasattr(node, '_call_user_data_handler'): node._call_user_data_handler(operation, node, clone) return clone def _nssplit(qualifiedName): fields = qualifiedName.split(':', 1) if len(fields) == 2: return fields else: return (None, fields[0]) def _get_StringIO(): # we can't use cStringIO since it doesn't support Unicode strings from StringIO import StringIO return StringIO() def _do_pulldom_parse(func, args, kwargs): events = apply(func, args, kwargs) toktype, rootNode = events.getEvent() events.expandNode(rootNode) events.clear() return rootNode def parse(file, parser=None, bufsize=None): """Parse a file into a DOM by filename or file object.""" if parser is None and not bufsize: from xml.dom import expatbuilder return expatbuilder.parse(file) else: from xml.dom import pulldom return _do_pulldom_parse(pulldom.parse, (file,), {'parser': parser, 'bufsize': bufsize}) def parseString(string, parser=None): """Parse a file into a DOM from a string.""" if parser is None: from xml.dom import expatbuilder return expatbuilder.parseString(string) else: from xml.dom import pulldom return _do_pulldom_parse(pulldom.parseString, (string,), {'parser': parser}) def getDOMImplementation(features=None): if features: if isinstance(features, StringTypes): features = domreg._parse_feature_string(features) for f, v in features: if not Document.implementation.hasFeature(f, v): return None return Document.implementation PyXML-0.8.2/xml/dom/minitraversal.py0100644000076400001440000000237207534565153016542 0ustar martinusers"""A DOM implementation that offers traversal and ranges on top of minidom, using the 4DOM traversal implementation.""" import minidom class DOMImplementation(minidom.DOMImplementation): # Augment the features table instead of duplicating the logic in # hasFeature(). _features = minidom.DOMImplementation._features + [ ("traversal", "1.0"), ("traversal", "2.0"), ("traversal", None), ("range", "1.0"), ("range", "2.0"), ("range", None), ] def _create_document(self): return Document() class Document(minidom.Document): implementation = DOMImplementation() def createNodeIterator(self, root, whatToShow, filter, entityReferenceExpansion): from xml.dom.NodeIterator import NodeIterator return NodeIterator(root, whatToShow, filter, entityReferenceExpansion) def createTreeWalker(self, root, whatToShow, filter, entityReferenceExpansion): from TreeWalker import TreeWalker return TreeWalker(root, whatToShow, filter, entityReferenceExpansion) def createRange(self): from Range import Range return Range(self) def getDOMImplementation(): return Document.implementation PyXML-0.8.2/xml/dom/pulldom.py0100644000076400001440000002731207452522430015325 0ustar martinusersimport xml.sax import xml.sax.handler import types try: _StringTypes = [types.StringType, types.UnicodeType] except AttributeError: _StringTypes = [types.StringType] START_ELEMENT = "START_ELEMENT" END_ELEMENT = "END_ELEMENT" COMMENT = "COMMENT" START_DOCUMENT = "START_DOCUMENT" END_DOCUMENT = "END_DOCUMENT" PROCESSING_INSTRUCTION = "PROCESSING_INSTRUCTION" IGNORABLE_WHITESPACE = "IGNORABLE_WHITESPACE" CHARACTERS = "CHARACTERS" class PullDOM(xml.sax.ContentHandler): _locator = None document = None def __init__(self, documentFactory=None): from xml.dom import XML_NAMESPACE self.documentFactory = documentFactory self.firstEvent = [None, None] self.lastEvent = self.firstEvent self.elementStack = [] self.push = self.elementStack.append try: self.pop = self.elementStack.pop except AttributeError: # use class' pop instead pass self._ns_contexts = [{XML_NAMESPACE:'xml'}] # contains uri -> prefix dicts self._current_context = self._ns_contexts[-1] self.pending_events = [] def pop(self): result = self.elementStack[-1] del self.elementStack[-1] return result def setDocumentLocator(self, locator): self._locator = locator def startPrefixMapping(self, prefix, uri): if not hasattr(self, '_xmlns_attrs'): self._xmlns_attrs = [] self._xmlns_attrs.append((prefix or 'xmlns', uri)) self._ns_contexts.append(self._current_context.copy()) self._current_context[uri] = prefix or None def endPrefixMapping(self, prefix): self._current_context = self._ns_contexts.pop() def startElementNS(self, name, tagName , attrs): # Retrieve xml namespace declaration attributes. xmlns_uri = 'http://www.w3.org/2000/xmlns/' xmlns_attrs = getattr(self, '_xmlns_attrs', None) if xmlns_attrs is not None: for aname, value in xmlns_attrs: attrs._attrs[(xmlns_uri, aname)] = value self._xmlns_attrs = [] uri, localname = name if uri: # When using namespaces, the reader may or may not # provide us with the original name. If not, create # *a* valid tagName from the current context. if tagName is None: prefix = self._current_context[uri] if prefix: tagName = prefix + ":" + localname else: tagName = localname if self.document: node = self.document.createElementNS(uri, tagName) else: node = self.buildDocument(uri, tagName) else: # When the tagname is not prefixed, it just appears as # localname if self.document: node = self.document.createElement(localname) else: node = self.buildDocument(None, localname) for aname,value in attrs.items(): a_uri, a_localname = aname if a_uri == xmlns_uri: if a_localname == 'xmlns': qname = a_localname else: qname = 'xmlns:' + a_localname attr = self.document.createAttributeNS(a_uri, qname) node.setAttributeNodeNS(attr) elif a_uri: prefix = self._current_context[a_uri] if prefix: qname = prefix + ":" + a_localname else: qname = a_localname attr = self.document.createAttributeNS(a_uri, qname) node.setAttributeNodeNS(attr) else: attr = self.document.createAttribute(a_localname) node.setAttributeNode(attr) attr.value = value self.lastEvent[1] = [(START_ELEMENT, node), None] self.lastEvent = self.lastEvent[1] self.push(node) def endElementNS(self, name, tagName): self.lastEvent[1] = [(END_ELEMENT, self.pop()), None] self.lastEvent = self.lastEvent[1] def startElement(self, name, attrs): if self.document: node = self.document.createElement(name) else: node = self.buildDocument(None, name) for aname,value in attrs.items(): attr = self.document.createAttribute(aname) attr.value = value node.setAttributeNode(attr) self.lastEvent[1] = [(START_ELEMENT, node), None] self.lastEvent = self.lastEvent[1] self.push(node) def endElement(self, name): self.lastEvent[1] = [(END_ELEMENT, self.pop()), None] self.lastEvent = self.lastEvent[1] def comment(self, s): if self.document: node = self.document.createComment(s) self.lastEvent[1] = [(COMMENT, node), None] self.lastEvent = self.lastEvent[1] else: event = [(COMMENT, s), None] self.pending_events.append(event) def processingInstruction(self, target, data): if self.document: node = self.document.createProcessingInstruction(target, data) self.lastEvent[1] = [(PROCESSING_INSTRUCTION, node), None] self.lastEvent = self.lastEvent[1] else: event = [(PROCESSING_INSTRUCTION, target, data), None] self.pending_events.append(event) def ignorableWhitespace(self, chars): node = self.document.createTextNode(chars) self.lastEvent[1] = [(IGNORABLE_WHITESPACE, node), None] self.lastEvent = self.lastEvent[1] def characters(self, chars): node = self.document.createTextNode(chars) self.lastEvent[1] = [(CHARACTERS, node), None] self.lastEvent = self.lastEvent[1] def startDocument(self): if self.documentFactory is None: import xml.dom.minidom self.documentFactory = xml.dom.minidom.Document.implementation def buildDocument(self, uri, tagname): # Can't do that in startDocument, since we need the tagname # XXX: obtain DocumentType node = self.documentFactory.createDocument(uri, tagname, None) self.document = node self.lastEvent[1] = [(START_DOCUMENT, node), None] self.lastEvent = self.lastEvent[1] self.push(node) # Put everything we have seen so far into the document for e in self.pending_events: if e[0][0] == PROCESSING_INSTRUCTION: _,target,data = e[0] n = self.document.createProcessingInstruction(target, data) e[0] = (PROCESSING_INSTRUCTION, n) elif e[0][0] == COMMENT: n = self.document.createComment(e[0][1]) e[0] = (COMMENT, n) else: raise AssertionError("Unknown pending event ",e[0][0]) self.lastEvent[1] = e self.lastEvent = e self.pending_events = None return node.firstChild def endDocument(self): self.lastEvent[1] = [(END_DOCUMENT, self.document), None] self.pop() def clear(self): "clear(): Explicitly release parsing structures" self.document = None class ErrorHandler: def warning(self, exception): print exception def error(self, exception): raise exception def fatalError(self, exception): raise exception class DOMEventStream: def __init__(self, stream, parser, bufsize): self.stream = stream self.parser = parser self.bufsize = bufsize if not hasattr(self.parser, 'feed'): self.getEvent = self._slurp self.reset() def reset(self): self.pulldom = PullDOM() # This content handler relies on namespace support self.parser.setFeature(xml.sax.handler.feature_namespaces, 1) self.parser.setContentHandler(self.pulldom) def __getitem__(self, pos): rc = self.getEvent() if rc: return rc raise IndexError def next(self): rc = self.getEvent() if rc: return rc raise StopIteration def __iter__(self): return self def expandNode(self, node): event = self.getEvent() parents = [node] while event: token, cur_node = event if cur_node is node: return if token != END_ELEMENT: parents[-1].appendChild(cur_node) if token == START_ELEMENT: parents.append(cur_node) elif token == END_ELEMENT: del parents[-1] event = self.getEvent() def getEvent(self): # use IncrementalParser interface, so we get the desired # pull effect if not self.pulldom.firstEvent[1]: self.pulldom.lastEvent = self.pulldom.firstEvent while not self.pulldom.firstEvent[1]: buf = self.stream.read(self.bufsize) if not buf: self.parser.close() return None self.parser.feed(buf) rc = self.pulldom.firstEvent[1][0] self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1] return rc def _slurp(self): """ Fallback replacement for getEvent() using the standard SAX2 interface, which means we slurp the SAX events into memory (no performance gain, but we are compatible to all SAX parsers). """ self.parser.parse(self.stream) self.getEvent = self._emit return self._emit() def _emit(self): """ Fallback replacement for getEvent() that emits the events that _slurp() read previously. """ rc = self.pulldom.firstEvent[1][0] self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1] return rc def clear(self): """clear(): Explicitly release parsing objects""" self.pulldom.clear() del self.pulldom self.parser = None self.stream = None class SAX2DOM(PullDOM): def startElementNS(self, name, tagName , attrs): PullDOM.startElementNS(self, name, tagName, attrs) curNode = self.elementStack[-1] parentNode = self.elementStack[-2] parentNode.appendChild(curNode) def startElement(self, name, attrs): PullDOM.startElement(self, name, attrs) curNode = self.elementStack[-1] parentNode = self.elementStack[-2] parentNode.appendChild(curNode) def processingInstruction(self, target, data): PullDOM.processingInstruction(self, target, data) node = self.lastEvent[0][1] parentNode = self.elementStack[-1] parentNode.appendChild(node) def ignorableWhitespace(self, chars): PullDOM.ignorableWhitespace(self, chars) node = self.lastEvent[0][1] parentNode = self.elementStack[-1] parentNode.appendChild(node) def characters(self, chars): PullDOM.characters(self, chars) node = self.lastEvent[0][1] parentNode = self.elementStack[-1] parentNode.appendChild(node) default_bufsize = (2 ** 14) - 20 def parse(stream_or_string, parser=None, bufsize=None): if bufsize is None: bufsize = default_bufsize if type(stream_or_string) in _StringTypes: stream = open(stream_or_string) else: stream = stream_or_string if not parser: parser = xml.sax.make_parser() return DOMEventStream(stream, parser, bufsize) def parseString(string, parser=None): try: from cStringIO import StringIO except ImportError: from StringIO import StringIO bufsize = len(string) buf = StringIO(string) if not parser: parser = xml.sax.make_parser() return DOMEventStream(buf, parser, bufsize) PyXML-0.8.2/xml/dom/xmlbuilder.py0100644000076400001440000003014007536326577016032 0ustar martinusers"""Implementation of the DOM Level 3 'LS-Load' feature.""" import copy import xml.dom from xml.dom.minicompat import * from xml.dom.NodeFilter import NodeFilter __all__ = ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"] class Options: """Features object that has variables set for each DOMBuilder feature. The DOMBuilder class uses an instance of this class to pass settings to the ExpatBuilder class. """ # Note that the DOMBuilder class in LoadSave constrains which of these # values can be set using the DOM Level 3 LoadSave feature. namespaces = 1 namespace_declarations = True validation = False external_parameter_entities = True external_general_entities = True external_dtd_subset = True validate_if_schema = False validate = False datatype_normalization = False create_entity_ref_nodes = True entities = True whitespace_in_element_content = True cdata_sections = True comments = True charset_overrides_xml_encoding = True infoset = False supported_mediatypes_only = False errorHandler = None filter = None class DOMBuilder: entityResolver = None errorHandler = None filter = None ACTION_REPLACE = 1 ACTION_APPEND_AS_CHILDREN = 2 ACTION_INSERT_AFTER = 3 ACTION_INSERT_BEFORE = 4 _legal_actions = (ACTION_REPLACE, ACTION_APPEND_AS_CHILDREN, ACTION_INSERT_AFTER, ACTION_INSERT_BEFORE) def __init__(self): self._options = Options() def _get_entityResolver(self): return self.entityResolver def _set_entityResolver(self, entityResolver): self.entityResolver = entityResolver def _get_errorHandler(self): return self.errorHandler def _set_errorHandler(self, errorHandler): self.errorHandler = errorHandler def _get_filter(self): return self.filter def _set_filter(self, filter): self.filter = filter def setFeature(self, name, state): if self.supportsFeature(name): state = state and 1 or 0 try: settings = self._settings[(_name_xform(name), state)] except KeyError: raise xml.dom.NotSupportedErr( "unsupported feature: " + `name`) else: for name, value in settings: setattr(self._options, name, value) else: raise xml.dom.NotFoundErr("unknown feature: " + repr(name)) def supportsFeature(self, name): return hasattr(self._options, _name_xform(name)) def canSetFeature(self, name, state): key = (_name_xform(name), state and 1 or 0) return self._settings.has_key(key) # This dictionary maps from (feature,value) to a list of # (option,value) pairs that should be set on the Options object. # If a (feature,value) setting is not in this dictionary, it is # not supported by the DOMBuilder. # _settings = { ("namespace_declarations", 0): [ ("namespace_declarations", 0)], ("namespace_declarations", 1): [ ("namespace_declarations", 1)], ("validation", 0): [ ("validation", 0)], ("external_general_entities", 0): [ ("external_general_entities", 0)], ("external_general_entities", 1): [ ("external_general_entities", 1)], ("external_parameter_entities", 0): [ ("external_parameter_entities", 0)], ("external_parameter_entities", 1): [ ("external_parameter_entities", 1)], ("validate_if_schema", 0): [ ("validate_if_schema", 0)], ("create_entity_ref_nodes", 0): [ ("create_entity_ref_nodes", 0)], ("create_entity_ref_nodes", 1): [ ("create_entity_ref_nodes", 1)], ("entities", 0): [ ("create_entity_ref_nodes", 0), ("entities", 0)], ("entities", 1): [ ("entities", 1)], ("whitespace_in_element_content", 0): [ ("whitespace_in_element_content", 0)], ("whitespace_in_element_content", 1): [ ("whitespace_in_element_content", 1)], ("cdata_sections", 0): [ ("cdata_sections", 0)], ("cdata_sections", 1): [ ("cdata_sections", 1)], ("comments", 0): [ ("comments", 0)], ("comments", 1): [ ("comments", 1)], ("charset_overrides_xml_encoding", 0): [ ("charset_overrides_xml_encoding", 0)], ("charset_overrides_xml_encoding", 1): [ ("charset_overrides_xml_encoding", 1)], ("infoset", 0): [], ("infoset", 1): [ ("namespace_declarations", 0), ("validate_if_schema", 0), ("create_entity_ref_nodes", 0), ("entities", 0), ("cdata_sections", 0), ("datatype_normalization", 1), ("whitespace_in_element_content", 1), ("comments", 1), ("charset_overrides_xml_encoding", 1)], ("supported_mediatypes_only", 0): [ ("supported_mediatypes_only", 0)], ("namespaces", 0): [ ("namespaces", 0)], ("namespaces", 1): [ ("namespaces", 1)], } def getFeature(self, name): xname = _name_xform(name) try: return getattr(self._options, xname) except AttributeError: if name == "infoset": options = self._options return (options.datatype_normalization and options.whitespace_in_element_content and options.comments and options.charset_overrides_xml_encoding and not (options.namespace_declarations or options.validate_if_schema or options.create_entity_ref_nodes or options.entities or options.cdata_sections)) raise xml.dom.NotFoundErr("feature %s not known" % repr(name)) def parseURI(self, uri): if self.entityResolver: input = self.entityResolver.resolveEntity(None, uri) else: input = DOMEntityResolver().resolveEntity(None, uri) return self.parse(input) def parse(self, input): options = copy.copy(self._options) options.filter = self.filter options.errorHandler = self.errorHandler fp = input.byteStream if fp is None and options.systemId: import urllib2 fp = urllib2.urlopen(input.systemId) return self._parse_bytestream(fp, options) def parseWithContext(self, input, cnode, action): if action not in self._legal_actions: raise ValueError("not a legal action") raise NotImplementedError("Haven't written this yet...") def _parse_bytestream(self, stream, options): import xml.dom.expatbuilder builder = xml.dom.expatbuilder.makeBuilder(options) return builder.parseFile(stream) def _name_xform(name): return name.lower().replace('-', '_') class DOMEntityResolver(NewStyle): __slots__ = '_opener', def resolveEntity(self, publicId, systemId): assert systemId is not None source = DOMInputSource() source.publicId = publicId source.systemId = systemId source.byteStream = self._get_opener().open(systemId) # determine the encoding if the transport provided it source.encoding = self._guess_media_encoding(source) # determine the base URI is we can import posixpath, urlparse parts = urlparse.urlparse(systemId) scheme, netloc, path, params, query, fragment = parts # XXX should we check the scheme here as well? if path and not path.endswith("/"): path = posixpath.dirname(path) + "/" parts = scheme, netloc, path, params, query, fragment source.baseURI = urlparse.urlunparse(parts) return source def _get_opener(self): try: return self._opener except AttributeError: self._opener = self._create_opener() return self._opener def _create_opener(self): import urllib2 return urllib2.build_opener() def _guess_media_encoding(self, source): info = source.byteStream.info() if info.has_key("Content-Type"): for param in info.getplist(): if param.startswith("charset="): return param.split("=", 1)[1].lower() class DOMInputSource(NewStyle): __slots__ = ('byteStream', 'characterStream', 'stringData', 'encoding', 'publicId', 'systemId', 'baseURI') def __init__(self): self.byteStream = None self.characterStream = None self.stringData = None self.encoding = None self.publicId = None self.systemId = None self.baseURI = None def _get_byteStream(self): return self.byteStream def _set_byteStream(self, byteStream): self.byteStream = byteStream def _get_characterStream(self): return self.characterStream def _set_characterStream(self, characterStream): self.characterStream = characterStream def _get_stringData(self): return self.stringData def _set_stringData(self, data): self.stringData = data def _get_encoding(self): return self.encoding def _set_encoding(self, encoding): self.encoding = encoding def _get_publicId(self): return self.publicId def _set_publicId(self, publicId): self.publicId = publicId def _get_systemId(self): return self.systemId def _set_systemId(self, systemId): self.systemId = systemId def _get_baseURI(self): return self.baseURI def _set_baseURI(self, uri): self.baseURI = uri class DOMBuilderFilter: """Element filter which can be used to tailor construction of a DOM instance. """ # There's really no need for this class; concrete implementations # should just implement the endElement() and startElement() # methods as appropriate. Using this makes it easy to only # implement one of them. FILTER_ACCEPT = 1 FILTER_REJECT = 2 FILTER_SKIP = 3 FILTER_INTERRUPT = 4 whatToShow = NodeFilter.SHOW_ALL def _get_whatToShow(self): return self.whatToShow def acceptNode(self, element): return self.FILTER_ACCEPT def startContainer(self, element): return self.FILTER_ACCEPT del NodeFilter class DocumentLS: """Mixin to create documents that conform to the load/save spec.""" async = False def _get_async(self): return False def _set_async(self, async): if async: raise xml.dom.NotSupportedErr( "asynchronous document loading is not supported") def abort(self): # What does it mean to "clear" a document? Does the # documentElement disappear? raise NotImplementedError( "haven't figured out what this means yet") def load(self, uri): raise NotImplementedError("haven't written this yet") def loadXML(self, source): raise NotImplementedError("haven't written this yet") def saveXML(self, snode): if snode is None: snode = self elif snode.ownerDocument is not self: raise xml.dom.WrongDocumentErr() return snode.toxml() class DOMImplementationLS: MODE_SYNCHRONOUS = 1 MODE_ASYNCHRONOUS = 2 def createDOMBuilder(self, mode, schemaType): if schemaType is not None: raise xml.dom.NotSupportedErr( "schemaType not yet supported") if mode == self.MODE_SYNCHRONOUS: return DOMBuilder() if mode == self.MODE_ASYNCHRONOUS: raise xml.dom.NotSupportedErr( "asynchronous builders are not supported") raise ValueError("unknown value for mode") def createDOMWriter(self): raise NotImplementedError( "the writer interface hasn't been written yet!") def createDOMInputSource(self): return DOMInputSource() PyXML-0.8.2/xml/marshal/0040755000076400001440000000000007614726123014152 5ustar martinusersPyXML-0.8.2/xml/marshal/__init__.py0100644000076400001440000000054707507520271016263 0ustar martinusers"""Converting Python objects to XML and back again. xml.marshal.generic Marshals simple Python data types into a custom XML format. The Marshaller and Unmarshaller classes can be subclassed in order to implement marshalling into a different XML DTD. xml.marshal.wddx Marshals Python data types into the WDDX DTD. """ __all__ = ['generic', 'wddx'] PyXML-0.8.2/xml/marshal/generic.py0100644000076400001440000004757007534565153016157 0ustar martinusers# Generic class for marshalling simple Python data types into an XML-based # format. The interface is the same as the built-in module of the # same name, with four functions: # dump(value, file), load(file) # dumps(value), loads(string) from types import * import string from xml.sax import saxlib, saxexts # Basic marshaller class, customizable by overriding it and # changing various attributes and methods. # It's also used as a SAX handler, which may be a good idea but may # also be a stupid hack. def version_independent_cmp(a,b): ta = type(a) tb = type(b) if ta is not tb: return cmp(ta.__name__, tb.__name__) return cmp(a,b) class Marshaller(saxlib.HandlerBase): # XML version and DOCTYPE declaration PROLOGUE = '' DTD = "" # Names of elements. These are specified as class attributes # because simple things like integers are often handled in the # same way, and only the element names change. tag_root = 'marshal' tag_int = 'int' tag_float = 'float' tag_long = 'long' tag_string = 'string' tag_tuple = 'tuple' tag_list = 'list' tag_dictionary = 'dictionary' tag_complex = 'complex' tag_reference = 'reference' tag_code = 'code' tag_none = 'none' tag_instance = 'object' # The four basic functions that form the caller's interface def dump(self, value, file): "Write the value on the open file" dict = {'id': 1} L = [self.PROLOGUE + self.DTD] + self.m_root(value, dict) # XXX should this just loop through the L and call file.write # for each item? file.write(string.join(L, "")) def dumps(self, value): "Marshal value, returning the resulting string" dict = {'id': 1} # now uses m_root for proper root element handling L = [self.PROLOGUE + self.DTD] + self.m_root(value, dict) return string.join(L, "") # IMPORTANT NOTE: The proper entry point to marshal # an object is m_root; the public marshalling # methods dump and dumps use m_root(). # # This function gets the name of the # type of the object being marshalled, and calls the # m_ method. This method must return a list of strings, # which will be returned to the caller. # # (This function can be called recursively, so it shouldn't # return just a single. The top-level caller will perform a # single string.join to get the resulting XML document. # # dict is a dictionary whose keys are used to store the IDs of # objects that have already been marshalled, in order to allow # writing a reference to them. # # XXX there should be some way to disable the automatic generation of # references to already-marshalled objects def _marshal(self, value, dict): t = type(value) i = str(id(value)) if dict.has_key(i): return self.m_reference(value, dict) else: if type(value) is LongType: meth = 'm_long' else: meth = "m_" + type(value).__name__ return getattr(self, meth)(value, dict) # Utility function, used for types that aren't implemented def m_unimplemented(self, value, dict): raise ValueError, ("Marshalling of object " + repr(value) + " unimplemented or not supported in this DTD") # The real entry point for marshalling, to handle properly # and cleanly any root tag or tags necessary for the marshalled # output. def m_root(self, value, dict): name = self.tag_root L = ['<%s>' % name] + self._marshal(value,dict) + ['' % name] return L # # All the generic marshalling functions for various Python types # def m_reference(self, value, dict): # This object has already been marshalled, so # emit a reference element. i = dict[str(id(value))] return ['<' + self.tag_reference + ' id="i%s"/>' % (i,)] def m_string(self, value, dict): name = self.tag_string L = ['<' + name + '>'] s = str(value) if '&' in s or '>' in s or '<' in s: s = string.replace(s, '&', '&') s = string.replace(s, '<', '<') s = string.replace(s, '>', '>') L.append(s) L.append('') return L # Since Python 2.2, the string type has a name of 'str' # To avoid having to rewrite all classes that implement m_string # we delegate m_str to m_string. def m_str(self, value, dict): return self.m_string(value, dict) def m_int(self, value, dict): name = self.tag_int return ['<' + name + '>' + str(value) + ''] def m_float(self, value, dict): name = self.tag_float return ['<' + name + '>' + str(value) + ''] def m_long(self, value, dict): name = self.tag_long value = str(value) if value[-1] == 'L': # some Python versions append and 'L' value = value[:-1] return ['<' + name + '>' + str(value) + ''] def m_tuple(self, value, dict): name = self.tag_tuple L = [] L.append( '<' + name + '>') for elem in value: L = L + self._marshal(elem, dict) L.append('') return L def m_list(self, value, dict): name = self.tag_list L = [] dict['id'] = dict['id'] + 1 i = str(dict['id']) dict[str(id(value))] = i dict[i] = value L.append('<' + name + ' id="i%s">' % i) for elem in value: L = L + self._marshal(elem, dict) L.append('') return L def m_dictionary(self, value, dict): name = self.tag_dictionary L = [] dict['id'] = dict['id'] + 1 i = str(dict['id']) dict[str(id(value))] = i dict[i] = value L.append('<' + name + ' id="i%s">' % (i,)) items = value.items() # Sort the items to allow reproducable results across Python # versions items.sort(version_independent_cmp) for key, v in items: L = L + self._marshal(key, dict) + self._marshal(v, dict) L.append('') return L # Python 2.2 renames dictionary to dict. def m_dict(self, value, dict): return self.m_dictionary(value, dict) def m_None(self, value, dict): return ['<' + self.tag_none + '/>'] # Python 2.2 renamed the type of None to NoneTye def m_NoneType(self, value, dict): return self.m_None(value, dict) def m_complex(self, value, dict): name = self.tag_complex return ['<' + name + '>' + str(value.real) + ' ' + str(value.imag) + ''] def m_code(self, value, dict): name = self.tag_code L = [] # The full information about code objects is only available # from the C level, so we'll use the built-in marshal module # to convert the code object into a string, and include it in # the HTML. import marshal, base64 L.append('') s = marshal.dumps(value) s = base64.encodestring(s) L.append(s) L.append('') return L def m_instance(self, value, dict): name = self.tag_instance L = [] dict['id'] = dict['id'] + 1 i = str(dict['id']) dict[str(id(value))] = i dict[i] = value cls = value.__class__ L.append('<%s id="i%s" module="%s" class="%s">' % (name, i, cls.__module__, cls.__name__)) # Check for pickle's __getinitargs__ if hasattr(value, '__getinitargs__'): args = value.__getinitargs__() len(args) # XXX Assert it's a sequence else: args = () L = L + self._marshal(args, dict) # Check for pickle's __getstate__ function try: getstate = value.__getstate__ except AttributeError: stuff = value.__dict__ else: stuff = getstate() L = L + self._marshal(stuff, dict) L.append('' % name) return L # These values are used as markers in the stack when unmarshalling # one of the structures below. When a tag is encountered, for # example, the TUPLE object is pushed onto the stack, and further # objects are processed. When the tag is found, the code # looks back into the stack until TUPLE is found; all the higher # objects are then collected into a tuple. Ditto for lists... TUPLE = {} LIST = {} DICT = {} class Unmarshaller(saxlib.HandlerBase): # This dictionary maps element names to the names of starting and ending # functions to call when unmarshalling them. My convention is to # name them um_start_foo and um_end_foo, but do whatever you like. unmarshal_meth = { 'marshal': ('um_start_root', None), 'int': ('um_start_int', 'um_end_int'), 'float': ('um_start_float', 'um_end_float'), 'long': ('um_start_long', 'um_end_long'), 'string': ('um_start_string', 'um_end_string'), 'tuple': ('um_start_tuple', 'um_end_tuple'), 'list': ('um_start_list', 'um_end_list'), 'dictionary': ('um_start_dictionary', 'um_end_dictionary'), 'complex': ('um_start_complex', 'um_end_complex'), 'reference': ('um_start_reference', None), 'code': ('um_start_code', 'um_end_code'), 'none': ('um_start_none', 'um_end_none'), 'object': ('um_start_instance', 'um_end_instance') } def __init__(self): # Find the named methods, and convert them to the actual # method object. d = {} for key, (sm, em) in self.unmarshal_meth.items(): if sm is not None: sm = getattr(self, sm) if em is not None: em = getattr(self, em) d[key] = sm,em self.unmarshal_meth = d self._clear() def _clear(self): """ Protected method to (re)initialize the object into a steady state. Performed by __init__ and _load. """ self.data_stack = [] self.dict = {} self.accumulating_chars = 0 def load(self, file): "Unmarshal one value, reading it from a file-like object" # Instantiate a new object; unmarshalling isn't thread-safe # because it modifies attributes on the object. m = self.__class__() return m._load(file) def loads(self, string): "Unmarshal one value from a string" # Instantiate a new object; unmarshalling isn't thread-safe # because it modifies attributes on the object. m = self.__class__() import StringIO file = StringIO.StringIO(string) return m._load(file) # Basic unmarshalling routine; it creates a SAX XML parser, # registers self as the SAX handler, parses it, and returns # the only thing on the data stack. def _load(self, file): "Read one value from the open file" p = saxexts.make_parser() p.setDocumentHandler(self) p.parseFile(file) assert len(self.data_stack) == 1 # leave the instance in a steady state result = self.data_stack[0] self._clear() return result # find_class() is copied from pickle.py def find_class(self, module, name): env = {} try: exec 'from %s import %s' % (module, name) in env except ImportError: raise SystemError, \ "Failed to import class %s from module %s" % \ (name, module) return env[name] # SAXlib handler methods. # # Unmarshalling is done by creating a stack (a Python list) on # starting the root element. When the .character() method may be # called, the last item on the stack must be a list; the # characters will be appended to that list. # # The starting methods must, at minimum, push a single list onto # the stack, as um_start_generic does. # # The ending methods can then do string.join() on the list on the # top of the stack, and convert it to whatever Python type is # required. The resulting Python object then replaces the list on # the top of the stack. # def startElement(self, name, attrs): # Call the start unmarshalling method, if specified sm, em = self.unmarshal_meth[name] if sm is not None: return sm(name,attrs) def characters(self, ch, start, length): if self.accumulating_chars: self.data_stack[-1].append(ch[start:start+length]) def endElement(self, name): # Call the ending method sm, em = self.unmarshal_meth[name] if em is not None: em(name) # um_start_root is really a "sentinel" method # which ensures that the unmarshaller is in a steady, # "empty" state. def um_start_root(self, name, attrs): if self.dict or self.data_stack: raise ValueError, \ "root element %s found elsewhere than root" \ % repr(name) def um_start_reference(self, name, attrs): assert attrs.has_key('id') id = attrs['id'] assert self.dict.has_key(id) self.data_stack.append(self.dict[id]) def um_start_generic(self, name, attrs): self.data_stack.append([]) self.accumulating_chars = 1 um_start_float = um_start_long = um_start_string = um_start_generic um_start_complex = um_start_code = um_start_none = um_start_generic um_start_int = um_start_generic def um_end_string(self, name): ds = self.data_stack # might need to convert unicode string to byte string ds[-1] = str(string.join(ds[-1], "")) self.accumulating_chars = 0 def um_end_int(self, name): ds = self.data_stack ds[-1] = string.join(ds[-1], "") ds[-1] = int(ds[-1]) self.accumulating_chars = 0 def um_end_long(self, name): ds = self.data_stack ds[-1] = string.join(ds[-1], "") ds[-1] = long(ds[-1]) self.accumulating_chars = 0 def um_end_float(self, name): ds = self.data_stack ds[-1] = string.join(ds[-1], "") ds[-1] = float(ds[-1]) self.accumulating_chars = 0 def um_end_none(self, name): ds = self.data_stack ds[-1] = None self.accumulating_chars = 0 def um_end_complex(self, name): ds = self.data_stack c = string.join(ds[-1], "") c = string.split(c) c = float(c[0]) + float(c[1])*1j ds[-1:] = [c] self.accumulating_chars = 0 def um_end_code(self, name): import marshal, base64 ds = self.data_stack s = string.join(ds[-1], "") s = base64.decodestring(s) ds[-1] = marshal.loads(s) self.accumulating_chars = 0 # Trickier stuff: dictionaries, lists, tuples. def um_start_list(self, name, attrs): self.data_stack.append(LIST) L = [] if attrs.has_key('id'): id = attrs[ 'id'] self.dict[id] = L self.data_stack.append(L) def um_end_list(self, name): ds = self.data_stack for index in range(len(ds)-1, -1, -1): if ds[index] is LIST: break assert index != -1 L = ds[index + 1] L[:] = ds[index + 2:len(ds)] ds[index:] = [L] def um_start_tuple(self, name, attrs): self.data_stack.append(TUPLE) def um_end_tuple(self, name): ds = self.data_stack for index in range(len(ds) - 1, -1, -1): if ds[index] is TUPLE: break assert index != -1 t = tuple(ds[index+1:len(ds)]) ds[index:] = [t] # Dictionary elements, in the generic format, must always have an # even number of objects contained inside them. These objects are # treated as alternating keys and values. def um_start_dictionary(self, name, attrs): self.data_stack.append(DICT) d = {} if attrs.has_key('id'): id = attrs['id'] self.dict[id] = d self.data_stack.append(d) def um_end_dictionary(self, name): ds = self.data_stack for index in range(len(ds) - 1, -1, -1): if ds[index] is DICT: break assert index != -1 d = ds[index + 1] for i in range(index + 2, len(ds), 2): key = ds[i] value = ds[i+1] d[key] = value ds[index:] = [d] def um_start_instance(self, name, attrs): module = attrs['module'] classname = attrs['class'] value = _EmptyClass() if attrs.has_key('id'): id = attrs['id'] self.dict[id] = value self.data_stack.append(value) self.data_stack.append(module) self.data_stack.append(classname) def um_end_instance(self, name): value, module, classname, initargs, dict = self.data_stack[-5:] klass = self.find_class(module, classname) instantiated = 0 if (not initargs and type(klass) is ClassType and not hasattr(klass, "__getinitargs__")): value.__class__ = klass instantiated = 1 if not instantiated: try: # Uh oh... we need to call the constructor with the initial # arguments, but we also have to preserve the identity of # the object, to keep recursive objects right. v2 = apply(klass, initargs) except TypeError, err: raise TypeError, "in constructor for %s: %s" % ( klass.__name__, str(err)), sys.exc_info()[2] else: for k,v in v2.__dict__.items(): setattr(value, k, v) # Now set the object's attributes from the marshalled dictionary for k,v in dict.items(): setattr(value, k, v) self.data_stack[-5:] = [value] # Helper class for instance unmarshalling class _EmptyClass: pass # module functions for procedural use of module _m = Marshaller() dump = _m.dump dumps = _m.dumps _um = Unmarshaller() load = _um.load loads = _um.loads del _m, _um def test(load, loads, dump, dumps, test_values, do_assert=1): # Try all the above bits of data import StringIO for item in test_values: s = dumps(item) print s output = loads(s) # Try it from a file file = StringIO.StringIO() dump(item, file) file.seek(0) output2 = load(file) if do_assert: assert item == output and item == output2 and output == output2 # Classes used in the test suite class _A: def __repr__(self): return '' class _B: def __repr__(self): return '' def runtests(): print "Testing XML marshalling..." L = [None, 1, pow(2, 123L), 19.72, 1+5j, "here is a string & a ", (1, 2, 3), ['alpha', 'beta', 'gamma'], {'key': 'value', 1: 2} ] test(load, loads, dump, dumps, L) instance = _A() ; instance.subobject = _B() instance.subobject.list=[None, 1, pow(2, 123L), 19.72, 1+5j, "here is a string & a "] instance.self = instance L = [instance] test(load, loads, dump, dumps, L, do_assert=0) recursive_list = [None, 1, pow(3, 65L), {1: 'spam', 2: 'eggs'}, '', 1+5j] recursive_list.append(recursive_list) test(load, loads, dump, dumps, [recursive_list], do_assert=0) # Try unmarshalling XML with extra harmless whitespace (as if it was # pretty-printed) output = loads(""" 1.0 abc """) assert output == (1.0, 'abc', []) if __name__ == '__main__': runtests() PyXML-0.8.2/xml/marshal/wddx.py0100644000076400001440000002351107555273110015466 0ustar martinusersfrom generic import * """WDDX marshalling""" # WDDX marshalling can be either "strict", in which Python objects # with no good WDDX equivalent cause a marshalling exception, or # "loose", in which WDDX takes extra steps to prevent marshalling # exception by finding the closest match for a Python object. # # If the module variable STRICT is true, any marshalling instances # created will use strict marshalling rules. If STRICT is false, # any marshalling instances created will use loose rules. # Changing the value of STRICT affects any marshallers # subsequently created; previously created marshaller objects # will not change their behavior. # # By default, STRICT is false. This default setting allows WDDX # the most flexible behavior for naive users of the module. # # In the current implementation of "loose" marshalling, there are # very few differences with loose marshalling: # # 1) the None object becomes an empty element, # which is unmarshalled as the empty string "". # # 2) Tuples become elements, which are unmarshalled # as lists. # # 3) Instances which have a __wddx__ method will have the # result of calling that method used as the marshalling # value. (See _WDDX_METHOD below.) STRICT = 0 # Added _WDDX_METHOD, which names a special method for WDDX # marshalling. If an instance to be marshalled has this method # defined, it is called with no arguments and the return value is used # for marshalling. (The marshaller code in m_instance forbids # the return value to be an instance with its own special # WDDX method, to prevent recursive death.) # # This method is useful for user-defined classes whose instances # mimic the behavior of built-in types such as dictionaries or # lists. # # This special method is used only if STRICT is false. _WDDX_METHOD = '__wddx__' # WDDX has a Boolean type. We need to generate such variables, so # this defines a class representing a truth value, and then creates # TRUE and FALSE. class TruthValue: def __init__(self, value): if value: self.__dict__['value'] = 1 else: self.__dict__['value'] = 0 def __setattr__(self, item, value): raise TypeError, "TruthValue object is read-only" def __nonzero__(self): return self.value def __cmp__(self, other): return cmp(self.value, other) def __hash__(self): return hash(self.value) def __repr__(self): if self.value: return "" else: return "" TRUE = TruthValue(1) FALSE = TruthValue(0) RECORDSET = {} import UserDict class RecordSet(UserDict.UserDict): def __init__(self, fields, *lists): UserDict.UserDict.__init__(self) if len(fields) != len(lists): raise ValueError, "Number of fields and lists must be the same" for L in lists[1:]: if len(L) != len(lists[0]): raise ValueError, "Number of entries in each list must be the same" self.fields = fields for i in range(len(fields)): f = fields[i] self.data[f] = lists[i] class WDDXMarshaller(Marshaller): DTD = '' tag_root = 'wddxPacket' tag_float = tag_int = tag_long = 'number' tag_instance = 'boolean' wddx_version = "0.9" m_reference = m_complex = m_code = Marshaller.m_unimplemented def __init__(self, strict=None): if strict is None: self._strict = STRICT else: self._strict = strict def m_root(self, value, dict): L = ['<%s version="%s">' % (self.tag_root, self.wddx_version)] # add header L.append('
    ') L = L + self._marshal(value, dict) L.append('' % self.tag_root) return L def m_instance(self, value, dict): if isinstance(value, RecordSet): return self.m_recordset(value, dict) # allow any TruthValue instance, not just # the predefined helpful "constants"; else # why make the class? if isinstance(value, TruthValue): if value: return [''] else: return [''] # check for _WDDX_METHOD method, but prevent # recursive death if return value also has wddx method if not self._strict and hasattr(value, _WDDX_METHOD): newval = getattr(value, _WDDX_METHOD)() # newval may not have its own wddx method if hasattr(newval, _WDDX_METHOD): raise ValueError, \ "%s method of object %s may not " \ "return object having own %s method" % \ (_WDDX_METHOD, repr(value), _WDDX_METHOD) return self._marshal(newval, dict) self.m_unimplemented(value, dict) def m_recordset(self, value, dict): L = ['' % (len(value), string.join(value.fields, ','))] for f in value.fields: recs = value[f] L.append('' % f) for r in recs: L = L + self._marshal(r, dict) L.append('') L.append('') return L def m_list(self, value, dict): L = [] i = str(id(value)) dict[i] = 1 L.append('' % len(value)) for elem in value: L = L + self._marshal(elem, dict) L.append('') return L def m_tuple(self, value, dict): if self._strict: return self.m_unimplemented(value, dict) else: return self.m_list(value, dict) def m_None(self, value, dict): if self._strict: return self.m_unimplemented(value, dict) else: return self.m_string("", dict) def m_dictionary(self, value, dict): L = [] i = str(id(value)) dict[i] = 1 L.append('') items = value.items() # Sort the items so the order they're written in is # deterministic; this is only needed to make testing easier. items.sort() for key, v in items: L.append('' % key) L = L + self._marshal(v, dict) L.append('') L.append('') return L class WDDXUnmarshaller(Unmarshaller): unmarshal_meth = { 'wddxPacket': (None, None), 'data': ('um_start_root', None), 'header': (None, None), 'char': ('um_start_char', None), 'boolean': ('um_start_boolean', 'um_end_boolean'), 'number': ('um_start_number', 'um_end_number'), 'string': ('um_start_string', 'um_end_string'), 'array': ('um_start_list', 'um_end_list'), 'struct': ('um_start_dictionary', 'um_end_dictionary'), 'var': ('um_start_var', None), 'recordset': ('um_start_recordset', 'um_end_recordset'), 'field': ('um_start_field', 'um_end_field'), } def um_start_char(self, name, attrs): print self.data_stack[-1] self.data_stack[-1].append(str(chr(string.atoi(attrs['code'], 16)))) def um_start_boolean(self, name, attrs): v = attrs['value'] self.data_stack.append([v]) def um_end_boolean(self, name): ds = self.data_stack if ds[-1][0] == 'true': ds[-1] = TRUE else: ds[-1] = FALSE um_start_number = Unmarshaller.um_start_generic um_end_number = Unmarshaller.um_end_float def um_start_var(self, name, attrs): name = attrs['name'] self.data_stack.append(name) def um_start_recordset(self, name, attrs): fields = string.split(attrs['fieldNames'], ',') rowCount = int(attrs['rowCount']) self.data_stack.append(RECORDSET) self.data_stack.append((rowCount, fields)) def um_end_recordset(self, name): ds = self.data_stack for index in range(len(ds) - 1, -1, -1): if ds[index] is RECORDSET: break assert index!=-1 rowCount, fields = ds[index + 1] lists = [None] * len(fields) for i in range(index+2, len(ds), 2): field = ds[i] value = ds[i + 1] pos = fields.index(field) lists[pos] = value ds[index:] = [apply(RecordSet, tuple([fields]+lists))] def um_start_field(self, name, attrs): field = attrs['name'] self.data_stack.append(field) self.data_stack.append(LIST) self.data_stack.append([]) um_end_field = Unmarshaller.um_end_list def dump(value, file, strict=None): m = WDDXMarshaller(strict) return m.dump(value, file) def dumps(value, strict=None): m = WDDXMarshaller(strict) return m.dumps(value) def load(file): return WDDXUnmarshaller().load(file) def loads(string): return WDDXUnmarshaller().loads(string) def runtests(): print "Testing WDDX marshalling..." recordset = RecordSet(['NAME', 'AGE'], ['John Doe', 'Jane Doe'], [34, 31]) class Custom: def __init__(self, value): self.value = value def __wddx__(self): return self.value def __repr__(self): return repr(self.value) global STRICT STRICT = 1 test(load, loads, dump, dumps, [TRUE, FALSE, 1, pow(2,123L), 19.72, "here is a string & a ", [1,2,3,"foo"], recordset, {'lowerBound': 18, 'upperBound': 139, 'eggs': ['rhode island red', 'bantam']}, {'s': 'a string', 'obj': {'s': 'a string', 'n': -12.456}, 'n': -12.456, 'b': TRUE, 'a': [10,'second element'], } ]) STRICT = 0 test(load, loads, dump, dumps, [(1, 3, "five", 7, None, Custom(42)),], do_assert=0) if __name__ == '__main__': runtests() PyXML-0.8.2/xml/parsers/0040755000076400001440000000000007614726123014202 5ustar martinusersPyXML-0.8.2/xml/parsers/xmlproc/0040755000076400001440000000000007614726123015666 5ustar martinusersPyXML-0.8.2/xml/parsers/xmlproc/__init__.py0100644000076400001440000000002607162110740017760 0ustar martinusers"The XMLProc parser." PyXML-0.8.2/xml/parsers/xmlproc/_outputters.py0100644000076400001440000000317107413601555020632 0ustar martinusers# This module contains common functionality used by xvcmd.py and xpcmd.py from xml.parsers.xmlproc import xmlapp, utils # Backwards compatibility declarations ESISDocHandler = utils.ESISDocHandler Canonizer = utils.Canonizer DocGenerator = utils.DocGenerator # Error handler class MyErrorHandler(xmlapp.ErrorHandler): def __init__(self, locator, parser, warnings, entstack, rawxml): xmlapp.ErrorHandler.__init__(self,locator) self.show_warnings=warnings self.show_entstack=entstack self.show_rawxml=rawxml self.parser=parser self.reset() def __show_location(self,prefix,msg): print "%s:%s: %s" % (prefix,self.get_location(),msg) if self.show_entstack: print " Document entity" for item in self.parser.get_current_ent_stack(): print " %s: %s" % item if self.show_rawxml: raw=self.parser.get_raw_construct() if len(raw)>50: print " Raw construct too big, suppressed." else: print " '%s'" % raw def get_location(self): return "%s:%d:%d" % (self.locator.get_current_sysid(),\ self.locator.get_line(), self.locator.get_column()) def warning(self,msg): if self.show_warnings: self.__show_location("W",msg) self.warnings=self.warnings+1 def error(self,msg): self.fatal(msg) def fatal(self,msg): self.__show_location("E",msg) self.errors=self.errors+1 def reset(self): self.errors=0 self.warnings=0 PyXML-0.8.2/xml/parsers/xmlproc/catalog.py0100644000076400001440000002362007413601752017647 0ustar martinusers""" An SGML Open catalog file parser. $Id: catalog.py,v 1.14 2024/12/30 12:09:14 loewis Exp $ """ import string,sys import xmlutils,xmlapp # --- Parser factory class class CatParserFactory: """This class is used by the CatalogManager to create new parsers as they are needed.""" def __init__(self,error_lang=None): self.error_lang=error_lang def make_parser(self,sysid): return CatalogParser(self.error_lang) # --- Empty catalog application class class CatalogApp: def handle_public(self,pubid,sysid): pass def handle_delegate(self,prefix,sysid): pass def handle_document(self,sysid): pass def handle_system(self,sysid1,sysid2): pass def handle_base(self,sysid): pass def handle_catalog(self,sysid): pass def handle_override(self,yesno): pass def handle_doctype(self, docelem, sysid): pass def handle_sgmldecl(self, sysid): '''Called for SGMLDECL catalog entries. These are only used by SGML systems and tell the application where to find the SGML declaration file.''' # --- Abstract catalog parser with common functionality class AbstrCatalogParser: "Abstract catalog parser with functionality needed in all such parsers." def __init__(self,error_lang=None): self.app=CatalogApp() self.err=xmlapp.ErrorHandler(None) self.error_lang=error_lang def set_application(self,app): self.app=app def set_error_handler(self,err): self.err=err # --- The catalog file parser (SGML Open Catalogs) class CatalogParser(AbstrCatalogParser,xmlutils.EntityParser): "A parser for SGML Open catalog files." def __init__(self,error_lang=None): AbstrCatalogParser.__init__(self,error_lang) xmlutils.EntityParser.__init__(self) # p=pubid (or prefix) # s=sysid (to be resolved) # o=other self.entry_hash={ "PUBLIC": ("p","s"), "DELEGATE": ("p","s"), "CATALOG": ("s"), "DOCUMENT": ("s"), "BASE": ("o"), "SYSTEM": ("o","s"), "OVERRIDE": ("o"), "DOCTYPE" : ("o", "s"), "SGMLDECL" : ("s")} def parseStart(self): if self.error_lang: self.set_error_language(self.error_lang) def do_parse(self): try: while self.pos+1=self.datasize: break entryname=self.find_reg(xmlutils.reg_ws) if not self.entry_hash.has_key(entryname): self.report_error(5100,(entryname,)) else: self.parse_entry(entryname,self.entry_hash[entryname]) except xmlutils.OutOfDataException: if self.final: raise else: self.pos=prepos # Didn't complete the construct def parse_arg(self): if self.now_at('"'): delim='"' elif self.now_at("'"): delim="'" else: return self.find_reg(xmlutils.reg_ws,0) return self.scan_to(delim) def skip_stuff(self): "Skips whitespace and comments between items." while 1: self.skip_ws() if self.now_at("--"): self.scan_to("--") else: break def parse_entry(self,name,args): arglist=[] for arg in args: self.skip_stuff() arglist.append(self.parse_arg()) if name == "PUBLIC": self.app.handle_public(arglist[0],arglist[1]) elif name == "CATALOG": self.app.handle_catalog(arglist[0]) elif name == "DELEGATE": self.app.handle_delegate(arglist[0],arglist[1]) elif name == "BASE": self.app.handle_base(arglist[0]) elif name == "DOCUMENT": self.app.handle_document(arglist[0]) elif name == "SYSTEM": self.app.handle_system(arglist[0],arglist[1]) elif name == "OVERRIDE": self.app.handle_override(arglist[0]) elif name == "DOCTYPE": self.app.handle_doctype(arglist[0], arglist[1]) elif name == "SGMLDECL": self.app.handle_sgmldecl(arglist[0]) # --- A catalog file manager class CatalogManager(CatalogApp): def __init__(self, error_handler = None): self.__public = {} self.__system = {} self.__delegations = [] self.__document = None self.__doctypes = {} # docelem -> sysid self.__base = None self.__sgmldecl = None # Keeps track of sysid base even if we recurse into other catalogs self.__catalog_stack=[] self.err = error_handler or xmlapp.ErrorHandler(None) self.parser_fact = CatParserFactory() self.parser = None # --- application interface def set_error_handler(self,err): self.err=err def set_parser_factory(self,parser_fact): self.parser_fact=parser_fact def parse_catalog(self,sysid): self.__catalog_stack.append((self.__base,)) self.__base=sysid self.parser=self.parser_fact.make_parser(sysid) old_locator = self.err.get_locator() self.err.set_locator(self.parser) self.parser.set_error_handler(self.err) self.parser.set_application(self) self.parser.parse_resource(sysid) self.err.set_locator(old_locator) self.__base=self.__catalog_stack[-1][0] del self.__catalog_stack[-1] def report(self,out=sys.stdout): out.write("Document sysid: %s\n" % self.__document) out.write("FPI mappings:\n") for it in self.__public.items(): out.write(" %s -> %s\n" % it) out.write("Sysid mappings:\n") for it in self.__system.items(): out.write(" %s -> %s\n" % it) out.write("Delegates:\n") for (prefix,cat_man) in self.__delegations: out.write("---PREFIX MAPPER: %s\n" % prefix) cat_man.report(out) out.write("---EOPM\n") # --- parse events def handle_base(self,newbase): self.__base=newbase def handle_catalog(self,sysid): self.parse_catalog(self.__resolve_sysid(sysid)) def handle_public(self,pubid,sysid): self.__public[pubid]=self.__resolve_sysid(sysid) def handle_system(self,sysid1,sysid2): self.__system[self.__resolve_sysid(sysid1)]=\ self.__resolve_sysid(sysid2) def handle_delegate(self,prefix,sysid): catalog_manager=CatalogManager() catalog_manager.set_parser_factory(self.parser_fact) catalog_manager.parse_catalog(self.__resolve_sysid(sysid)) self.__delegations.append((prefix,catalog_manager)) def handle_document(self, sysid): self.__document = self.__resolve_sysid(sysid) def handle_sgmldecl(self, sysid): self.__sgmldecl = self.__resolve_sysid(sysid) def handle_doctype(self, docelem, sysid): self.__doctypes[docelem] = self.__resolve_sysid(sysid) # --- client services def get_public_ids(self): """Returns a list of all declared public indentifiers in this catalog and delegates.""" list=self.__public.keys() for delegate in self.__delegations: list=list+delegate.get_public_ids() return list def get_document_sysid(self): return self.__document def get_sgmldecl(self): return self.__sgmldecl def remap_sysid(self,sysid): try: return self.__system[sysid] except KeyError: return sysid def resolve_sysid(self,pubid,sysid): if pubid!=None: resolved=0 for (prefix,catalog) in self.__delegations: if prefix==pubid[:len(prefix)]: sysid=catalog.resolve_sysid(pubid,sysid) resolved=1 break if not resolved: try: sysid=self.__public[pubid] except KeyError: self.err.error("Unknown public identifier '%s'" % pubid) return self.remap_sysid(sysid) else: self.remap_sysid(sysid) def get_doctype_sysid(self, docelem): """Returns the system identifier of the DTD with the given document element. Raises KeyError if no such document element is known.""" return self.remap_sysid(self.__doctypes[docelem]) # --- internal methods def __resolve_sysid(self,sysid): return xmlutils.join_sysids(self.__base,sysid) # --- An xmlproc catalog client class xmlproc_catalog: def __init__(self,sysid,pf,error_handler=None): self.catalog=CatalogManager(error_handler) self.catalog.set_parser_factory(pf) self.catalog.parse_catalog(sysid) def get_document_sysid(self): return self.catalog.get_document_sysid() def get_sgmldecl(self): return self.catalog.get_sgmldecl() def resolve_pe_pubid(self,pubid,sysid): if pubid==None: return self.catalog.remap_sysid(sysid) else: return self.catalog.resolve_sysid(pubid,sysid) def resolve_doctype_pubid(self,pubid,sysid): if pubid==None: return self.catalog.remap_sysid(sysid) else: return self.catalog.resolve_sysid(pubid,sysid) def resolve_entity_pubid(self,pubid,sysid): if pubid==None: return self.catalog.remap_sysid(sysid) else: return self.catalog.resolve_sysid(pubid,sysid) # --- A SAX catalog client class SAX_catalog: def __init__(self,sysid,pf): self.catalog=CatalogManager() self.catalog.set_parser_factory(pf) self.catalog.parse_catalog(sysid) def resolveEntity(self,pubid,sysid): return self.catalog.resolve_sysid(pubid,sysid) PyXML-0.8.2/xml/parsers/xmlproc/charconv.py0100644000076400001440000001467207413601752020047 0ustar martinusers# Some experiments in adding character encoding conversions to xmlproc. # This module is not yet used by the released xmlproc, since I'm awaiting # a reorganization. # # $Id: charconv.py,v 1.7 2024/12/30 12:09:14 loewis Exp $ import string # --- Conversion tables # CP 850 to ISO 8859-1 # First element is no. 128, second 129 ... # The non-ISO characters, such as , are mapped to non-ISO chars # 127-145 and 147-159 in the order they appear in CP 850. Since there are # more non-ISO chars than there is room for in these intervals, some of # the last chars are also mapped to 159. cp850_iso=[199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197, 201,230,198,244,246,242,251,249,255,246,220,248,163,127,215,128, 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187, 129,130,131,132,133,193,194,192,169,134,135,136,137,162,165,138, 139,140,141,142,143,144,227,195,145,147,148,149,150,151,152,164, 240,208,202,203,200,153,205,206,207,154,155,156,157,166,204,158, 211,223,212,210,245,213,181,222,254,218,219,217,253,221,175,180, 173,177,159,190,182,167,247,184,176,168,159,185,179,178,159,160] cp850_iso_tbl="" for ix in range(128): cp850_iso_tbl=cp850_iso_tbl+chr(ix) for chno in cp850_iso: cp850_iso_tbl=cp850_iso_tbl+chr(chno) # ISO 8859-1 to CP 850 iso_cp850=[0]*256 for ix in range(256): iso_cp850[ord(cp850_iso_tbl[ix])]=ix iso_cp850_tbl="" for chno in iso_cp850: iso_cp850_tbl=iso_cp850_tbl+chr(chno) # Windows CP 1252 to ISO 8859-1 # Maps characters 128-159, 63 means non-mappable, 127 means unused in 1252 # Does a fuzzy transform (ndash and mdash both mapped to -, and so on) cp1252_iso=[127,127,44,63,63,95,63,63,94,63,63,60,198,127,127,127,127,39,39, 34,34,183,45,45,126,63,63,62,230,127,127,127] cp1252_iso_tbl="" for char in map(chr,range(128)+cp1252_iso+range(160,256)): cp1252_iso_tbl=cp1252_iso_tbl+char # --- Conversion functions def utf8_to_iso8859(data): out="" ix=0 for ix in range(len(data)): chn=ord(data[ix]) if chn & 224==192: # 110xxxxx out=out+chr( ((chn & 3) << 6) + (ord(data[ix+1]) & 63)) elif chn & 128==0: # 0xxxxxxx out=out+data[ix] return out def iso8859_to_utf8(data): out="" for ch in data: if ord(ch)<128: out=out+ch else: chno=ord(ch) out=out+chr(192+((chno & 192)>>6))+chr(128+(chno & 63)) return out def cp850_to_iso8859(data): return string.translate(data,cp850_iso_tbl) def iso8859_to_cp850(data): return string.translate(data,iso_cp850_tbl) def id_conv(data): return data def cp850_to_utf8(data): return iso8859_to_utf8(cp850_to_iso8859(data)) def utf8_to_cp850(data): return iso8859_to_cp850(utf8_to_iso8859(data)) def cp1252_to_iso8859(data): return string.translate(data,cp1252_iso_tbl) # --- Conversion function database class ConverterDatabase: """This class knows about all registered converting functions, and can be queried for information about converters.""" def __init__(self): self.__map={} self.__alias_map={} def add_alias(self,canonical,alias): "Adds an alias for a character set." self.__alias_map[string.lower(alias)]=string.lower(canonical) def can_convert(self,from_encoding,to_encoding): """Returns true if converters to from from_encoding to to_encoding are known. Encoding names follow the syntax specified by the XML rec.""" from_encoding=self._canonize_name(from_encoding) to_encoding=self._canonize_name(to_encoding) if from_encoding==to_encoding: return 1 try: return self.__map[from_encoding].has_key(to_encoding) except KeyError: return 0 def get_converter(self,from_encoding,to_encoding): """Returns a converter function that converts from the character encoding from_encoding to to_encoding. A KeyError will be thrown if no converter is known.""" from_encoding=self._canonize_name(from_encoding) to_encoding=self._canonize_name(to_encoding) if from_encoding==to_encoding: return id_conv else: return self.__map[from_encoding][to_encoding] def add_converter(self,from_encoding,to_encoding,converter): from_encoding=self._canonize_name(from_encoding) to_encoding=self._canonize_name(to_encoding) if not self.__map.has_key(from_encoding): self.__map[from_encoding]={} self.__map[from_encoding][to_encoding]=converter def _canonize_name(self,name): "Returns the canonical form of a charset name." name=string.lower(name) if self.__alias_map.has_key(name): return self.__alias_map[name] else: return name # --- Globals convdb=ConverterDatabase() convdb.add_alias("US-ASCII","ANSI_X3.4-1968") convdb.add_alias("US-ASCII","iso-ir-6") convdb.add_alias("US-ASCII","ANSI_X3.4-1986") convdb.add_alias("US-ASCII","ISO_646.irv:1991") convdb.add_alias("US-ASCII","ASCII") convdb.add_alias("US-ASCII","ISO646-US") convdb.add_alias("US-ASCII","us") convdb.add_alias("US-ASCII","IBM367") convdb.add_alias("US-ASCII","cp367") convdb.add_alias("US-ASCII","csASCII") convdb.add_alias("ISO-8859-1","ISO_8859-1:1987") convdb.add_alias("ISO-8859-1","iso-ir-100") convdb.add_alias("ISO-8859-1","ISO_8859-1") convdb.add_alias("ISO-8859-1","latin1") convdb.add_alias("ISO-8859-1","l1") convdb.add_alias("ISO-8859-1","IBM819") convdb.add_alias("ISO-8859-1","CP819") convdb.add_alias("ISO-8859-1","csISOLatin1") convdb.add_alias("IBM850","cp850") convdb.add_alias("IBM850","850") convdb.add_alias("IBM850","csPC850Multilingual") # converters (foo -> foo case not needed, handled automatically) convdb.add_converter("IBM850","ISO-8859-1",cp850_to_iso8859) convdb.add_converter("US-ASCII","ISO-8859-1",id_conv) convdb.add_converter("windows-1252","ISO-8859-1",cp1252_to_iso8859) convdb.add_converter("ISO-8859-1","IBM850",iso8859_to_cp850) convdb.add_converter("US-ASCII","IBM850",id_conv) convdb.add_converter("ISO-8859-1","WINDOWS-1252",id_conv) convdb.add_converter("US-ASCII","UTF-8",id_conv) # these are slow, so you should use Python 2.x convdb.add_converter("UTF-8","ISO-8859-1",utf8_to_iso8859) convdb.add_converter("ISO-8859-1","UTF-8",iso8859_to_utf8) convdb.add_converter("UTF-8","IBM850",utf8_to_cp850) convdb.add_converter("IBM850","UTF-8",cp850_to_utf8) PyXML-0.8.2/xml/parsers/xmlproc/dtdparser.py0100644000076400001440000005452507461630227020237 0ustar martinusers""" This module contains a DTD parser that reports DTD parse events to a listener. Used by xmlproc to parse DTDs, but can be used for other purposes as well. $Id: dtdparser.py,v 1.13 2025/04/13 19:10:40 larsga Exp $ """ import string string_find = string.find # optimization from xmlutils import * from xmldtd import * # ============================== # A DTD parser # ============================== class DTDParser(XMLCommonParser): "A parser for XML DTDs, both internal and external." # --- LOW-LEVEL SCANNING METHODS # Redefined here with extra checking for parameter entity processing def find_reg(self,regexp,required=1): oldpos=self.pos mo=regexp.search(self.data,self.pos) if mo==None: if self.final and not required: self.pos=len(self.data) # Just moved to the end return self.data[oldpos:] if self.in_peref: self.pop_entity() self.in_peref=0 self._skip_ws() return self.find_reg(regexp,required) raise OutOfDataException() self.pos=mo.start(0) return self.data[oldpos:self.pos] def scan_to(self,target): new_pos=string_find(self.data,target,self.pos) if new_pos==-1: if self.in_peref: self.pop_entity() self.in_peref=0 self._skip_ws() return self.scan_to(target) raise OutOfDataException() res=self.data[self.pos:new_pos] self.pos=new_pos+len(target) return res def get_index(self,target): new_pos=string_find(self.data,target,self.pos) if new_pos==-1: if self.in_peref: self.pop_entity() self.in_peref=0 self._skip_ws() return self.get_index(target) raise OutOfDataException() return new_pos def test_str(self,str): if self.datasize-self.posself.datasize-5 and not self.final: if self.in_peref: self.pop_entity() self.in_peref=0 self._skip_ws() return self.test_reg(regexp) raise OutOfDataException() return regexp.match(self.data,self.pos)!=None def get_match(self,regexp): if self.pos>self.datasize-5 and not self.final: if self.in_peref: self.pop_entity() self.in_peref=0 self._skip_ws() return self.get_match(regexp) raise OutOfDataException() ent=regexp.match(self.data,self.pos) if ent==None: self.report_error(reg2code[regexp.pattern]) return "" end=ent.end(0) # Speeds us up slightly if end==self.datasize: if self.in_peref: self.pop_entity() self.in_peref=0 #self._skip_ws() return ent.group(0) raise OutOfDataException() self.pos=end return ent.group(0) # --- DTD Parser proper def __init__(self): EntityParser.__init__(self) self.internal=0 self.seen_xmldecl=0 self.dtd=DTDConsumerPE() # Keeps track of PE info self.dtd_consumer=self.dtd # Where all events go self.in_peref=0 self.ignores_entered=0 self.includes_entered=0 self.own_ent_stack=[] # Keeps includes_entered def reset(self): EntityParser.reset(self) if hasattr(self,"dtd"): self.dtd.reset() self.internal=0 self.seen_xmldecl=0 self.in_peref=0 self.ignores_entered=0 self.includes_entered=0 self.own_ent_stack=[] # Keeps includes_entered self.dtd_start_called = 0 # Set to 1 if parsing external subset from # xmlproc.py (which has called dtd_start...) def parseStart(self): if not self.dtd_start_called: self.dtd_consumer.dtd_start() def parseEnd(self): self.dtd_consumer.dtd_end() def set_dtd_consumer(self,dtd): "Tells the parser where to send DTD information." self.dtd_consumer=dtd def set_dtd_object(self,dtd): """Tells the parser where to mirror PE information (in addition to what goes to the DTD consumer and where to get PE information.""" self.dtd=dtd def set_internal(self,yesno): "Tells the parser whether the DTD is internal or external." self.internal=yesno def deref(self): "Removes circular references." self.ent = self.dtd_consumer = self.dtd = self.app = self.err = None def do_parse(self): "Does the actual parsing." try: prepos=self.pos if self.ignores_entered>0: self.parse_ignored_data() self._skip_ws() while self.pos") and self.includes_entered>0: self.includes_entered=self.includes_entered-1 else: self.report_error(3013) self.scan_to(">") prepos=self.pos self._skip_ws() if self.final and self.includes_entered>0: self.report_error(3043) except OutOfDataException,e: if self.final: raise e else: self.pos=prepos except IndexError,e: if self.final: raise OutOfDataException() else: self.pos=prepos def parse_entity(self): "Parses an entity declaration." EntityParser.skip_ws(self,1) # No PE refs allowed here if self.now_at("%"): pedecl=1 EntityParser.skip_ws(self,1) # No PE refs allowed here else: pedecl=0 ent_name=self._get_name() self.skip_ws(1) (pub_id,sys_id)=self.parse_external_id(0) if sys_id == None: internal = 1 ent_val = self.parse_ent_repltext() else: internal = 0 if not self.get_current_sysid() and \ urlparse.urlparse(sys_id)[0] == "": self.report_error(2024, sys_id) sys_id = join_sysids(self.get_current_sysid(), sys_id) if self.now_at("NDATA"): self.report_error(3002) else: self.skip_ws() if not internal and self.now_at("NDATA"): # Parsing the optional NDataDecl if pedecl: self.report_error(3035) self.skip_ws() ndata=self._get_name() self.skip_ws() else: ndata = None if not self.now_at(">"): self.report_error(3005,">") if pedecl: # These are echoed to self.dtd so we remember this stuff if internal: self.dtd_consumer.new_parameter_entity(ent_name,ent_val) if self.dtd!=self.dtd_consumer: self.dtd.new_parameter_entity(ent_name,ent_val) else: self.dtd_consumer.new_external_pe(ent_name,pub_id,sys_id) if self.dtd!=self.dtd_consumer: self.dtd.new_external_pe(ent_name,pub_id,sys_id) else: if internal: self.dtd_consumer.new_general_entity(ent_name,ent_val) else: self.dtd_consumer.new_external_entity(ent_name,pub_id,sys_id,ndata) def parse_ent_repltext(self): """Parses an entity replacement text and resolves all character entity and parameter entity references in it.""" if self.now_at('"'): delim = '"' elif self.now_at("'"): delim = "'" else: self.report_error(3004,("'","\"")) self.scan_to(">") return return self.parse_ent_litval(self.scan_to(delim)) def parse_ent_litval(self,litval): pos=0 val="" while 1: res=reg_litval_stop.search(litval,pos) if res==None: break val=val+litval[pos:res.start(0)] pos=res.start(0) if litval[pos:pos+2]=="&#": endpos=string_find(litval,";",pos) if endpos==-1: self.report_error(3005,";") break if litval[pos+2]=="x": digs=unhex(litval[pos+3:endpos]) else: digs=int(litval[pos+2:endpos]) if not (digs==9 or digs==10 or digs==13 or \ (digs>=32 and digs<=255)): if digs>255: if using_unicode and digs<65536: val = val+xml_chr(digs) else: self.report_error(1005,digs) else: self.report_error(3018,digs) else: val=val+xml_chr(digs) pos=endpos+1 elif litval[pos]=="%": endpos=string_find(litval,";",pos) if endpos==-1: self.report_error(3005,";") break name=litval[pos+1:endpos] try: ent=self.dtd.resolve_pe(name) if ent.is_internal(): val=val+self.parse_ent_litval(ent.value) else: self.report_error(3037) # FIXME: Easily solved now...? except KeyError: self.report_error(3038,name) pos=endpos+1 else: self.report_error(4001) break return val+litval[pos:] def parse_notation(self): "Parses a notation declaration." self.skip_ws(1) name=self._get_name() self.skip_ws(1) (pubid,sysid)=self.parse_external_id(1,0) self.skip_ws() if not self.now_at(">"): self.report_error(3005,">") self.dtd_consumer.new_notation(name,pubid,sysid) def parse_pe_ref(self): "Parses a reference to a parameter entity." name=self.get_match(reg_pe_ref)[1:-1] try: ent=self.dtd.resolve_pe(name) except KeyError: self.report_error(3038,name) return if ent.is_internal(): self.push_entity(self.get_current_sysid(),ent.value) self.do_parse() self.pop_entity() else: sysid=self.pubres.resolve_pe_pubid(ent.get_pubid(), ent.get_sysid()) int=self.internal self.set_internal(0) try: self.open_entity(sysid) # Does parsing and popping finally: self.set_internal(int) def parse_attlist(self): "Parses an attribute list declaration." self.skip_ws(1) elem=self._get_name() self.skip_ws(1) while not self.test_str(">"): attr=self._get_name() self.skip_ws(1) if self.test_reg(reg_attr_type): a_type=self.get_match(reg_attr_type) elif self.now_at("NOTATION"): self.skip_ws(1) a_type=("NOTATION",self.__parse_list(reg_name,"|")) elif self.now_at("("): self.pos=self.pos-1 # Does not expect '(' to be skipped a_type=self.__parse_list(reg_nmtoken,"|") tokens={} for token in a_type: if tokens.has_key(token): self.report_error(3044,(token,)) else: tokens[token]=1 else: self.report_error(3039) self.scan_to(">") return self.skip_ws(1) if self.test_str("\"") or self.test_str("'"): a_decl="#DEFAULT" a_def=self.parse_ent_repltext() elif self.now_at("#IMPLIED"): a_decl="#IMPLIED" a_def=None elif self.now_at("#REQUIRED"): a_decl="#REQUIRED" a_def=None elif self.now_at("#FIXED"): self.skip_ws(1) a_decl = "#FIXED" a_def = self.parse_ent_repltext() else: self.report_error(3909) a_decl = None a_def = None self.skip_ws() self.dtd_consumer.new_attribute(elem,attr,a_type,a_decl,a_def) self.pos=self.pos+1 # Skipping the '>' def parse_elem_type(self): "Parses an element type declaration." self.skip_ws(1) #elem_name=self.get_match(reg_name) elem_name=self._get_name() self.skip_ws(1) # content-spec if self.now_at("EMPTY"): elem_cont="EMPTY" elif self.now_at("ANY"): elem_cont="ANY" elif self.now_at("("): elem_cont=self._parse_content_model() else: self.report_error(3004,("EMPTY, ANY","(")) elem_cont="ANY" # Just so things don't fall apart downstream self.skip_ws() if not self.now_at(">"): self.report_error(3005,">") self.dtd_consumer.new_element_type(elem_name,elem_cont) def _parse_content_model(self,level=0): """Parses the content model of an element type declaration. Level tells the function if we are on the top level (=0) or not (=1). The '(' has just been passed over, we read past the ')'. Returns a tuple (separator, contents, modifier), where content consists of (cp, modifier) tuples and cp can be a new content model tuple.""" self.skip_ws() # Creates a content list with separator first cont_list=[] sep="" if self.now_at("#PCDATA") and level==0: return self.parse_mixed_content_model() while 1: self.skip_ws() if self.now_at("("): cp=self._parse_content_model(1) else: cp=self._get_name() if self.test_str("?") or self.test_str("*") or self.test_str("+"): mod=self.data[self.pos] self.pos=self.pos+1 else: mod="" if type(cp) in StringTypes: cont_list.append((cp,mod)) else: cont_list.append(cp) self.skip_ws() if self.now_at(")"): break if sep=="": if self.test_str("|") or self.test_str(","): sep=self.data[self.pos] else: self.report_error(3004,("'|'",",")) self.pos=self.pos+1 else: if not self.now_at(sep): self.report_error(3040) self.scan_to(")") if self.test_str("+") or self.test_str("?") or self.test_str("*"): mod=self.data[self.pos] self.pos=self.pos+1 else: mod="" return (sep,cont_list,mod) def parse_mixed_content_model(self): "Parses mixed content models. Ie: ones containing #PCDATA." cont_list=[("#PCDATA","")] sep="" mod="" while 1: try: self.skip_ws() except OutOfDataException,e: raise e if self.now_at("|"): sep="|" elif self.now_at(")"): break else: self.report_error(3005,"|") self.scan_to(">") self.skip_ws() cont_list.append((self.get_match(reg_name),"")) if self.now_at("*"): mod="*" elif sep=="|": self.report_error(3005,"*") return (sep,cont_list,mod) def parse_conditional(self): "Parses a conditional section." if self.internal: self.report_error(3041) self.scan_to("]]>") else: self.skip_ws() if self.now_at("IGNORE"): self.ignores_entered=1 self.skip_ws() if not self.now_at("["): self.report_error(3005,"[") self.parse_ignored_data() return if not self.now_at("INCLUDE"): self.report_error(3004,("'IGNORE'","INCLUDE")) self.scan_to("[") self.includes_entered=self.includes_entered+1 self.skip_ws() if not self.now_at("["): self.report_error(3005,"[") # Doing an extra skip_ws and waiting until we get here # before increasing the include count, to avoid increasing # the count inside a PE, where it would be forgotten after pop. self.skip_ws() self.includes_entered=self.includes_entered+1 def parse_ignored_data(self): try: counter=self.ignores_entered while counter: self.find_reg(reg_cond_sect) if self.now_at("]]>"): counter=counter-1 else: counter=counter+1 self.pos=self.pos+3 except OutOfDataException,e: if self.final: self.report_error(3043) self.ignores_entered=counter self.data="" self.pos=0 self.datasize=0 raise e self.ignores_entered=0 def __parse_list(self, elem_regexp, separator): "Parses a '(' S? elem_regexp S? separator ... ')' list. (Internal.)" list=[] self.skip_ws() if not self.now_at("("): self.report_error(3005,"(") while 1: self.skip_ws() list.append(self.get_match(elem_regexp)) self.skip_ws() if self.now_at(")"): break elif not self.now_at(separator): self.report_error(3004,("')'",separator)) break return list def is_external(self): return not self.internal # --- Internal methods def _push_ent_stack(self,name="None"): EntityParser._push_ent_stack(self,name) self.own_ent_stack.append(self.includes_entered) self.includes_entered=0 def _pop_ent_stack(self): EntityParser._pop_ent_stack(self) self.includes_entered=self.own_ent_stack[-1] del self.own_ent_stack[-1] # --- Minimal DTD consumer class DTDConsumerPE(DTDConsumer): def __init__(self): DTDConsumer.__init__(self,None) self.param_ents={} self.used_notations = {} def new_parameter_entity(self,name,val): if not self.param_ents.has_key(name): #Keep first decl self.param_ents[name]=InternalEntity(name,val) def new_external_pe(self,name,pubid,sysid): if not self.param_ents.has_key(name): # Keep first decl self.param_ents[name]=ExternalEntity(name,pubid,sysid,"") def resolve_pe(self,name): return self.param_ents[name] def reset(self): self.param_ents={} PyXML-0.8.2/xml/parsers/xmlproc/errors.py0100644000076400001440000010201507534565153017555 0ustar martinusers# -*- coding: iso-8859-1 -*- # This file contains the lists of error messages used by xmlproc import string # The interface to the outside world # Todo: # - 3047 needed in Swedish, Norwegian and French # - 2024 ditto # - 2025 ditto # - 2004 must be retranslated error_lists={} # The hash of errors def add_error_list(language,list): error_lists[string.lower(language)]=list def get_error_list(language): return error_lists[string.lower(language)] def get_language_list(): return error_lists.keys() # Errors in English english={ # --- Warnings: 1000-1999 1000: "Undeclared namespace prefix '%s'", 1002: "Unsupported encoding '%s'", 1003: "Obsolete namespace syntax", 1005: "Unsupported character number '%d' in character reference", 1006: "Element '%s' has attribute list, but no element declaration", 1007: "Attribute '%s' defined more than once", 1008: "Ambiguous content model", # --- Namespace warnings 1900: "Namespace prefix names cannot contain ':'s.", 1901: "Namespace URI cannot be empty", 1902: "Namespace prefix not declared", 1903: "Attribute names not unique after namespace processing", # --- Validity errors: 2000-2999 2000: "Actual value of attribute '%s' does not match fixed value", 2001: "Element '%s' not allowed here", 2002: "Document root element '%s' does not match declared root element", 2003: "Element '%s' not declared", 2004: "Element '%s' ended before required elements found (%s)", 2005: "Character data not allowed in the content of this element", 2006: "Attribute '%s' not declared", 2007: "ID '%s' appears more than once in document", 2008: "Only unparsed entities allowed as the values of ENTITY attributes", 2009: "Notation '%s' not declared", 2010: "Required attribute '%s' not present", 2011: "IDREF referred to non-existent ID '%s'", 2012: "Element '%s' declared more than once", 2013: "Only one ID attribute allowed on each element type", 2014: "ID attributes cannot be #FIXED or defaulted", 2015: "xml:space must be declared an enumeration type", 2016: "xml:space must have exactly one or both of the values 'default' and 'preserve'", 2017: "'%s' is not an allowed value for the '%s' attribute", 2018: "Value of '%s' attribute must be a valid name", 2019: "Value of '%s' attribute not a valid name token", 2020: "Value of '%s' attribute not a valid name token sequence", 2021: "Token '%s' in the value of the '%s' attribute is not a valid name", 2022: "Notation attribute '%s' uses undeclared notation '%s'", 2023: "Unparsed entity '%s' uses undeclared notation '%s'", 2024: "Cannot resolve relative URI '%s' when document URI unknown", 2025: "Element '%s' missing before element '%s'", # --- Well-formedness errors: 3000-3999 # From xmlutils 3000: "Couldn't open resource '%s'", 3001: "Construct started, but never completed", 3002: "Whitespace expected here", 3003: "Didn't match '%s'", ## FIXME: This must be redone 3004: "One of %s or '%s' expected", 3005: "'%s' expected", 3047: "encoding '%s' conflicts with autodetected encoding", 3048: "character set conversion problem: %s", # From xmlproc.XMLCommonParser 3006: "SYSTEM or PUBLIC expected", 3007: "Text declaration must appear first in entity", 3008: "XML declaration must appear first in document", 3009: "Multiple text declarations in a single entity", 3010: "Multiple XML declarations in a single document", 3011: "XML version missing on XML declaration", 3012: "Standalone declaration on text declaration not allowed", 3045: "Processing instruction target names beginning with 'xml' are reserved", 3046: "Unsupported XML version", # From xmlproc.XMLProcessor 3013: "Illegal construct", 3014: "Premature document end, element '%s' not closed", 3015: "Premature document end, no root element", 3016: "Attribute '%s' occurs twice", 3017: "Elements not allowed outside root element", 3018: "Illegal character number '%d' in character reference", 3019: "Entity recursion detected", 3020: "External entity references not allowed in attribute values", 3021: "Undeclared entity '%s'", 3022: "'<' not allowed in attribute values", 3023: "End tag for '%s' seen, but '%s' expected", 3024: "Element '%s' not open", 3025: "']]>' must not occur in character data", 3027: "Not a valid character number", 3028: "Character references not allowed outside root element", 3029: "Character data not allowed outside root element", 3030: "Entity references not allowed outside root element", 3031: "References to unparsed entities not allowed in element content", 3032: "Multiple document type declarations", 3033: "Document type declaration not allowed inside root element", 3034: "Premature end of internal DTD subset", 3042: "Element crossed entity boundary", # From xmlproc.DTDParser 3035: "Parameter entities cannot be unparsed", 3036: "Parameter entity references not allowed in internal subset declarations", 3037: "External entity references not allowed in entity replacement text", 3038: "Unknown parameter entity '%s'", 3039: "Expected type or alternative list", 3040: "Choice and sequence lists cannot be mixed", 3041: "Conditional sections not allowed in internal subset", 3043: "Conditional section not closed", 3044: "Token '%s' defined more than once", # next: 3049 # From regular expressions that were not matched 3900: "Not a valid name", 3901: "Not a valid version number (%s)", 3902: "Not a valid encoding name", 3903: "Not a valid comment", 3905: "Not a valid hexadecimal number", 3906: "Not a valid number", 3907: "Not a valid parameter reference", 3908: "Not a valid attribute type", 3909: "Not a valid attribute default definition", 3910: "Not a valid enumerated attribute value", 3911: "Not a valid standalone declaration", # --- Internal errors: 4000-4999 4000: "Internal error: Entity stack broken", 4001: "Internal error: Entity reference expected.", 4002: "Internal error: Unknown error number %d.", 4003: "Internal error: External PE references not allowed in declarations", # --- XCatalog errors: 5000-5099 5000: "Uknown XCatalog element: %s.", 5001: "Required XCatalog attribute %s on %s missing.", # --- SOCatalog errors: 5100-5199 5100: "Invalid or unsupported construct: %s.", } # Errors in Norwegian norsk = english.copy() norsk.update({ # --- Warnings: 1000-1999 1000: "Navneroms-prefikset '%s' er ikke deklarert", 1002: "Tegn-kodingen '%s' er ikke stttet", 1003: "Denne navnerom-syntaksen er foreldet", 1005: "Tegn nummer '%d' i tegn-referansen er ikke stttet", 1006: "Element '%s' har attributt-liste, men er ikke deklarert", 1007: "Attributt '%s' deklarert flere ganger", 1008: "Tvetydig innholds-modell", # --- Namespace warnings: 1900-1999 1900: "Navnerommets prefiks-navn kan ikke inneholde kolon", 1901: "Navnerommets URI kan ikke vre tomt", 1902: "Navnerommets prefiks er ikke deklarert", 1903: "Attributt-navn ikke unike etter navneroms-prosessering", # --- Validity errors: 2000-2999 2000: "Faktisk verdi til attributtet '%s' er ikke lik #FIXED-verdien", 2001: "Elementet '%s' er ikke tillatt her", 2002: "Dokumentets rot-element '%s' er ikke det samme som det deklarerte", 2003: "Element-typen '%s' er ikke deklarert", 2004: "Elementet '%s' avsluttet, men innholdet ikke ferdig", 2005: "Tekst-data er ikke tillatt i dette elementets innhold", 2006: "Attributtet '%s' er ikke deklarert", 2007: "ID-en '%s' brukt mer enn en gang", 2008: "Bare uparserte entiteter er tillatt som verdier til ENTITY-attributter", 2009: "Notasjonen '%s' er ikke deklarert", 2010: "Pkrevd attributt '%s' mangler", 2011: "IDREF viste til ikke-eksisterende ID '%s'", 2012: "Elementet '%s' deklarert mer enn en gang", 2013: "Bare ett ID-attributt er tillatt pr element-type", 2014: "ID-attributter kan ikke vre #FIXED eller ha standard-verdier", 2015: "xml:space m deklareres som en oppramstype", 2016: "xml:space m ha en eller begge av verdiene 'default' og 'preserve'", 2017: "'%s' er ikke en gyldig verdi for '%s'-attributtet", 2018: "Verdien til '%s'-attributtet m vre et gyldig navn", 2019: "Verdien til '%s'-attributtet er ikke et gyldig NMTOKEN", 2020: "Verdien til '%s'-attributtet er ikke et gyldig NMTOKENS", 2021: "Symbolet '%s' i verdien til '%s'-attributtet er ikke et gyldig navn", 2022: "Notasjons-attributtet '%s' bruker en notasjon '%s' som ikke er deklarert", 2023: "Uparsert entitet '%s' bruker en notasjon '%s' som ikke er deklarert", # --- Well-formedness errors: 3000-3999 # From xmlutils 3000: "Kunne ikke pne '%s'", 3001: "For tidlig slutt p entiteten", 3002: "Blanke forventet her", 3003: "Matchet ikke '%s'", ## FIXME: This must be redone 3004: "En av %s eller '%s' forventet", 3005: "'%s' forventet", # From xmlproc.XMLCommonParser 3006: "SYSTEM eller PUBLIC forventet", 3007: "Tekst-deklarasjonen m st frst i entiteten", 3008: "XML-deklarasjonen m st frst i dokumentet", 3009: "Flere tekst-deklarasjoner i samme entitet", 3010: "Flere tekst-deklarasjoner i samme dokument", 3011: "XML-versjonen mangler p XML-deklarasjonen", 3012: "'Standalone'-deklarasjon p tekst-deklarasjon ikke tillatt", # From xmlproc.XMLProcessor 3013: "Syntaksfeil", 3014: "Dokumentet slutter for tidlig, elementet '%s' er ikke lukket", 3015: "Dokumentet slutter for tidlig, rot-elementet mangler", 3016: "Attributtet '%s' gjentatt", 3017: "Kun ett rot-element er tillatt", 3018: "Ulovlig tegn nummer '%d' i tegn-referanse", 3019: "Entitets-rekursjon oppdaget", 3020: "Eksterne entitets-referanser ikke tillatt i attributt-verdier", 3021: "Entiteten '%s' er ikke deklarert", 3022: "'<' er ikke tillatt i attributt-verdier", 3023: "Slutt-tagg for '%s', men '%s' forventet", 3024: "Elementet '%s' lukket, men ikke pent", 3025: "']]>' ikke tillatt i tekst-data", 3027: "Ikke et gyldig tegn-nummer", 3028: "Tegn-referanser ikke tillatt utenfor rot-elementet", 3029: "Tekst-data ikke tillatt utenfor rot-elementet", 3030: "Entitets-referanser ikke tillatt utenfor rot-elementet", 3031: "Referanser til uparserte entiteter er ikke tillatt i element-innhold", 3032: "Mer enn en dokument-type-deklarasjon", 3033: "Dokument-type-deklarasjon kun tillatt fr rot-elementet", 3034: "Det interne DTD-subsettet slutter for tidlig", 3042: "Element krysset entitets-grense", 3045: "Processing instruction navn som begynner med 'xml' er reservert", 3046: "Denne XML-versjonen er ikke stttet", # From xmlproc.DTDParser 3035: "Parameter-entiteter kan ikke vre uparserte", 3036: "Parameter-entitets-referanser ikke tillatt inne i deklarasjoner i det interne DTD-subsettet", 3037: "Eksterne entitets-referanser ikke tillatt i entitetsdeklarasjoner", 3038: "Parameter-entiteten '%s' ikke deklarert", 3039: "Forventet attributt-type eller liste av alternativer", 3040: "Valg- og sekvens-lister kan ikke blandes", 3041: "'Conditional sections' er ikke tillatt i det interne DTD-subsettet", 3043: "'Conditional section' ikke lukket", 3044: "Symbolet '%s' er definert mer enn en gang", # From regular expressions that were not matched 3900: "Ikke et gyldig navn", 3901: "Ikke et gyldig versjonsnummer (%s)", 3902: "Ikke et gyldig tegnkodings-navn", 3903: "Ikke en gyldig kommentar", 3905: "Ikke et gyldig heksadesimalt tall", 3906: "Ikke et gyldig tall", 3907: "Ikke en gyldig parameter-entitets-referanse", 3908: "Ikke en gyldig attributt-type", 3909: "Ikke en gyldig attributt-standard-verdi", 3910: "Ikke en gyldig verdi for opprams-attributter", 3911: "Ikke en gyldig verdi for 'standalone'", # --- Internal errors: 4000-4999 4000: "Intern feil: Entitets-stakken korrupt.", 4001: "Intern feil: Entitets-referanse forventet.", 4002: "Intern feil: Ukjent feilmelding %d.", 4003: "Intern feil: Eksterne parameter-entiteter ikke tillatt i deklarasjoner", # --- XCatalog errors: 5000-5099 5000: "Ukjent XCatalog-element: %s.", 5001: "Pkrevd XCatalog-attributt %s p %s mangler.", # --- SOCatalog errors: 5100-5199 5100: "Ugyldig eller ikke stttet konstruksjon: %s.", }) # Errors in Swedish # Contributed by Marus Brisenfeldt, svenska = english.copy() svenska.update({ # --- Warnings: 1000-1999 1000: "Namnrymds-prefixet '%s' r inte deklarerat", 1002: "Systemet stder inte teckenuppsttningen '%s'", 1003: "Denna namnrymds-syntax r frlegad", 1005: "Teckennummer '%d' i teckenreferansen stds inte", 1006: "Ett attribut mste deklareras fr elementet '%s'", 1007: "Attributet '%s' r deklarerat flera gnger", 1008: "Tvetydig innhllsmodell", # --- Namespace warnings: 1900-1999 1900: "Namnrymdens prefixnamn kan inte innehlla kolon", 1901: "Namnrymdens URI fr inte vara tom (mste deklareras)", 1902: "Namnrymdsprefixet r inte deklarerat", 1903: "Attribut-namn inte unika efter namnrymds-prosessering", # --- Validity errors: 2000-2999 2000: "Attributet '%s' faktiska vrde r inte likt #FIXED-vrdet", 2001: "Elementet '%s' tillts inte hr", 2002: "Dokumentets rot-element '%s' r inte det samma som deklarerat", 2003: "Elementtypen '%s' r inte deklarerad", 2004: "Elementet '%s' r avslutat, men innhllet r inte fullstndigt", 2005: "Textdata (PCDATA) r inte tilltet som innehll i elementet", 2006: "Attributet '%s' r inte deklarerat", 2007: "ID't '%s' anvnds mer n en gng", 2008: "Endast icke 'parsade' entiteter r tilltna som vrden till ENTITY-attribut", 2009: "Notationen '%s' r inte deklarerad", 2010: "Erfordligt attribut '%s' saknas", 2011: "IDREF hnvisar till ett icke existerande ID ('%s')", 2012: "Elementet '%s' har deklarerats mer n en gng", 2013: "Endast ett ID-attribut er tilltet per elementtyp", 2014: "ID-attribut kan inte vara '#FIXED' eller ha ett standardvrde", 2015: "xml:space mste deklareras som en listtyp", 2016: "xml:space mste ha en eller bda av vrdena 'default' och 'preserve'", 2017: "'%s' r inte ett giltigt vrde p attributet '%s'", 2018: "Vrdet p attributet '%s' mste vara ett giltigt namn", 2019: "Vrdet p attributet '%s' r inte ett giltigt NMTOKEN", 2020: "Vrdet p attributet '%s' r inte ett giltigt NMTOKENS", 2021: "Symbolen '%s' i vrdet p attributet '%s' r inte ett giltigt namn", 2022: "Notations-attributet '%s' anvnder en notation ('%s') som inte r deklarerad", 2023: "Icke 'parsad' entitet anvnder en notation ('%s') som inte r deklarerad", # --- Well-formedness errors: 3000-3999 # From xmlutils 3000: "Systemet kunde inte ppna '%s'", 3001: "Entitet pbrjad, men inte avslutad", 3002: "Mellanslag frvntat hr", 3003: "Matchar inte '%s'", ## FIXME: This must be redone 3004: "Antingen %s eller '%s' frvntad", 3005: "'%s' frvntad", # From xmlproc.XMLCommonParser 3006: "Antingen SYSTEM eller PUBLIC frvntad", 3007: "Textdeklarationen mste st frst i entiteten", 3008: "XML-deklarationen mste st frst i dokumentet", 3009: "Flera textdeklarationer i samma entitet", 3010: "Flera textdeklarationer i samma dokument", 3011: "XML-version saknas i XML-deklarationen", 3012: "'Standalone'-deklaration i textdeklarationen r inte tilltet", # From xmlproc.XMLProcessor 3013: "Syntaxfel", 3014: "Fr tidigt dokumentslut, elementet '%s' r inte stngt", 3015: "Fr tidigt dokumentslut, rotelement saknas", 3016: "Attributet '%s' anvnt tv gnger", 3017: "Endast ett rotelement r tilltet", 3018: "Olovlig teckennummer ('%d') i teckenreferansen", 3019: "Entitets-upprepning upptckt", 3020: "Externa entitets-referanser r inte tilltna i attributvrden", 3021: "Entiteten '%s' r inte deklarerad", 3022: "'<' er inte tilltet i attributvrdet", 3023: "Sluttagg fr '%s' istllet fr frvntad '%s'", 3024: "Finner elementet '%s' sluttagg, men inte dess starttagg", 3025: "']]>' inte tilltet i textdata", 3027: "Inget giltigt teckennummer", 3028: "Teckenreferanser r inte tilltna utanfr rotelementet", 3029: "Textdata r inte tilltet utanfr rotelementet", 3030: "Entitetsreferanser r inte tilltna utanfr rotelementet", 3031: "Referanser till icke 'parsade' entiteter tillts inte i elementinnhllet", 3032: "Multipla dokumenttypsdeklarationer", 3033: "Dokumenttypsdeklarationer tillts inte i rotelementet", 3034: "Det interna DTD-subsettet avslutas fr tidigt", 3042: "Element verskrider entitetsgrns", # From xmlproc.DTDParser 3035: "Parameterentiteter kan inte vara 'oparsade'", 3036: "Parameterentitetsreferanser tillts inte inne i deklarationer i det interna DTD-subsettet", 3037: "Externa entitetsreferanser tillts inte i entitetsdeklarationer", 3038: "Parameterentiteten '%s' r inte deklarerad", 3039: "Frvntat attributtyp eller lista av alternativ", 3040: "Val- och sekvenslistor kan inte blandas", 3041: "'Villkorssektioner' r inte tilltna i den interna DTD-delmngden (subsetet)", 3043: "'Villkorssektionen' r inte stngd", 3044: "Symbolen '%s' har definerats mer n en gng", 3045: "Processinstruktionsnamn som brjar med 'xml' r reserverade", 3046: "Systemet stder inte anvnd XML-versjon", # From regular expressions that were not matched 3900: "Inget giltigt namn", 3901: "Inget giltigt versionsnummer", 3902: "Inget giltigt teckenkodsnamn", 3903: "Ingen giltig kommentar", 3905: "Inget giltigt hexadecimalt tal", 3906: "Inget giltigt tal", 3907: "Ingen giltig parameterentitetsreferans", 3908: "Ingen giltig attributtyp", 3909: "Inge giltigt attributstandardvrde", 3910: "Ikke en gyldig attributt-standard-verdi", 3911: "Ikke en gyldig verdi for 'standalone'", # --- Internal errors: 4000-4999 4000: "Internt fel: Entitetsstacken korrupt.", 4001: "Internt fel: Entitetsreferans frvntad.", 4002: "Internt fel: Oknt felmeddelande %d.", 4003: "Internt fel: Externa parameterentiteter tillts inte i deklarationer.", # --- XCatalog errors: 5000-5099 5000: "Oknt XCatalog-element: %s.", 5001: "Ndvndigt XCatalog-attribut %s p %s saknas.", # --- SOCatalog errors: 5100-5199 5100: "Konstruktionen: %s r ogiltig eller saknar std.", }) # Errors in French # Contributed by Alexandre Fayolle, Logilab. Alexandre.Fayolle@logilab.fr french = english.copy() french.update({ # Les termes franais utiliss sont tirs de l'ouvrage # XML, Langage et applications, Alain Michard, Eyrolles # ISBN 2-212-09052-8 # --- Warnings: 1000-1999 1000: "Prfixe de domaine nominal non dclar '%s'", 1002: "Encodage non support '%s'", 1003: "Syntaxe de domaine nominal obsolte", 1005: "Caractre numro '%d' non support dans la rfrence de caractre", 1006: "L'lment '%s' a une liste d'attributs mais pas de dclaration d'lment", 1007: "L'attribute '%s' est dfini plus d'une fois", 1008: "Modle de contenu ambigu", # --- Namespace warnings 1900: "Les prfixes de domaines nominaux ne peuvent contenir le caractre ':'", 1901: "L'URI du domaine nominal ne doit pas tre vide", 1902: "Le prfixe du domaine nominal n'est pas dclar", 1903: "Le nom d'attribut n'est pas unique aprs traitement des domaines nominaux", # --- Validity errors: 2000-2999 2000: "La valeur de l'attribut '%s' ne correspond pas la valeur impose", 2001: "L'lment '%s' ne peut figurer cet endroit", 2002: "L'lment racine du document '%s' ne correspond pas la racine dclare", 2003: "L'lment '%s' n'a pas t dclar", 2004: "L'lment '%s' est termin, mais il n'est pas complet", 2005: "Les donnes ne sont pas autorises comme contenu de cet lment", 2006: "L'attribut '%s' n'a pas t dclar", 2007: "L'ID '%s' apparat plusieurs fois dans le document", 2008: "Seules les entits non XML sont permises dans les attributs ENTITY", 2009: "La notation '%s' n'a pas t dclare", 2010: "L'attribut requis '%s' est absent", 2011: "L'attribut IDREF point sur un ID inexistant '%s'", 2012: "L'lment '%s' est dclar plus d'une fois", 2013: "Un seul attribut ID par type d'lment", 2014: "Les attributs ID nepeuvent tre #FIXED ou avoir de valeur par dfaut", 2015: "xml:space doit tre de type numration", 2016: "xml:space doit avoir comme valeurs possibles 'default' et 'preserve'", 2017: "'%s' n'est pas une valeur autorise pour l'attribut '%s'", 2018: "La valeur de l'attribut '%s' doit tre un nom valide", 2019: "La valeur de l'attribut '%s' n'est pas un identifiant de nom valide", 2020: "La valeur de l'attribut '%s' n'est pas une liste d'identifiants de noms valides", 2021: "L'identifiant '%s' dans la valeur de l'attribut '%s' n'est pas valide", 2022: "L'attribut notation '%s' utilise la notation non dclare '%s'", 2023: "L'entit non XML '%s' utilise la notation non dclare '%s'", # --- Well-formedness errors: 3000-3999 # From xmlutils 3000: "Impossible d'ouvrir la ressource '%s'", 3001: "Construction commence mais jamais acheve", 3002: "Caractres d'espacement attendus cet endroit", 3003: "Impossible de faire correspondre '%s'", ## FIXME: This must be redone 3004: "'%s' ou '%s' tait attendu", 3005: "'%s' tat attendu", # From xmlproc.XMLCommonParser 3006: "SYSTEM ou PUBLIC tait attendu", 3007: "La dclaration de texte doit apparatre en premier dans une entit", 3008: "La dclaration XML doit apparatre en premier dans un document", 3009: "Plusieurs dclarations de texte dans une seule entit", 3010: "Plusieurs dclarations XML dans le document", 3011: "Il manque la versin d'XML dans la dclaratino XML", 3012: "Une dclaration indpendante de texte sont interdites", 3045: "Les noms de cibles d'instruction de traitement commenant par 'xml' sont rservs", 3046: "Version de XML non supporte", # From xmlproc.XMLProcessor 3013: "Construction illgale", 3014: "Fin de document prmature, l'lment '%s' n'est pas ferm", 3015: "Fin de document prmature, pas d'lment racine", 3016: "L'attribut '%s' apparit deux fois", 3017: "Les lments ne peuvent apparatre l'extrieur de l'lment racine", 3018: "Caractre numro '%d' non support dans la rfrence de caractre", 3019: "Une entit rcursive a t dtecte", 3020: "Les rfrences des entits externes sont interdites dans les valeurs d'attributs", 3021: "L'entit '%s' n'a pas t dclare", 3022: "'<' est interdit dans les valeurs d'attributs", 3023: "La balise de fin pour '%s' a t vue, alors que '%s' tait attendu", 3024: "L'lment'%s' n'a pas t ouvert", 3025: "']]>' ne doit pas apparatre dans les sections littrales", 3027: "Numro de caractre invalide", 3028: "Les rfrences de caractres sont interdites en dehors de l'lment racine", 3029: "Les sections littrales sont interdites en dehors de l'lment racine", 3030: "Les rfrences des entits sont interdites en dehors de l'lment racine", 3031: "Les rfrences des entits non XML sont interdites dans un lment", 3032: "Il y a de multiples dclaratinos de type de document", 3033: "La dclaration de type de document est interdite dans l'lment racine", 3034: "Fin prmature de la DTD interne", 3042: "Un lment chevauche les limites d'une entit", # From xmlproc.DTDParser 3035: "Les entits paramtres ne peuvent pas tre drfrences", 3036: "Les rfrences des entits paramtres sont interdites dans la DTD interne", 3037: "Les rfrences des entits externes sont interdites dans le texte de remplacement", 3038: "L'entit paramtre '%s' est inconnue", 3039: "Un type une liste de valeurs possibles est attendu", 3040: "Les liste de choix et les listes de squences ne peuvent tre mlanges", 3041: "Les sections conditionnelles sont interdites dans la DTD interne", 3043: "La section conditionnelle n'est pas ferme", 3044: "Le marqueur '%s' est dfini plusieurs fois", # next: 3047 # From regular expressions that were not matched 3900: "Nom invalide", 3901: "Numro de version invalide (%s)", 3902: "Nom d'encodage invalide", 3903: "Commentaire invalide", 3905: "Nombre hexadcimal invalide", 3906: "Nombre invalide", 3907: "Rfrence un paramtre invalide", 3908: "Type d'attribut invalide", 3909: "Dfinitionde valeur par dfaut d'attribut invalide", 3910: "Valeur d'attribut numr invalide", 3911: "Dclaration autonome invalide", # --- Internal errors: 4000-4999 4000: "Erreur interne : pile dentits casse", 4001: "Erreur interne : rfrence une entit attendue.", 4002: "Erreur interne : numro d'erreur inconnu.", 4003: "Erreur interne : rfrence un PE externe interdite dans la dclaration", # --- XCatalog errors: 5000-5099 5000: "L'lment de XCatalog est inconnu : %s.", 5001: "L'attribut de XCatalog %s requis sur %s est manquant.", # --- SOCatalog errors: 5100-5199 5100: "Construction invalide ou non supporte : %s.", }) # Errors in Spanish # Contributed by Ricardo Javier Cardenes (ricardo@conysis.com) spanish = { # --- Warnings: 1000-1999 1000: "Prefijo de espacio de nombres sin declarar '%s'", 1002: "Codificacin no soportada '%s'", 1003: "Sintaxis de espacio de nombres obsoleta", 1005: "Caracter nmero '%d' no soportado en la referencia a caracter", 1006: "El elemento '%s' tiene lista de atributos, pero no declaracin de elemento", 1007: "El atributo '%s' est definido ms de una vez", 1008: "Modelo de contenido ambiguo", # --- Namespace warnings 1900: "Los prefijos de espacio de nombres no pueden contener ':'.", 1901: "Las URI de los espacios de nombre no pueden estar vacas", 1902: "Prefijo de espacio de nombres sin declarar", 1903: "Nombres de atributo repetidos despus de procesar el espacio de nombres", # --- Validity errors: 2000-2999 2000: "El valor real del atributo '%s' no se corresponde al valor fijado", 2001: "No se permite aqu el elemento '%s'", 2002: "El elemento '%s' raz del documento no es el mismo que se declar", 2003: "El elemento '%s' no est declarado", 2004: "El elemento '%s' termina antes de encontrar los elementos requeridos (%s)", 2005: "No se permite texto en el contenido de este elemento", 2006: "El atributo '%s' no ha sido declarado", 2007: "El ID '%s' aparece ms de una vez en el documento", 2008: "Slo se permiten entidades sin analizar como valores de los atributos ENTITY", 2009: "No est declarada la notacin '%s'", 2010: "No est presente el atributo '%s' necesario", 2011: "IDREF referida a un ID '%s', que no existe", 2012: "El elemento '%s' est declarado ms de una vez", 2013: "Slo se permite un atributo ID por cada tipo de elemento", 2014: "Los atributos ID no pueden ser #FIXED ni tener valor por defecto", 2015: "xml:space debe ser declarado como tipo enumerado", 2016: "xml:space debe tener exactamente los valores 'default' y 'preserve'", 2017: "'%s' no es un tipo vlido para el atributo '%s'", 2018: "El valor del atributo '%s' debe ser un nombre vlido", 2019: "El valor del atributo '%s' no es un NMTOKEN vlido", 2020: "El valor del atributo '%s' no es un NMTOKENS vlido", 2021: "El smbolo '%s' en el valor del atributo '%s' no es un nombre vlido", 2022: "El atributo de notacin '%s' usa la notacin '%s', que no est declarada", 2023: "La entidad sin analizar '%s' usa la notacin '%s', que no est declarada", 2024: "No se puede resolver la URI relativa '%s' si se desconoce la URI del documento", 2025: "No se encuentra el elemento '%s' antes del '%s'", # --- Well-formedness errors: 3000-3999 # From xmlutils 3000: "No pude abrir el recurso '%s'", 3001: "Se empez la construccin, pero no se pudo completar", 3002: "Aqu se esperaba un espacio en blanco", 3003: "'%s' no se corresponde", ## FIXME: This must be redone 3004: "Se esperaba %s o '%s'", 3005: "Se esperaba '%s'", 3047: "La codificacin '%s' es conflictiva con la autodetectada", 3048: "Problema de conversin de conjunto de caracteres: %s", # From xmlproc.XMLCommonParser 3006: "Se esperaba SYSTEM o PUBLIC", 3007: "La declaracin de texto debe aparecer la primera en la entidad", 3008: "La declaracin XML debe aparecer la primera en el documento", 3009: "Varias declaraciones de texto en la misma entidad", 3010: "Mltiples declaraciones XML en el mismo documento", 3011: "Falta la versin en la declaracin XML", 3012: "No se permite una declaracin 'standalone' en una declaracin de texto", 3045: "Los nombres de PI que comienzan por 'xml' estn reservados", 3046: "Versin XML no soportada", # From xmlproc.XMLProcessor 3013: "Construccin ilegal", 3014: "El documento acab prematuramente. No se cerr el elemento '%s'", 3015: "Fin prematuro del documento. No hay elemento raz", 3016: "El atributo '%s' est duplicado", 3017: "No se permiten elementos fuera del raz", 3018: "Caracter ilegal nmero '%d' en la referencia a caracter", 3019: "Detectada recursividad de entidades", 3020: "No se permiten referencias a entidades externas en los valores de los atributos", 3021: "Entidad '%s' sin declarar", 3022: "No se permite '<' en los valores de atributos", 3023: "Se encontr la etiqueta de fin de '%s', pero se esperaba '%s'", 3024: "Element '%s' not open", 3025: "No debe aparecer ']]>' dentro de datos de texto", 3027: "No es un nmero de caracter vlido", 3028: "No se permite la referencia a caracteres fuera del elemento raz", 3029: "No se admite texto fuera del elemento raz", 3030: "No se admiten referencias a entidades fuera del elemento raz", 3031: "No se admiten referencias a entidades sin analizar en el contenido de un elemento", 3032: "Mltiples declaraciones de tipo de documento", 3033: "No se admite una declaracin de tipo de documento dentro del elemento raz", 3034: "Fin prematuro de un subconjunto interno de DTD", 3042: "Un elemento cruza los lmites de la entidad", # From xmlproc.DTDParser 3035: "Las entidades paramtricas no pueden ser de tipo 'unparsed'", 3036: "No se permiten referencias a entidades paramtricas en un subconjunto interno de declaraciones", 3037: "No se permiten referencias a entidades externas en texto de reemplazo de entidades", 3038: "Entidad paramtrica desconocida '%s'", 3039: "Se esperaba un tipo o una lista de alternativas", 3040: "No se puede mezclar listas secuenciales con alternativas", 3041: "No se admiten secciones condicionales en subconjuntos internos", 3043: "Seccin condicional sin cerrar", 3044: "Se defini el smbolo '%s' ms de una vez", # next: 3049 # From regular expressions that were not matched 3900: "No es un nombre vlido", 3901: "No es un nmero de versin vlido (%s)", 3902: "No es un nombre de codificacin vlido", 3903: "No es un comentario vlido", 3905: "No es un nmero hexadecimal vlido", 3906: "No es un nmero vlido", 3907: "No es una referencia a parmetro vlida", 3908: "No es un tipo de atributo vlido", 3909: "No es una definicin de atributo por defecto vlida", 3910: "No es un valor de atributo enumerado vlido", 3911: "No es una declaracin 'standalone' vlida", # --- Internal errors: 4000-4999 4000: "Error interno: Pila de la entidad corrupta", 4001: "Error interno: Se esperaba una referencia a entidad.", 4002: "Error interno: Nmero de error desconocido.", 4003: "Error interno: No se admiten refrencias PE externas en las declaraciones", # --- XCatalog errors: 5000-5099 5000: "Elemento XCatalog desconocido: %s.", 5001: "Falta el atributo XCatalog %s necesario en %s.", # --- SOCatalog errors: 5100-5199 5100: "Construccin invlida o no soportada: %s.", } # Updating the error hash add_error_list("en", english) add_error_list("no", norsk) add_error_list("sv", svenska) add_error_list("fr", french) add_error_list("es", spanish) # Checking def _test(): def compare(l1, l2): for key in l1: if not key in l2: print "l1:", key for key in l2: if not key in l1: print "l2:", key en = english.keys() no = norsk.keys() sv = svenska.keys() fr = french.keys() es = spanish.keys() en.sort() no.sort() sv.sort() fr.sort() es.sort() print "en == no" compare(en, no) print "en == sv" compare(en, sv) print "en == fr" compare(en, fr) print "en == es" compare(en, es) if __name__ == "__main__": _test() PyXML-0.8.2/xml/parsers/xmlproc/namespace.py0100644000076400001440000001135507413601752020173 0ustar martinusers""" A parser filter for namespace support. Placed externally to the parser for efficiency reasons. $Id: namespace.py,v 1.5 2024/12/30 12:09:14 loewis Exp $ """ import string import xmlapp # --- ParserFilter class ParserFilter(xmlapp.Application): "A generic parser filter class." def __init__(self): xmlapp.Application.__init__(self) self.app=xmlapp.Application() def set_application(self,app): "Sets the application to report events to." self.app=app # --- Methods inherited from xmlapp.Application def set_locator(self,locator): xmlapp.Application.set_locator(self,locator) self.app.set_locator(locator) def doc_start(self): self.app.doc_start() def doc_end(self): self.app.doc_end() def handle_comment(self,data): self.app.handle_comment(data) def handle_start_tag(self,name,attrs): self.app.handle_start_tag(name,attrs) def handle_end_tag(self,name): self.app.handle_end_tag(name) def handle_data(self,data,start,end): self.app.handle_data(data,start,end) def handle_ignorable_data(self,data,start,end): self.app.handle_ignorable_data(data,start,end) def handle_pi(self,target,data): self.app.handle_pi(target,data) def handle_doctype(self,root,pubID,sysID): self.app.handle_doctype(root,pubID,sysID) def set_entity_info(self,xmlver,enc,sddecl): self.app.set_entity_info(xmlver,enc,sddecl) # --- NamespaceFilter class NamespaceFilter(ParserFilter): """An xmlproc application that processes qualified names and reports them as 'URI local-part' names. It reports errors through the error reporting mechanisms of the parser.""" def __init__(self,parser): ParserFilter.__init__(self) self.ns_map={} # Current prefix -> URI map self.ns_stack=[] # Pushed for each element, used to maint ns_map self.rep_ns_attrs=0 # Report xmlns-attributes? self.parser=parser def set_report_ns_attributes(self,action): "Tells the filter whether to report or delete xmlns-attributes." self.rep_ns_attrs=action # --- Overridden event methods def handle_start_tag(self,name,attrs): old_ns={} # Reset ns_map to these values when we leave this element del_ns=[] # Delete these prefixes from ns_map when we leave element # attrs=attrs.copy() Will have to do this if more filters are made # Find declarations, update self.ns_map and self.ns_stack for (a,v) in attrs.items(): if a[:6]=="xmlns:": prefix=a[6:] if string.find(prefix,":")!=-1: self.parser.report_error(1900) if v=="": self.parser.report_error(1901) elif a=="xmlns": prefix="" else: continue if self.ns_map.has_key(prefix): old_ns[prefix]=self.ns_map[prefix] else: del_ns.append(prefix) if prefix=="" and v=="": del self.ns_map[prefix] else: self.ns_map[prefix]=v if not self.rep_ns_attrs: del attrs[a] self.ns_stack.append((old_ns,del_ns)) # Process elem and attr names name=self.__process_name(name) parts=string.split(name) if len(parts)>1: ns=parts[0] else: ns=None for (a,v) in attrs.items(): del attrs[a] aname=self.__process_name(a,ns) if attrs.has_key(aname): self.parser.report_error(1903) attrs[aname]=v # Report event self.app.handle_start_tag(name,attrs) def handle_end_tag(self,name): name=self.__process_name(name) # Clean up self.ns_map and self.ns_stack (old_ns,del_ns)=self.ns_stack[-1] del self.ns_stack[-1] self.ns_map.update(old_ns) for prefix in del_ns: del self.ns_map[prefix] self.app.handle_end_tag(name) # --- Internal methods def __process_name(self,name,default_to=None): n=string.split(name,":") if len(n)>2: self.parser.report_error(1900) return name elif len(n)==2: if n[0]=="xmlns": return name try: return "%s %s" % (self.ns_map[n[0]],n[1]) except KeyError: self.parser.report_error(1902) return name elif default_to!=None: return "%s %s" % (default_to,name) elif self.ns_map.has_key("") and name!="xmlns": return "%s %s" % (self.ns_map[""],name) else: return name PyXML-0.8.2/xml/parsers/xmlproc/utils.py0100644000076400001440000001513107463727455017411 0ustar martinusers""" Some utilities for use with xmlproc. $Id: utils.py,v 1.7 2025/05/01 09:02:37 loewis Exp $ """ import xmlapp, sys, string, types replace = string.replace if sys.platform[ : 4] == "java": from java.lang import Exception try: from codecs import EncodedFile except ImportError, e: # if we are on Python 1.5 def EncodedFile(file, encoding): return file # --- XMLParseException class XMLParseException(Exception): pass # --- ErrorPrinter class ErrorPrinter(xmlapp.ErrorHandler): """An error handler that prints out warning messages.""" def __init__(self, locator, level = 0, out = sys.stderr): xmlapp.ErrorHandler.__init__(self, locator) self.level = level self.out = out def warning(self,msg): if self.level < 1: self.out.write("WARNING: %s at %s\n" % (msg,self.__get_location())) def error(self,msg): if self.level < 2: self.out.write("ERROR: %s at %s\n" % (msg,self.__get_location())) def fatal(self,msg): self.out.write("ERROR: %s at %s\n" % (msg,self.__get_location())) def __get_location(self): return "%s:%d:%d" % (self.locator.get_current_sysid(), self.locator.get_line(), self.locator.get_column()) # --- ErrorRaiser class ErrorRaiser(xmlapp.ErrorHandler): """An error handler that raises exceptions.""" def __init__(self, locator = None, level = 0): xmlapp.ErrorHandler.__init__(self, locator) self.level = level def warning(self, msg): if self.level < 1: raise XMLParseException(msg) def error(self, msg): if self.level < 2: raise XMLParseException(msg) def fatal(self, msg): raise XMLParseException(msg) # --- ErrorCounter class ErrorCounter(xmlapp.ErrorHandler): """An error handler that counts errors.""" def __init__(self, locator = None): xmlapp.ErrorHandler.__init__(self, locator) self.reset() def reset(self): self.warnings=0 self.errors =0 self.fatals =0 def warning(self,msg): self.warnings=self.warnings+1 def error(self,msg): self.errors=self.errors+1 def fatal(self,msg): self.fatals=self.fatals+1 # --- ESIS document handler class ESISDocHandler(xmlapp.Application): def __init__(self,writer=sys.stdout): self.writer=writer def handle_pi(self,target,data): self.writer.write("?"+target+" "+data+"\n") def handle_start_tag(self,name,amap): self.writer.write("("+name+"\n") for a_name in amap.keys(): self.writer.write("A"+a_name+" "+amap[a_name]+"\n") def handle_end_tag(self,name): self.writer.write(")"+name+"\n") def handle_data(self,data,start_ix,end_ix): self.writer.write("-"+data[start_ix:end_ix]+"\n") # --- XML canonizer class Canonizer(xmlapp.Application): def __init__(self,writer=sys.stdout): self.elem_level=0 self.writer=writer def handle_pi(self,target, remainder): if target!="xml": self.writer.write("") def handle_start_tag(self,name,amap): self.writer.write("<"+name) a_names=amap.keys() a_names.sort() for a_name in a_names: self.writer.write(" "+a_name+"=\"") self.write_data(amap[a_name]) self.writer.write("\"") self.writer.write(">") self.elem_level=self.elem_level+1 def handle_end_tag(self,name): self.writer.write("") self.elem_level=self.elem_level-1 def handle_ignorable_data(self,data,start_ix,end_ix): self.write_data(data[start_ix:end_ix]) def handle_data(self,data,start_ix,end_ix): if self.elem_level>0: self.write_data(data[start_ix:end_ix]) def write_data(self,data): data=replace(data,"&","&") data=replace(data,"<","<") data=replace(data,"\"",""") data=replace(data,">",">") data=replace(data,chr(9)," ") data=replace(data,chr(10)," ") data=replace(data,chr(13)," ") self.writer.write(data) # --- DocGenerator def escape_content(str): return replace(replace(str, "&", "&"), "<", "<") def escape_attval(str): return replace(replace(replace(str, "&", "&"), "<", "<"), '"', """) class DocGenerator(xmlapp.Application): def __init__(self, out = None): if not out: self.out = EncodedFile(sys.stdout, "utf-8") else: self.out = out def handle_pi(self, target, remainder): self.out.write("" % (target, remainder)) def handle_start_tag(self,name,amap): self.out.write("<"+name) for (name, value) in amap.items(): self.out.write(' %s="%s"' % (name, escape_attval(value))) self.out.write(">") def handle_end_tag(self,name): self.out.write("" % name) def handle_ignorable_data(self,data,start_ix,end_ix): self.out.write(escape_content(data[start_ix:end_ix])) def handle_data(self,data,start_ix,end_ix): self.out.write(escape_content(data[start_ix:end_ix])) # --- DictResolver class DictResolver(xmlapp.PubIdResolver): def __init__(self, mapping = None): if mapping == None: mapping = {} self.mapping = mapping def resolve_pe_pubid(self, pubid, sysid): return self.mapping.get(pubid, sysid) def resolve_doctype_pubid(self, pubid, sysid): return self.mapping.get(pubid, sysid) def resolve_entity_pubid(self, pubid, sysid): return self.mapping.get(pubid, sysid) # --- Location class Location: def __init__(self, locator): self._sysid = locator.get_current_sysid() self._line = locator.get_line() self._column = locator.get_column() def get_sysid(self): return self._sysid def get_line(self): return self._line def get_column(self): return self._column def __str__(self): return "%s:%s:%s" % (self._sysid, self._line, self._column) # --- Various DTD and validation tools def load_dtd(sysid): import dtdparser,xmldtd dp=dtdparser.DTDParser() dtd=xmldtd.CompleteDTD(dp) dp.set_dtd_consumer(dtd) dp.parse_resource(sysid) return dtd def validate_doc(dtd,sysid): import xmlval parser=xmlval.XMLValidator() parser.dtd=dtd # FIXME: what to do if there is a !DOCTYPE? parser.set_error_handler(ErrorPrinter(parser)) parser.parse_resource(sysid) #dtd.rollback_changes() PyXML-0.8.2/xml/parsers/xmlproc/xcatalog.py0100644000076400001440000000443507413601752020042 0ustar martinusers""" Support for XCatalog catalog files. $Id: xcatalog.py,v 1.9 2024/12/30 12:09:14 loewis Exp $ """ import catalog,xmlapp,xmlproc # --- An XCatalog parser factory class XCatParserFactory: def __init__(self,error_lang=None): self.error_lang=error_lang def make_parser(self,sysid): return XCatalogParser(self.error_lang) class FancyParserFactory: def __init__(self,error_lang=None): self.error_lang=error_lang def make_parser(self,sysid): if sysid[-4:]==".soc": return catalog.CatalogParser(self.error_lang) elif sysid[-4:]==".xml": return XCatalogParser(self.error_lang) else: return catalog.CatalogParser(self.error_lang) # --- An XCatalog 0.1 parser class XCatalogParser(catalog.AbstrCatalogParser,xmlapp.Application): def __init__(self,error_lang=None): catalog.AbstrCatalogParser.__init__(self) xmlapp.Application.__init__(self) self.error_lang=error_lang def parse_resource(self,sysid): parser=xmlproc.XMLProcessor() self.parser=parser parser.set_application(self) if self.error_lang!=None: parser.set_error_language(self.error_lang) parser.set_error_handler(self.err) parser.parse_resource(sysid) del self.parser def handle_start_tag(self,name,attrs): try: if name=="Base": self.app.handle_base(attrs["HRef"]) elif name=="Map": self.app.handle_public(attrs["PublicID"],attrs["HRef"]) elif name=="Delegate": self.app.handle_delegate(attrs["PublicID"],attrs["HRef"]) elif name=="Extend": self.app.handle_catalog(attrs["HRef"]) elif name!="XCatalog": self.parser.report_error(5000,(name,)) except KeyError,e: if e.args[0] in ("HRef" , "PublicID"): self.parser.report_error(5001,(e.args[0],name)) else: raise e # This came from the application, pass it on # implementing Locator methods def get_current_sysid(self): return self.parser.get_current_sysid() def get_line(self): return self.parser.get_line() def get_column(self): return self.parser.get_column() PyXML-0.8.2/xml/parsers/xmlproc/xmlapp.py0100644000076400001440000001562707534565153017556 0ustar martinusers""" This file contains the default classes that are used to receive events from the XML parser. All these classes are meant to be subclassed (or imitated) by clients that want to handle these functions themselves. Application is the class that receives document data from the parser, and is probably the one most people want. $Id: xmlapp.py,v 1.12 2025/08/13 09:28:51 afayolle Exp $ """ import sys,urllib2,urlparse from xmlutils import * # ============================== # The default application class # ============================== class Application: """This is the class that represents the application that receives parsed data from the parser. It is meant to be subclassed by users.""" def __init__(self): self.locator=None def set_locator(self,locator): """Gives the application an object to ask for the current location. Called automagically by the parser.""" self.locator=locator def doc_start(self): "Notifies the application of the start of the document." pass def doc_end(self): "Notifies the application of the end of the document." pass def handle_comment(self,data): "Notifies the application of comments." pass def handle_start_tag(self,name,attrs): "Notifies the application of start tags (and empty element tags)." pass def handle_end_tag(self,name): "Notifies the application of end tags (and empty element tags)." pass def handle_data(self,data,start,end): "Notifies the application of character data." pass def handle_ignorable_data(self,data,start,end): "Notifies the application of character data that can be ignored." pass def handle_pi(self,target,data): "Notifies the application of processing instructions." pass def handle_doctype(self,root,pubID,sysID): "Notifies the application of the document type declaration." pass def set_entity_info(self,xmlver,enc,sddecl): """Notifies the application of information about the current entity supplied by an XML or text declaration. All three parameters will be None, if they weren't present.""" pass # ============================== # The public identifier resolver # ============================== class PubIdResolver: """An application class that resolves public identifiers to system identifiers.""" def resolve_pe_pubid(self,pubid,sysid): """Maps the public identifier of a parameter entity to a system identifier. The default implementation just returns the system identifier.""" return sysid def resolve_doctype_pubid(self,pubid,sysid): """Maps the public identifier of the DOCTYPE declaration to a system identifier. The default implementation just returns the system identifier.""" return sysid def resolve_entity_pubid(self,pubid,sysid): """Maps the public identifier of an external entity to a system identifier. The default implementation just returns the system identifier.""" return sysid # ============================== # The default error handler # ============================== class ErrorHandler: """An error handler for the parser. This class can be subclassed by clients that want to use their own error handlers.""" def __init__(self,locator): self.locator=locator def set_locator(self,loc): self.locator=loc def get_locator(self): return self.locator def warning(self,msg): "Handles a non-fatal error message." pass def error(self,msg): self.fatal(msg) # "The reports of the error's fatality are much exaggerated" # --Paul Prescod def fatal(self,msg): "Handles a fatal error message." if self.locator==None: print "ERROR: "+msg else: print "ERROR: "+msg+" at %s:%d:%d" % (self.locator.get_current_sysid(),\ self.locator.get_line(),\ self.locator.get_column()) print "TEXT: '%s'" % (self.locator.data[self.locator.pos:\ self.locator.pos+10]) sys.exit(1) # ============================== # The default entity handler # ============================== class EntityHandler: "An entity handler for the parser." def __init__(self,parser): self.parser=parser def resolve_ent_ref(self,entname): """Resolves a general entity reference and returns its contents. The default method only resolves the predefined entities. Returns a 2-tuple (n,m) where n is true if the entity is internal. For internal entities m is the value, for external ones it is the system id.""" try: return (1,predef_ents[entname]) except KeyError: self.parser.report_error(3021,entname) return (1,"") # ============================== # A DTD event handler # ============================== class DTDConsumer: """Represents an XML DTD. This class can be subclassed by applications which want to handle the DTD information themselves.""" def __init__(self,parser): self.parser=parser def dtd_start(self): "Called when DTD parsing starts." pass def dtd_end(self): "Called when the DTD is completely parsed." pass def new_general_entity(self,name,val): "Receives internal general entity declarations." pass def new_external_entity(self,ent_name,pub_id,sys_id,ndata): """Receives external general entity declarations. 'ndata' is the empty string if the entity is parsed.""" pass def new_parameter_entity(self,name,val): "Receives internal parameter entity declarations." pass def new_external_pe(self,name,pubid,sysid): "Receives external parameter entity declarations." pass def new_notation(self,name,pubid,sysid): "Receives notation declarations." pass def new_element_type(self,elem_name,elem_cont): "Receives the declaration of an element type." pass def new_attribute(self,elem,attr,a_type,a_decl,a_def): "Receives the declaration of a new attribute." pass def handle_comment(self,contents): "Receives the contents of a comment." pass def handle_pi(self,target,data): "Receives the target and data of processing instructions." pass # ============================== # An inputsource factory # ============================== class InputSourceFactory: "A class that creates file-like objects from system identifiers." def create_input_source(self,sysid): if sysid[1:3]==":\\" or urlparse.urlparse(sysid)[0] == '': return open(sysid) else: return urllib2.urlopen(sysid) PyXML-0.8.2/xml/parsers/xmlproc/xmldtd.py0100644000076400001440000006746507461630230017544 0ustar martinusers""" These are the DTD-aware classes of xmlproc. They provide both the DTD event consumers for the DTD parser as well as the objects that store DTD information for retrieval by clients (including the validating parser). $Id: xmldtd.py,v 1.18 2025/04/13 19:13:16 larsga Exp $ """ import types from xmlutils import * from xmlapp import * # ============================== # WFC-DTD # ============================== class WFCDTD(DTDConsumer): "DTD-representing class for the WFC parser." def __init__(self,parser): DTDConsumer.__init__(self,parser) self.dtd_listener=DTDConsumer(parser) self.reset() def reset(self): "Clears all DTD information." self.gen_ents={} self.param_ents={} self.elems={} self.attrinfo={} self.used_notations={} # Notations used by NOTATION attrs # Adding predefined entities for name in predef_ents.keys(): self.new_general_entity(name,predef_ents[name]) def set_dtd_listener(self,listener): "Registers an object that listens for DTD parse events." self.dtd_listener=listener def resolve_pe(self,name): """Returns the entitiy object associated with this parameter entity name. Throws KeyError if the entity is not declared.""" return self.param_ents[name] def resolve_ge(self,name): """Returns the entitiy object associated with this general entity name. Throws KeyError if the entity is not declared.""" return self.gen_ents[name] def get_general_entities(self): """Returns the names of all declared general entities.""" return self.gen_ents.keys() def get_parameter_entities(self): "Returns the names of all declared parameter entities." return self.param_ents.keys() def get_elem(self,name): """Returns the declaration of this element. Throws KeyError if the element does not exist.""" return self.elems[name] def get_elements(self): "Returns a list of all declared element names." return self.elems.keys() def get_notation(self,name): """Returns the declaration of the notation. Throws KeyError if the notation does not exist.""" raise KeyError(name) def get_notations(self): """Returns the names of all declared notations.""" return [] def get_root_elem(self,name): """Returns the name of the declared root element, or None if none were declared.""" return None # --- Shortcut information for validation def dtd_end(self): "Stores shortcut information." self.attrinfo={} for elem in self.elems.values(): self.attrinfo[elem.get_name()]=(elem.get_default_attributes(), elem.get_fixed_attributes()) self.dtd_listener.dtd_end() def get_element_info(self,name): return self.attrinfo[name] # --- Parse events def new_attribute(self,elem,attr,a_type,a_decl,a_def): "Receives the declaration of a new attribute." self.dtd_listener.new_attribute(elem,attr,a_type,a_decl,a_def) if not self.elems.has_key(elem): self.elems[elem]=ElementTypeAny(elem) # Adding dummy self.elems[elem].add_attr(attr,a_type,a_decl,a_def,self.parser) # --- Echoing DTD parse events def dtd_start(self): self.dtd_listener.dtd_start() # dtd_end is implemented in WFCDTD, no need to repeat here def handle_comment(self, contents): self.dtd_listener.handle_comment(contents) def handle_pi(self, target, data): self.dtd_listener.handle_pi(target, data) def new_general_entity(self,name,val): if self.gen_ents.has_key(name): ## FIXME: May warn return # Keep first decl ent=InternalEntity(name,val) self.gen_ents[name]=ent self.dtd_listener.new_general_entity(name,val) def new_parameter_entity(self,name,val): if self.param_ents.has_key(name): ## FIXME: May warn return # Keep first decl ent=InternalEntity(name,val) self.param_ents[name]=ent self.dtd_listener.new_parameter_entity(name,val) def new_external_entity(self,ent_name,pubid,sysid,ndata): if self.gen_ents.has_key(ent_name): ## FIXME: May warn return # Keep first decl if ndata != None and hasattr(self, "notations"): if not self.notations.has_key(ndata): self.used_notations[ndata]= ent_name ent=ExternalEntity(ent_name,pubid,sysid,ndata) self.gen_ents[ent_name]=ent self.dtd_listener.new_external_entity(ent_name,pubid,sysid,ndata) def new_external_pe(self,name,pubid,sysid): if self.param_ents.has_key(name): ## FIXME: May warn return # Keep first decl ent=ExternalEntity(name,pubid,sysid,"") self.param_ents[name]=ent self.dtd_listener.new_external_pe(name,pubid,sysid) def new_comment(self,contents): self.dtd_listener.new_comment(contents) def new_pi(self,target,rem): self.dtd_listener.new_pi(target,rem) def new_notation(self,name,pubid,sysid): self.dtd_listener.new_notation(name,pubid,sysid) def new_element_type(self,elem_name,elem_cont): self.dtd_listener.new_element_type(elem_name,elem_cont) # ============================== # DTD consumer for the validating parser # ============================== class CompleteDTD(WFCDTD): "Complete DTD handler for the validating parser." def __init__(self,parser): WFCDTD.__init__(self,parser) def reset(self): "Clears all DTD information." WFCDTD.reset(self) self.notations={} self.attlists={} # Attribute lists of elements not yet declared self.root_elem=None self.cmhash={} def get_root_elem(self): "Returns the name of the declared root element." return self.root_elem def get_notation(self,name): """Returns the declaration of the notation. Throws KeyError if the notation does not exist.""" return self.notations[name] def get_notations(self): """Returns the names of all declared notations.""" return self.notations.keys() # --- DTD parse events def dtd_end(self): WFCDTD.dtd_end(self) self.cmhash={} for elem in self.attlists.keys(): self.parser.report_error(1006,elem) self.attlists={} # Not needed any more, can free this memory for notation in self.used_notations.keys(): try: self.get_notation(notation) except KeyError: self.parser.report_error(2022,(self.used_notations[notation], notation)) self.used_notations={} # Not needed, save memory def new_notation(self,name,pubid,sysid): self.notations[name]=(pubid,sysid) self.dtd_listener.new_notation(name,pubid,sysid) def new_element_type(self,elem_name,elem_cont): if self.elems.has_key(elem_name): self.parser.report_error(2012,elem_name) return # Keeping first declaration if elem_cont=="EMPTY": elem_cont=("",[],"") self.elems[elem_name]=ElementType(elem_name,make_empty_model(), elem_cont) elif elem_cont=="ANY": elem_cont=None self.elems[elem_name]=ElementTypeAny(elem_name) else: model=make_model(self.cmhash,elem_cont,self.parser) self.elems[elem_name]=ElementType(elem_name,model,elem_cont) if self.attlists.has_key(elem_name): for (attr,a_type,a_decl,a_def) in self.attlists[elem_name]: self.elems[elem_name].add_attr(attr,a_type,a_decl,a_def,\ self.parser) del self.attlists[elem_name] self.dtd_listener.new_element_type(elem_name,elem_cont) def new_attribute(self,elem,attr,a_type,a_decl,a_def): "Receives the declaration of a new attribute." self.dtd_listener.new_attribute(elem,attr,a_type,a_decl,a_def) try: self.elems[elem].add_attr(attr,a_type,a_decl,a_def,self.parser) except KeyError: try: self.attlists[elem].append((attr,a_type,a_decl,a_def)) except KeyError: self.attlists[elem]=[(attr,a_type,a_decl,a_def)] # ============================== # Represents an XML element type # ============================== class ElementType: "Represents an element type." def __init__(self,name,compiled,original): self.name=name self.attrhash={} self.attrlist=[] self.content_model=compiled self.content_model_structure=original def get_name(self): "Returns the name of the element type." return self.name def get_attr_list(self): """Returns a list of the declared attribute names in the order the attributes were declared.""" return self.attrlist def get_attr(self,name): "Returns the attribute or throws a KeyError if it's not declared." return self.attrhash[name] def add_attr(self,attr,a_type,a_decl,a_def,parser): "Adds a new attribute to the element." if self.attrhash.has_key(attr): parser.report_error(1007,attr) return # Keep first declaration self.attrlist.append(attr) if a_type=="ID": for attr_name in self.attrhash.keys(): if self.attrhash[attr_name].type=="ID": parser.report_error(2013) if a_decl!="#REQUIRED" and a_decl!="#IMPLIED": parser.report_error(2014) elif type(a_type)==types.TupleType and a_type[0]=="NOTATION": for notation in a_type[1]: parser.dtd.used_notations[notation]=attr self.attrhash[attr]=Attribute(attr,a_type,a_decl,a_def,parser) if a_def!=None: self.attrhash[attr].validate(self.attrhash[attr].default,parser) def get_start_state(self): "Return the start state of this content model." return self.content_model["start"] def final_state(self, state): "True if 'state' is a final state." return self.content_model["final"] & state def next_state(self, state, elem_name): """Returns the next state of the content model from the given one when elem_name is encountered. Character data is represented as '#PCDATA'. If 0 is returned the element is not allowed here or if the state is unknown.""" return self.content_model[state].get(elem_name, 0) def next_state_skip(self, state, elem_name): """Assumes that one element has been forgotten and tries to skip forward one state (regardless of what element is attached to the transition) to get to a state where elem_name is legal. Returns a (state, elem) tuple, where elem is the element missing, and state is the state reached by following the elem_name arc after using the missing element. None is returned if no missing element can be found.""" arcs = self.content_model[state] for skipped in arcs.keys(): if self.content_model[arcs[skipped]].has_key(elem_name): arcs2 = self.content_model[arcs[skipped]] return (arcs2[elem_name], skipped) def get_valid_elements(self, state): """Returns a list of the valid elements in the given state, or the empty list if none are valid (or if the state is unknown). If the content model is ANY, the empty list is returned.""" if self.content_model == None: # that is, any return [] # any better ideas? try: return self.content_model[state].keys() except KeyError: return [] def get_content_model(self): """Returns the element content model in (sep,cont,mod) format, where cont is a list of (name,mod) and (sep,cont,mod) tuples. ANY content models are represented as None, and EMPTYs as ("",[],"").""" return self.content_model_structure # --- Methods used to create shortcut validation information def get_default_attributes(self): defs={} for attr in self.attrhash.values(): if attr.get_default()!=None: defs[attr.get_name()]=attr.get_default() return defs def get_fixed_attributes(self): fixed={} for attr in self.attrhash.values(): if attr.get_decl()=="#FIXED": fixed[attr.get_name()]=attr.get_default() return fixed # --- Element types with ANY content class ElementTypeAny(ElementType): def __init__(self,name): ElementType.__init__(self,name,None,None) def get_start_state(self): return 1 def final_state(self,state): return 1 def next_state(self,state,elem_name): return 1 def get_valid_elements(self, state): return [] # any better ideas? can't get DTD here... # ============================== # Attribute # ============================== class Attribute: "Represents a declared attribute." def __init__(self,name,attrtype,decl,default,parser): self.name=name self.type=attrtype self.decl=decl # Normalize the default value before setting it if default!=None and self.type!="CDATA": self.default=string.join(string.split(default)) else: self.default=default # Handling code for special attribute xml:space if name=="xml:space": error = 0 if type(self.type) in StringTypes: parser.report_error(2015) return if len(self.type) < 1 or len(self.type) > 2: error = 1 else: for alt in self.type: if alt not in ["default", "preserve"]: error = 1 if error: parser.report_error(2016) def validate(self,value,parser): "Validates given value for correctness." if type(self.type) not in StringTypes: for val in self.type: if val==value: return parser.report_error(2017,(value,self.name)) elif self.type=="CDATA": return elif self.type=="ID" or self.type=="IDREF" or self.type=="ENTITIY": if not matches(reg_name,value): parser.report_error(2018,self.name) elif self.type=="NMTOKEN": if not matches(reg_nmtoken,value): parser.report_error(2019,self.name) elif self.type=="NMTOKENS": if not matches(reg_nmtokens,value): parser.report_error(2020,self.name) elif self.type=="IDREFS" or self.type=="ENTITIES": for token in string.split(value): if not matches(reg_name,token): parser.report_error(2021,(token,self.name)) def get_name(self): "Returns the attribute name." return self.name def get_type(self): "Returns the type of the attribute. (ID, CDATA etc)" return self.type def get_decl(self): "Returns the declaration (#IMPLIED, #REQUIRED, #FIXED or #DEFAULT)." return self.decl def get_default(self): """Returns the default value of the attribute, or None if none has been declared.""" return self.default # ============================== # Entities # ============================== class InternalEntity: def __init__(self,name,value): self.name=name self.value=value def is_internal(self): return 1 def get_value(self): "Returns the replacement text of the entity." return self.value class ExternalEntity: def __init__(self,name,pubid,sysid,notation): self.name=name self.pubid=pubid self.sysid=sysid self.notation=notation def is_parsed(self): "True if this is a parsed entity." return self.notation=="" def is_internal(self): return 0 def get_pubid(self): "Returns the public identifier of the entity." return self.pubid def get_sysid(self): "Returns the system identifier of the entity." return self.sysid def get_notation(self): "Returns the notation of the entity, or None if there is none." return self.notation # ============================== # Internal classes # ============================== # Non-deterministic state model builder class FNDABuilder: "Builds a finite non-deterministic automaton." def __init__(self): self.__current=0 self.__transitions=[[]] self.__mem=[] def remember_state(self): "Makes the builder remember the current state." self.__mem.append(self.__current) def set_current_to_remembered(self): """Makes the current state the last remembered one. The last remembered one is not forgotten.""" self.__current=self.__mem[-1] def forget_state(self): "Makes the builder forget the current remembered state." del self.__mem[-1] def new_state(self): "Creates a new last state and makes it the current one." self.__transitions.append([]) self.__current=len(self.__transitions)-1 def get_automaton(self): "Returns the automaton produced by the builder." return self.__transitions def get_current_state(self): "Returns the current state." return self.__current def new_transition(self,label,frm,to): "Creates a new transition from frm to to, over label." self.__transitions[frm].append((to,label)) def new_transition_to_new(self,label): """Creates a new transition from the current state to a new state, which becomes the new current state.""" self.remember_state() self.new_state() self.__transitions[self.__mem[-1]].append((self.__current,label)) self.forget_state() def new_transition_cur2rem(self,label): """Adds a new transition from the current state to the last remembered state.""" self.__transitions[self.__current].append((self.__mem[-1],label)) def new_transition_rem2cur(self,label): """Creates a new transition from the current state to the last remembered one.""" self.__transitions[self.__mem[-1]].append((self.__current,label)) def new_transition_2cur(self,frm,label): "Creates a new transition from frm to current state, with label." self.__transitions[frm].append((self.__current,label)) # Content model class class ContentModel: "Represents a singleton content model. (Internal.)" def __init__(self,contents,modifier): self.contents=contents self.modifier=modifier def add_states(self,builder): "Builds the part of the automaton corresponding to this model part." if self.modifier=="?": builder.remember_state() self.add_contents(builder) builder.new_transition_rem2cur("") builder.forget_state() elif self.modifier=="+": self.add_contents(builder) builder.remember_state() self.add_contents(builder,1) builder.set_current_to_remembered() builder.forget_state() elif self.modifier=="*": builder.remember_state() builder.new_transition_to_new("") self.add_contents(builder,1) builder.new_transition_rem2cur("") builder.forget_state() else: self.add_contents(builder) def add_contents(self,builder,loop=0): """Adds the states and transitions belonging to the self.contents parts. If loop is true the states will loop back to the first state.""" if type(self.contents[0])==types.InstanceType: if loop: builder.remember_state() self.contents[0].add_states(builder) builder.new_transition_cur2rem("") builder.set_current_to_remembered() builder.forget_state() else: self.contents[0].add_states(builder) else: if loop: builder.new_transition(self.contents[0], builder.get_current_state(), builder.get_current_state()) else: builder.new_transition_to_new(self.contents[0]) # Sequential content model class SeqContentModel(ContentModel): "Represents a sequential content model. (Internal.)" def add_contents(self,builder,loop=0): if loop: builder.remember_state() for cp in self.contents: cp.add_states(builder) if loop: builder.new_transition_cur2rem("") builder.forget_state() # Choice content model class ChoiceContentModel(ContentModel): "Represents a choice content model. (Internal.)" def add_contents(self,builder,loop=0): builder.remember_state() end_states=[] # The states at the end of each alternative for cp in self.contents: builder.new_state() builder.new_transition_rem2cur("") cp.add_states(builder) end_states.append(builder.get_current_state()) builder.new_state() for state in end_states: builder.new_transition_2cur(state,"") if loop: builder.new_transition_cur2rem("") builder.forget_state() # ============================== # Conversion of FDAs # ============================== def hash(included): "Creates a hash number from the included array." no=0 exp=1L for state in included: if state: no=no+exp exp=exp*2L return no def fnda2fda(transitions,final_state,parser): """Converts a finite-state non-deterministic automaton into a deterministic one.""" # transitions: old FNDA as [[(to,over),(to,over),...], # [(to,over),(to,over),...]] structure # new FDA as [{over:to,over:to,...}, # {over:to,over:to,...}] structure # err: error-handler #print_trans(transitions) transitions.append([]) new_states={} # Compute the e-closure of the start state closure_hash={} start_state=[0]*len(transitions) compute_closure(0,start_state,transitions) state_key=hash(start_state) closure_hash[0]=state_key # Add transitions and the other states add_transitions(0,transitions,new_states,start_state,state_key,parser, closure_hash) states=new_states.keys() states.sort() #print_states(new_states,2) for state in states: if state % 2==1: new_states["start"]=state break new_states["final"]=pow(2L,final_state) return new_states def add_transitions(ix,transitions,new_states,cur_state_list,state_key,parser, closure_hash): "Set up transitions and create new states." new_states[state_key]={} # OK, a new one, create it new_trans={} # Hash from label to a list of the possible destination states # Find all transitions from this set of states and group them by their # labels in the new_trans hash no=0 for old_state in cur_state_list: if old_state: for (to,what) in transitions[no]: if what!="": if new_trans.has_key(what): new_trans[what].append(to) else: new_trans[what]=[to] no=no+1 # Go through the list of transitions, creating new transitions and # destination states in the model for (over,destlist) in new_trans.items(): # creating new state # Reports ambiguity, but rather crudely. Will improve this later. # if len(destlist)>1: # parser.report_error(1008) if len(destlist)==1 and closure_hash.has_key(destlist[0]): # The closure of this state has been computed before, don't repeat new_state=closure_hash[destlist[0]] else: new_inc=[0]*len(transitions) for to in destlist: compute_closure(to,new_inc,transitions) new_state=hash(new_inc) if len(destlist)==1: closure_hash[destlist[0]]=new_state # add transition and destination state new_states[state_key][over]=new_state if not new_states.has_key(new_state): add_transitions(to,transitions,new_states,new_inc,\ new_state,parser,closure_hash) def compute_closure(ix,included,transitions): "Computes the e-closure of this state." included[ix]=1 for (to,what) in transitions[ix]: if what=="" and not included[to]: compute_closure(to,included,transitions) def print_trans(model): ix=0 for transitions in model: print "STATE: %d" % ix for step in transitions: print " TO %d OVER %s" % step ix=ix+1 raw_input() def print_states(states,stop=0): assert not (states.has_key("start") or states.has_key("final")) for trans_key in states.keys(): trans=states[trans_key] print "State: "+`trans_key` for (to,what) in trans: try: print " To: "+`to`+" over: "+what except TypeError: print "ERROR: "+`what` if stop>1: raw_input() if stop: raw_input() def make_empty_model(): "Constructs a state model for empty content models." return { 1:{}, "final":1, "start":1 } def make_model(cmhash,content_model,err): "Creates an FDA from the content model." cm=`content_model` if cmhash.has_key(cm): return cmhash[cm] else: content_model=make_objects(content_model) builder=FNDABuilder() content_model.add_states(builder) content_model=fnda2fda(builder.get_automaton(), builder.get_current_state(), err) cmhash[cm]=content_model return content_model def make_objects(content_model): "Turns a tuple-ized content model into one based on objects." (sep,contents,mod)=content_model if contents[0][0]=="#PCDATA": mod="*" # it's implied that #PCDATA can occur more than once newconts=[] for tup in contents: if len(tup)==2: newconts.append(ContentModel([tup[0]],tup[1])) else: newconts.append(make_objects(tup)) if sep==",": return SeqContentModel(newconts,mod) elif sep=="|": return ChoiceContentModel(newconts,mod) elif sep=="": return ContentModel(newconts,mod) # --- Various utilities def compile_content_model(cm): "Parses a content model string, returning a compiled content model." import dtdparser,utils p=dtdparser.DTDParser() p.set_error_handler(utils.ErrorPrinter(p)) p.data=cm[1:] p.datasize=len(p.data) p.final=1 return make_model({},p._parse_content_model(),p) def parse_content_model(cm): "Parses a content model string, returning a compiled content model." import dtdparser,utils p=dtdparser.DTDParser() p.set_error_handler(utils.ErrorPrinter(p)) p.data=cm[1:] p.datasize=len(p.data) p.final=1 return p._parse_content_model() def load_dtd(sysid): import dtdparser,utils dp=dtdparser.DTDParser() dp.set_error_handler(utils.ErrorPrinter(dp)) dtd=CompleteDTD(dp) dp.set_dtd_consumer(dtd) dp.parse_resource(sysid) return dtd def load_dtd_string(dtdstr): import dtdparser, utils dp = dtdparser.DTDParser() dp.set_error_handler(utils.ErrorPrinter(dp)) dtd = CompleteDTD(dp) dp.set_dtd_consumer(dtd) dp.parse_string(dtdstr) return dtd PyXML-0.8.2/xml/parsers/xmlproc/xmlproc.py0100644000076400001440000004677307534565153017747 0ustar martinusers""" The main module of the parser. All other modules will be imported into this one, so this module is the only one one needs to import. For validating parsing, import xmlval instead. """ # $Id: xmlproc.py,v 1.25 2025/08/13 09:28:51 afayolle Exp $ import re,string,sys,urlparse string_translate=string.translate # optimization. made 10% difference! string_find =string.find from dtdparser import * from xmlutils import * from xmlapp import * from xmldtd import * version="0.70" revision="$Revision: 1.25 $" # ============================== # A full well-formedness parser # ============================== class XMLProcessor(XMLCommonParser): "A parser that performs a complete well-formedness check." def __init__(self): EntityParser.__init__(self) # Various handlers self.app=Application() self.dtd=WFCDTD(self) self.ent=self.dtd self.dtd_listener=None self.stop_on_wf=1 def set_application(self,app): "Sets the object to send data events to." self.app=app app.set_locator(self) def set_dtd_listener(self,listener): "Registers an object that listens for DTD parse events." self.dtd_listener=listener def set_data_after_wf_error(self,stop_on_wf=0): """Sets the parser policy on well-formedness errors. If this is set to 0 data events are still delivered, even after well-formedness errors. Otherwise no more data events reach the application after such erors. """ self.stop_on_wf=stop_on_wf def set_read_external_subset(self,read_it): """Tells the parser whether to read the external subset of documents or not.""" self.read_external_subset=read_it def report_error(self,number,args=None): if self.stop_on_wf and number>2999: self.app=Application() # No more data events reported EntityParser.report_error(self,number,args) def reset(self): EntityParser.reset(self) if hasattr(self,"dtd"): self.dtd.reset() # State vars self.stack=[] self.seen_root=0 self.seen_doctype=0 self.seen_xmldecl=0 self.stop_on_wf=1 self.read_external_subset=0 def deref(self): "Deletes circular references." self.dtd = self.ent = self.err = self.app = self.pubres = None def do_parse(self): "Does the actual parsing." try: while self.pos") # Avoid endless loops elif self.data[self.pos]=="&": if self.now_at("&#"): self.parse_charref() else: self.pos=self.pos+1 # Skipping the '&' self.parse_ent_ref() else: self.parse_data() except IndexError, e: # Means self.pos was outside the buffer when we did a raw # compare. This is both a little ugly and fragile to # changes, but this loop is rather time-critical, so we do # raw compares anyway. # Should try to lose this since it gets very hard to find # problems if the user throws an IndexError... if self.final: raise OutOfDataException() else: self.pos=self.prepos # Didn't complete the construct except OutOfDataException, e: if self.final: raise e else: self.pos=self.prepos # Didn't complete the construct def parseStart(self): "Must be called before parsing starts. (Notifies application.)" self.app.doc_start() def parseEnd(self): """Must be called when parsing is finished. (Does some checks and " "notifies the application.)""" if self.stack!=[] and self.ent_stack==[]: self.report_error(3014,self.stack[-1]) elif not self.seen_root: self.report_error(3015) self.app.doc_end() def parse_start_tag(self): "Parses the start tag." self.pos=self.pos+1 # Skips the '<' name=self._get_name() self.skip_ws() try: (attrs,fixeds)=self.dtd.attrinfo[name] attrs=attrs.copy() except KeyError: attrs={} fixeds={} if self.data[self.pos]!=">" and self.data[self.pos]!="/": seen={} while not self.test_str(">") and not self.test_str("/>"): a_name=self._get_name() self.skip_ws() if not self.now_at("="): self.report_error(3005,"=") self.scan_to(">") ## Panic! Get out of the tag! a_val="" break self.skip_ws() a_val=self.parse_att_val() if a_val==-1: # WF error, we've skipped the rest of the tag self.pos=self.pos-1 # Lets us find the '>' if self.data[self.pos-1]=="/": self.pos=self.pos-1 # Gets the '/>' cases right break if seen.has_key(a_name): self.report_error(3016,a_name) else: seen[a_name]=1 attrs[a_name]=a_val if fixeds.has_key(a_name) and fixeds[a_name]!=a_val: self.report_error(2000,a_name) self.skip_ws() # --- Take care of the tag if self.stack==[] and self.seen_root: self.report_error(3017) self.seen_root=1 if self.now_at(">"): self.app.handle_start_tag(name,attrs) self.stack.append(name) elif self.now_at("/>"): self.app.handle_start_tag(name,attrs) self.app.handle_end_tag(name) else: self.report_error(3004,("'>'","/>")) def parse_att_val(self): "Parses an attribute value and resolves all entity references in it." val="" if self.now_at('"'): delim='"' reg_attval_stop=reg_attval_stop_quote elif self.now_at("'"): delim="'" reg_attval_stop=reg_attval_stop_sing else: self.report_error(3004,("'","\"")) self.scan_to(">") return -1 # FIXME: Ugly. Should throw an exception instead while 1: piece=self.find_reg(reg_attval_stop) val=val+ws_trans(piece) if self.now_at(delim): break if self.now_at("&#"): val=val+self._read_char_ref() elif self.now_at("&"): name=self._get_name() if name in self.open_ents: self.report_error(3019) return else: self.open_ents.append(name) try: ent=self.ent.resolve_ge(name) if ent.is_internal(): # Doing all this here sucks a bit, but... self.push_entity(self.get_current_sysid(),\ ent.value,name) self.final=1 # Only one block val=val+self.parse_literal_entval() if not self.pos==self.datasize: self.report_error(3001) # Thing started, not compl self.pop_entity() else: self.report_error(3020) except KeyError: self.report_error(3021,name) ## FIXME: Check standalone dcl del self.open_ents[-1] elif self.now_at("<"): self.report_error(3022) continue else: self.report_error(4001) self.pos=self.pos+1 # Avoid endless loop continue if not self.now_at(";"): self.report_error(3005,";") return val def parse_literal_entval(self): "Parses a literal entity value for insertion in an attribute value." val="" reg_stop=re.compile("&") while 1: try: piece=self.find_reg(reg_stop) except OutOfDataException: # Only character data left val=val+ws_trans(self.data[self.pos:]) self.pos=self.datasize break val=val+ws_trans(piece) if self.now_at("&#"): val=val+self._read_char_ref() elif self.now_at("&"): name=self._get_name() if name in self.open_ents: self.report_error(3019) return "" else: self.open_ents.append(name) try: ent=self.ent.resolve_ge(name) if ent.is_internal(): # Doing all this here sucks a bit, but... self.push_entity(self.get_current_sysid(),\ ent.value,name) self.final=1 # Only one block val=val+self.parse_literal_entval() if not self.pos==self.datasize: self.report_error(3001) self.pop_entity() else: self.report_error(3020) except KeyError: self.report_error(3021,name) del self.open_ents[-1] else: self.report_error(4001) if not self.now_at(";"): self.report_error(3005,";") self.scan_to(">") return val def parse_end_tag(self): "Parses the end tag from after the ''." self.pos=self.pos+2 # Skips the '": self.skip_ws() # Probably rare to find whitespace here if not self.now_at(">"): self.report_error(3005,">") else: self.pos=self.pos+1 try: elem = self.stack[-1] if name != elem: self.report_error(3023,(name,elem)) # Let's do some guessing in case we continue if len(self.stack)>0 and self.stack[-1]==name: del self.stack[-1] else: self.stack.append(elem) # Put it back else: del self.stack[-1] except IndexError: self.report_error(3024,name) self.app.handle_end_tag(name) def parse_data(self): "Parses character data." start=self.pos end=string_find(self.data,"<",self.pos) if end==-1: end=string_find(self.data,"&",self.pos) if end==-1: if not self.final: raise OutOfDataException() end=self.datasize else: ampend=string_find(self.data,"&",self.pos,end) if ampend!=-1: end=ampend self.pos=end if string_find(self.data,"]]>",start,end)!=-1: self.pos=string_find(self.data,"]]>",start,end) self.report_error(3025) self.pos=self.pos+3 # Skipping over it if self.stack==[]: res=reg_ws.match(self.data,start) if res==None or res.end(0)!=end: self.report_error(3029) else: self.app.handle_data(self.data,start,end) def parse_charref(self): "Parses a character reference." if self.now_at("x"): digs=unhex(self.get_match(reg_hex_digits)) else: try: digs=int(self.get_match(reg_digits)) except ValueError: self.report_error(3027) digs=None if not self.now_at(";"): self.report_error(3005,";") if digs==None: return if not (digs==9 or digs==10 or digs==13 or \ (digs>=32 and digs<=255)): if digs>255: if using_unicode and digs<65536: self.app.handle_data(xml_chr(digs),0,1) else: self.report_error(1005,digs) else: self.report_error(3018,digs) else: if self.stack==[]: self.report_error(3028) self.app.handle_data(xml_chr(digs),0,1) def parse_cdata(self): "Parses a CDATA marked section from after the '") if self.stack==[]: self.report_error(3029) self.app.handle_data(self.data,self.pos,new_pos) self.pos=new_pos+3 def parse_ent_ref(self): "Parses a general entity reference from after the '&'." name=self._get_name() if not self.now_at(";"): self.report_error(3005,";") try: ent=self.ent.resolve_ge(name) except KeyError: self.report_error(3021,name) return if ent.name in self.open_ents: self.report_error(3019) return self.open_ents.append(ent.name) if self.stack==[]: self.report_error(3030) # Storing size of current element stack stack_size=len(self.stack) if ent.is_internal(): self.push_entity(self.get_current_sysid(),ent.value,name) try: self.do_parse() except OutOfDataException: # Ran out of data before done self.report_error(3001) self.flush() self.pop_entity() else: if ent.notation != None: self.report_error(3031) else: self.seen_root = 0 # Haven't seen root in the new entity yet self.open_entity(self.pubres.resolve_entity_pubid(ent.get_pubid(), ent.get_sysid()), name) self.seen_root = 1 # Did any elements cross the entity boundary? if stack_size != len(self.stack): self.report_error(3042) del self.open_ents[-1] def parse_doctype(self): "Parses the document type declaration." if self.seen_doctype: self.report_error(3032) if self.seen_root: self.report_error(3033) self.skip_ws(1) rootname = self._get_name() self.skip_ws(1) (pub_id, sys_id) = self.parse_external_id() self.skip_ws() self.app.handle_doctype(rootname, pub_id, sys_id) self.dtd.dtd_start() if self.now_at("["): self.parse_internal_dtd() elif not self.now_at(">"): self.report_error(3005, ">") # External subset must be parsed _after_ the internal one if pub_id != None or sys_id != None: # Was there an external id at all? if not self.get_current_sysid() and \ urlparse.urlparse(sys_id)[0] == "": self.report_error(2024, sys_id) if self.read_external_subset: p = self._setup_dtd_parser(0) try: sys_id = self.pubres.resolve_doctype_pubid(pub_id, sys_id) p.dtd_start_called = 1 p.parse_resource(join_sysids(self.get_current_sysid(), sys_id)) finally: p.deref() self.err.set_locator(self) if (pub_id == None and sys_id == None) or \ not self.read_external_subset: # If we parse the external subset dtd_end is called for us by # the dtd parser. If we don't we must call it ourselves. self.dtd.dtd_end() self.seen_doctype=1 # Has to be at the end to avoid block trouble def parse_internal_dtd(self): "Parse the internal DTD beyond the '['." self.set_start_point() # Record start of int_subset, preserve data self.update_pos() line=self.line lb=self.last_break last_part_size=0 while 1: self.find_reg(reg_int_dtd) if self.now_at("\""): self.scan_to("\"") elif self.now_at("'"): self.scan_to("'") elif self.now_at("") elif self.now_at("") elif self.now_at("") elif self.now_at("]"): p=self.pos self.skip_ws() if self.now_at(">"): last_part_size=(self.pos-p)+1 break # [:lps] cuts off the "]\s+>" at the end self.handle_internal_dtd(line,lb,self.get_region()[:-last_part_size]) def handle_internal_dtd(self,doctype_line,doctype_lb,int_dtd): "Handles the internal DTD." try: p=self._setup_dtd_parser(1) try: p.line=doctype_line p.last_break=doctype_lb p.set_sysid(self.get_current_sysid()) p.final=1 p.feed(int_dtd, decoded = 1) except OutOfDataException: self.report_error(3034) finally: p.deref() self.err.set_locator(self) def _setup_dtd_parser(self, internal_subset): p=DTDParser() p.set_error_handler(self.err) p.set_dtd_consumer(self.dtd) p.set_error_language(self.err_lang) p.set_inputsource_factory(self.isf) p.set_pubid_resolver(self.pubres) p.set_dtd_object(self.dtd) if self.dtd_listener!=None: self.dtd.set_dtd_listener(self.dtd_listener) p.set_internal(internal_subset) self.err.set_locator(p) return p # ===== The introspection methods ===== def get_elem_stack(self): "Returns the internal element stack. Note: this is a live list!" return self.stack def get_data_buffer(self): "Returns the current data buffer." return self.data def get_construct_start(self): """Returns the start position of the current construct (tag, comment, etc).""" return self.prepos def get_construct_end(self): """Returns the end position of the current construct (tag, comment, etc).""" return self.pos def get_raw_construct(self): "Returns the raw form of the current construct." return self.data[self.prepos:self.pos] def get_current_ent_stack(self): """Returns a snapshot of the entity stack. A list of the system identifier of the entity and its name, if any.""" return map(lambda ent: (ent[0],ent[9]),self.ent_stack) PyXML-0.8.2/xml/parsers/xmlproc/xmlutils.py0100644000076400001440000007754507550507011020130 0ustar martinusers# -*- coding: iso-8859-1 -*- """ Some common declarations for the xmlproc system gathered in one file. """ # $Id: xmlutils.py,v 1.34 2025/09/13 15:37:17 fdrake Exp $ import string,re,urlparse,os,sys,types import xmlapp,charconv,errors try: StringTypes = [types.StringType, types.UnicodeType] except AttributeError: StringTypes = [types.StringType] try: import codecs def mkconverter(parser,src,dest): if src == dest: return lambda s:s try: enc = src decoder = codecs.lookup(src)[1] # If the target is Unicode, we need no encoder if dest is None: # the decoder returns a string,length tuple, # we only need the string return lambda c,d = decoder:(d(c)[0]) enc = dest encoder = codecs.lookup(dest)[0] return lambda c,d=decoder,e=encoder:e(d(c)[0])[0] except LookupError: parser.report_error(1002,enc) return lambda s:s _interned = {} def string_intern(x): if type(x) == types.StringType: return intern(x) return _interned.setdefault(x,x) using_unicode = 1 xml_chr = unichr BOM = unicode("\xfe\xff","utf-16-be") except ImportError: def mkconverter(parser,src,dest): if dest == None: dest = "utf-8" if charconv.convdb.can_convert(src,dest): return charconv.convdb.get_converter(src,dest) else: parser.report_error(1002,src) return lambda s:s string_intern = intern using_unicode = 0 xml_chr = chr # FIXME: support BOM detection in multibyte mode BOM = None # Standard exceptions class OutOfDataException(Exception): """An exception that signals that more data is expected, but the current buffer has been exhausted.""" pass # ============================== # The general entity parser # ============================== class EntityParser: """A generalized parser for XML entities, whether DTD, documents or even catalog files.""" def __init__(self): # --- Creating support objects self.err=xmlapp.ErrorHandler(self) self.ent=xmlapp.EntityHandler(self.err) self.isf=xmlapp.InputSourceFactory() self.pubres=xmlapp.PubIdResolver() self.data_charset=None # the default charset in XML is UTF-8 self.input_encoding = None # not determined, yet self.charset_converter = None self.err_lang="en" self.errors=errors.get_error_list(self.err_lang) self.reset() def set_error_language(self,language): """Sets the language in which errors are reported. (ISO 3166 codes.) Throws a KeyError if the language is not supported.""" self.errors=errors.get_error_list(string.lower(language)) self.err_lang=string.lower(language) # only set if supported def set_error_handler(self,err): "Sets the object to send error events to." self.err=err def set_pubid_resolver(self,pubres): self.pubres=pubres def set_entity_handler(self,ent): "Sets the object that resolves entity references." self.ent=ent def set_inputsource_factory(self,isf): "Sets the object factory used to create input sources from sysids." self.isf=isf def set_data_charset(self,charset): """Tells the parser which character encoding to use when reporting data to applications. The default is None, which means to return Unicode string if supported and UTF-8 otherwise.""" self.data_charset=charset def parse_resource(self, sysID, bufsize = 16384): """Begin parsing an XML entity with the specified system identifier. Only used for the document entity, not to handle subentities, which open_entity takes care of.""" self.current_sysID = sysID try: infile = self.isf.create_input_source(sysID) except (IOError, OSError): self.report_error(3000, sysID) return self.read_from(infile,bufsize) infile.close() self.close() def parse_string(self, doc, sysid = None, pubid = None): """Parse an XML document from the doc string.""" if sysid: self.current_sysID = sysid # FIXME: pubid! self.feed(doc) self.close() def open_entity(self, sys_id, name = "None"): """Starts parsing a new entity, pushing the old onto the stack. This method must not be used to start parsing, use parse_resource for that. Note that sys_id must be absolute.""" try: inf = self.isf.create_input_source(sys_id) except (IOError, OSError): self.report_error(3000, sys_id) return self._push_ent_stack(name) self.current_sysID = sys_id self.pos = 0 self.line = 1 self.last_break = 0 self.data = "" self.encoded_data = "" self.input_encoding = None self.charset_converter = None tmp = self.seen_xmldecl self.seen_xmldecl = 0 # Avoid complaints # XXX Should not need to read the whole thing in, but doing so # fixes PyXML SF bug #608453. There should be a better fix. self.read_from(inf, -1) self.seen_xmldecl = tmp self.flush() self.pop_entity() def push_entity(self,sysID,contents,name="None"): """Parse some text and consider it a new entity, making it possible to return to the original entity later.""" self._push_ent_stack(name) self.data = contents self.encoded_data = "" self.current_sysID = sysID self.pos = 0 self.line = 1 self.last_break = 0 self.datasize = len(contents) self.last_upd_pos = 0 self.final = 1 def pop_entity(self): "Skips out of the current entity and back to the previous one." if self.ent_stack==[]: self.report_error(4000) self._pop_ent_stack() def read_from(self,fileobj,bufsize=16384): """Reads data from a file-like object until EOF. Does not close it. **WARNING**: This method does not call the parseStart/parseEnd methods, since it does not know if it may be called several times. Use parse_resource if you just want to read a file.""" while 1: buf=fileobj.read(bufsize) if buf=="": break try: self.feed(buf) except OutOfDataException: break def reset(self): """Resets the parser, losing all unprocessed data.""" self.ent_stack=[] self.open_ents=[] # Used to test for entity recursion self.current_sysID="Unknown" self.first_feed=1 # Block information self.data="" self.encoded_data="" self.final=0 self.datasize=0 self.start_point=-1 # Location tracking self.line=1 self.last_break=0 self.block_offset=0 # Offset from start of stream to start of cur block self.pos=0 self.last_upd_pos=0 def autodetect_encoding(self, new_data): if len(new_data)<5: # If this is a very short external entity, it may not # have enough bytes for auto-detection. In that case, # it must be UTF-8 enc = "utf-8" elif new_data[:3] == '\xef\xbb\xbf': enc = "utf-8" # with BOM elif new_data[:4] == '\0\0\0\x3c': enc = "ucs-4-be" elif new_data[:4] == '\x3c\0\0\0': enc = "ucs-4-le" # ignore unusual byte orders 2143 and 3412 elif new_data[:2] == '\xfe\xff': enc = "utf-16-be" # with BOM elif new_data[:2] == '\xff\xfe': enc = "utf-16-le" # with BOM elif new_data[:4] == '\0\x3c\0\x3f': enc = "utf-16-be" elif new_data[:4] == '\0\x3f\0\x3c': enc = "utf-16-be" elif new_data[:5] == 'self.datasize-5 and not self.final: raise OutOfDataException() return regexp.match(self.data,self.pos)!=None def get_match(self,regexp): "Returns the result of matching the regexp and advances self.pos." if self.pos>self.datasize-5 and not self.final: raise OutOfDataException() ent=regexp.match(self.data,self.pos) if ent==None: self.report_error(reg2code[regexp.pattern]) return "" end=ent.end(0) # Speeds us up slightly if end==self.datasize: raise OutOfDataException() self.pos=end return ent.group(0) def update_pos(self): "Updates (line,col)-pos by checking processed blocks." breaks=string.count(self.data,"\n",self.last_upd_pos,self.pos) self.last_upd_pos=self.pos if breaks>0: self.line=self.line+breaks self.last_break=string.rfind(self.data,"\n",0,self.pos) def get_wrapped_match(self,wraps): "Returns a contained match. Useful for regexps inside quotes." found=0 for (wrap,regexp) in wraps: if self.test_str(wrap): found=1 self.pos=self.pos+len(wrap) break if not found: msg="" for (wrap,regexp) in wraps[:-1]: msg="%s'%s', " % (msg,wrap) self.report_error(3004,(msg[:-2],wraps[-1][0])) data=self.get_match(regexp) if not self.now_at(wrap): self.report_error(3005,wrap) return data #--- ERROR HANDLING def report_error(self,number,args=None): try: msg = self.errors[number] if args != None: msg = msg % args except KeyError: msg = self.errors[4002] % number # Unknown err msg :-) if number < 2000: self.err.warning(msg) elif number < 3000: self.err.error(msg) else: self.err.fatal(msg) #--- USEFUL METHODS def get_current_sysid(self): "Returns the sysid of the file we are reading now." return self.current_sysID def set_sysid(self,sysID): "Sets the current system identifier. Does not store the old one." self.current_sysID = sysID def get_offset(self): "Returns the current offset from the start of the stream." return self.block_offset+self.pos def get_line(self): "Returns the current line number." self.update_pos() return self.line def get_column(self): "Returns the current column position." self.update_pos() return self.pos-self.last_break def is_root_entity(self): "Returns true if the current entity is the root entity." return self.ent_stack==[] def is_external(self): """Returns true if the current entity is an external entity. The root (or document) entity is not considered external.""" return self.ent_stack!=[] and \ self.ent_stack[0][0]!=self.get_current_sysid() # --- Internal methods def _push_ent_stack(self,name="None"): self.ent_stack.append((self.get_current_sysid(),self.data,self.pos,\ self.line,self.last_break,self.datasize,\ self.last_upd_pos,self.block_offset,self.final, self.input_encoding,self.charset_converter, name)) def _pop_ent_stack(self): (self.current_sysID, self.data, self.pos, self.line, self.last_break, \ self.datasize, self.last_upd_pos, self.block_offset, self.final, \ self.input_encoding, self.charset_converter, dummy) = \ self.ent_stack[-1] del self.ent_stack[-1] # ============================== # Common code for some parsers # ============================== class XMLCommonParser(EntityParser): def parse_external_id(self,required=0,sysidreq=1): """Parses an external ID declaration and returns a tuple consisting of (pubid,sysid). If the required attribute is false neither SYSTEM nor PUBLIC identifiers are required. If sysidreq is false a SYSTEM identifier is not required after a PUBLIC one.""" pub_id=None sys_id=None if self.now_at("SYSTEM"): self.skip_ws(1) sys_id=self.get_wrapped_match([("\"",reg_sysid_quote),\ ("'",reg_sysid_apo)]) elif self.now_at("PUBLIC"): self.skip_ws(1) pub_id=self.get_wrapped_match([("\"",reg_pubid_quote),\ ("'",reg_pubid_apo)]) pub_id=string.join(string.split(pub_id)) if sysidreq: self.skip_ws(1) sys_id=self.get_wrapped_match([("\"",reg_sysid_quote),\ ("'",reg_sysid_apo)]) else: if self.test_str("'") or self.test_str('"'): self.report_error(3002) self.skip_ws() if self.test_str("'") or self.test_str('"'): sys_id=self.get_wrapped_match([("\"",reg_sysid_quote),\ ("'",reg_sysid_apo)]) else: if required: self.report_error(3006) return (pub_id,sys_id) def __get_quoted_string(self): "Returns the contents of a quoted string at current position." try: quo=self.data[self.pos] except IndexError: raise OutOfDataException() if not (self.now_at('"') or self.now_at("'")): self.report_error(3004,("'\"'","'")) self.scan_to(">") return "" return self.scan_to(quo) def parse_xml_decl(self,handler=None): "Parses the contents of the XML declaration from after the ''.""" trgt=self._get_name() if trgt=="xml": if report_xml_decl: self.parse_xml_decl(handler) else: self.parse_xml_decl() if not self.now_at("?>"): self.report_error(3005,"?>") self.seen_xmldecl=1 else: if self.now_at("?>"): rem="" else: self.skip_ws(1) rem=self.scan_to("?>") # OutOfDataException if not found if reg_res_pi.match(trgt)!=None: if trgt=="xml:namespace": self.report_error(1003) elif trgt!="xml-stylesheet": self.report_error(3045) handler.handle_pi(trgt,rem) def parse_comment(self,handler): "Parses the comment from after ''." new_pos = self.get_index("--") handler.handle_comment(self.data[self.pos : new_pos]) self.pos = new_pos if not self.now_at("-->"): self.report_error(3005,"-->") def _read_char_ref(self): "Parses a character reference and returns the character." if self.now_at("x"): digs=unhex(self.get_match(reg_hex_digits)) else: digs=int(self.get_match(reg_digits)) if not (digs==9 or digs==10 or digs==13 or \ (digs>=32 and digs<=255)): if digs>255: # XXX check for surrogate references if using_unicode and digs<65536: self.app.handle_data(xml_chr(digs),0,1) else: self.report_error(1005,digs) else: self.report_error(3018,digs) return "" else: return xml_chr(digs) def _get_name(self): """Parses the name at the current position and returns it. An error is reported if no name is present.""" if self.pos>self.datasize-5 and not self.final: raise OutOfDataException() match = reg_name.match(self.data,self.pos) if match: self.pos = match.end() if match.end()==self.datasize and not self.final: raise OutOfDataException() return string_intern(match.group()) else: self.report_error(3900) return "" # --- A collection of useful functions # Utility functions def unhex(hex_value): "Converts a string hex-value to an integer." sum=0 for char in hex_value: sum=sum*16 char=ord(char) if char<58 and char>=48: sum=sum+(char-48) elif char>=97 and char<=102: sum=sum+(char-87) elif char>=65 and char<=70: sum=sum+(char-55) # else ERROR, but it can't occur here return sum def matches(regexp,str): mo=regexp.match(str) return mo!=None and len(mo.group(0))==len(str) def join_sysids_general(base, url): "Resolves a URL relative to a base URL. The base can be None." if urlparse.urlparse(url)[0] != "": return url elif urlparse.urlparse(base)[0] == "": if urlparse.urlparse(url)[0] == "": return os.path.join(os.path.split(base)[0], url) else: return url else: return urlparse.urljoin(base, url) def join_sysids_win32(base, url): "Resolves a URL relative to a base URL. The base can be None." if urlparse.urlparse(url)[0] != "": return url elif len(urlparse.urlparse(base)[0])<2: # Handles drive identifiers correctly if len(urlparse.urlparse(url)[0])<2: return os.path.join(os.path.split(base)[0],url) else: return url else: return urlparse.urljoin(base,url) # here join_sysids(base,url): is set to the correct function if sys.platform == "win32": join_sysids = join_sysids_win32 else: join_sysids = join_sysids_general # --- Some useful regexps if using_unicode: _re_flags = re.UNICODE else: _re_flags = 0 namestart = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_:" + \ "" namechars = namestart + "0123456789.-" whitespace = "\n\t \r" reg_ws=re.compile("[\n\t \r]+",_re_flags) reg_ver=re.compile("[-a-zA-Z0-9_.:]+",_re_flags) reg_enc_name=re.compile("[A-Za-z][-A-Za-z0-9._]*") reg_std_alone=re.compile("yes|no") if using_unicode: from xml.utils import characters reg_name = characters.re_Name() reg_names = characters.re_Names() reg_nmtoken = characters.re_Nmtoken() reg_nmtokens = characters.re_Nmtokens() reg_pe_ref = re.compile("%"+characters.Name+";") del characters else: reg_name=re.compile("["+namestart+"]["+namechars+"]*") reg_names=re.compile("["+namestart+"]["+namechars+"]*" "([\n\t \r]+["+namestart+"]["+namechars+"]*)*") reg_nmtoken=re.compile("["+namechars+"]+") reg_nmtokens=re.compile("["+namechars+"]+([\n\t \r]+["+namechars+"]+)*") reg_pe_ref=re.compile("%["+namestart+"]["+namechars+"]*;") reg_sysid_quote=re.compile("[^\"]*") reg_sysid_apo=re.compile("[^']*") reg_pubid_quote=re.compile("[- \n\t\ra-zA-Z0-9'()+,./:=?;!*#@$_%]*") reg_pubid_apo=re.compile("[- \n\t\ra-zA-Z0-9()+,./:=?;!*#@$_%]*") reg_start_tag=re.compile("<[A-Za-z_:]") reg_quoted_attr=re.compile("[^<\"]*") reg_apo_attr=re.compile("[^<']*") reg_c_data=re.compile("[<&]") reg_ent_val_quote=re.compile("[^\"]+") reg_ent_val_apo=re.compile("[^\']+") reg_attr_type=re.compile(r"CDATA|IDREFS|IDREF|ID|ENTITY|ENTITIES|NMTOKENS|" "NMTOKEN") # NOTATION support separate reg_attr_def=re.compile(r"#REQUIRED|#IMPLIED") reg_digits=re.compile("[0-9]+") reg_hex_digits=re.compile("[0-9a-fA-F]+") reg_res_pi=re.compile("xml",re.I) reg_int_dtd=re.compile("\"|'|<\\?|') def startCDATA(self): self._in_cdata = 1 self._out.write('') # --- ContentGenerator is the SAX1 DocumentHandler for writing back XML class ContentGenerator(XMLGenerator): def characters(self, str, start, end): # In SAX1, characters receives start and end; in SAX2, it receives # a string. For plain strings, we may want to use a buffer object. return XMLGenerator.characters(self, str[start:start+end]) # --- XMLFilterImpl class XMLFilterBase(saxlib.XMLFilter): """This class is designed to sit between an XMLReader and the client application's event handlers. By default, it does nothing but pass requests up to the reader and events on to the handlers unmodified, but subclasses can override specific methods to modify the event stream or the configuration requests as they pass through.""" # ErrorHandler methods def error(self, exception): self._err_handler.error(exception) def fatalError(self, exception): self._err_handler.fatalError(exception) def warning(self, exception): self._err_handler.warning(exception) # ContentHandler methods def setDocumentLocator(self, locator): self._cont_handler.setDocumentLocator(locator) def startDocument(self): self._cont_handler.startDocument() def endDocument(self): self._cont_handler.endDocument() def startPrefixMapping(self, prefix, uri): self._cont_handler.startPrefixMapping(prefix, uri) def endPrefixMapping(self, prefix): self._cont_handler.endPrefixMapping(prefix) def startElement(self, name, attrs): self._cont_handler.startElement(name, attrs) def endElement(self, name): self._cont_handler.endElement(name) def startElementNS(self, name, qname, attrs): self._cont_handler.startElementNS(name, qname, attrs) def endElementNS(self, name, qname): self._cont_handler.endElementNS(name, qname) def characters(self, content): self._cont_handler.characters(content) def ignorableWhitespace(self, chars): self._cont_handler.ignorableWhitespace(chars) def processingInstruction(self, target, data): self._cont_handler.processingInstruction(target, data) def skippedEntity(self, name): self._cont_handler.skippedEntity(name) # DTDHandler methods def notationDecl(self, name, publicId, systemId): self._dtd_handler.notationDecl(name, publicId, systemId) def unparsedEntityDecl(self, name, publicId, systemId, ndata): self._dtd_handler.unparsedEntityDecl(name, publicId, systemId, ndata) # EntityResolver methods def resolveEntity(self, publicId, systemId): self._ent_handler.resolveEntity(publicId, systemId) # XMLReader methods def parse(self, source): self._parent.setContentHandler(self) self._parent.setErrorHandler(self) self._parent.setEntityResolver(self) self._parent.setDTDHandler(self) self._parent.parse(source) def setLocale(self, locale): self._parent.setLocale(locale) def getFeature(self, name): return self._parent.getFeature(name) def setFeature(self, name, state): self._parent.setFeature(name, state) def getProperty(self, name): return self._parent.getProperty(name) def setProperty(self, name, value): self._parent.setProperty(name, value) # FIXME: remove this backward compatibility hack when not needed anymore XMLFilterImpl = XMLFilterBase # --- BaseIncrementalParser class BaseIncrementalParser(xmlreader.IncrementalParser): """This class implements the parse method of the XMLReader interface using the feed, close and reset methods of the IncrementalParser interface as a convenience to SAX 2.0 driver writers.""" def parse(self, source): source = prepare_input_source(source) self.prepareParser(source) self._cont_handler.startDocument() # FIXME: what about char-stream? inf = source.getByteStream() buffer = inf.read(16384) while buffer != "": self.feed(buffer) buffer = inf.read(16384) self.close() self.reset() self._cont_handler.endDocument() def prepareParser(self, source): """This method is called by the parse implementation to allow the SAX 2.0 driver to prepare itself for parsing.""" raise NotImplementedError("prepareParser must be overridden!") # --- Utility functions def prepare_input_source(source, base = ""): """This function takes an InputSource and an optional base URL and returns a fully resolved InputSource object ready for reading.""" if type(source) in _StringTypes: source = xmlreader.InputSource(source) elif hasattr(source, "read"): f = source source = xmlreader.InputSource() source.setByteStream(f) if hasattr(f, "name"): source.setSystemId(f.name) if source.getByteStream() is None: sysid = source.getSystemId() if os.path.isfile(sysid): basehead = os.path.split(os.path.normpath(base))[0] source.setSystemId(os.path.join(basehead, sysid)) f = open(sysid, "rb") else: source.setSystemId(urlparse.urljoin(base, sysid)) f = urllib2.urlopen(source.getSystemId()) source.setByteStream(f) return source # =========================================================================== # # DEPRECATED SAX 1.0 CLASSES # # =========================================================================== # --- AttributeMap class AttributeMap: """An implementation of AttributeList that takes an (attr,val) hash and uses it to implement the AttributeList interface.""" def __init__(self, map): self.map=map def getLength(self): return len(self.map.keys()) def getName(self, i): try: return self.map.keys()[i] except IndexError,e: return None def getType(self, i): return "CDATA" def getValue(self, i): try: if type(i)==types.IntType: return self.map[self.getName(i)] else: return self.map[i] except KeyError,e: return None def __len__(self): return len(self.map) def __getitem__(self, key): if type(key)==types.IntType: return self.map.keys()[key] else: return self.map[key] def items(self): return self.map.items() def keys(self): return self.map.keys() def has_key(self,key): return self.map.has_key(key) def get(self, key, alternative=None): return self.map.get(key, alternative) def copy(self): return AttributeMap(self.map.copy()) def values(self): return self.map.values() # --- Event broadcasting object class EventBroadcaster: """Takes a list of objects and forwards any method calls received to all objects in the list. The attribute list holds the list and can freely be modified by clients.""" class Event: "Helper objects that represent event methods." def __init__(self,list,name): self.list=list self.name=name def __call__(self,*rest): for obj in self.list: apply(getattr(obj,self.name), rest) def __init__(self,list): self.list=list def __getattr__(self,name): return self.Event(self.list,name) def __repr__(self): return "" % id(self) # --- ESIS document handler import saxlib class ESISDocHandler(saxlib.HandlerBase): "A SAX document handler that produces naive ESIS output." def __init__(self,writer=sys.stdout): self.writer=writer def processingInstruction (self,target, remainder): """Receive an event signalling that a processing instruction has been found.""" self.writer.write("?"+target+" "+remainder+"\n") def startElement(self,name,amap): "Receive an event signalling the start of an element." self.writer.write("("+name+"\n") for a_name in amap.keys(): self.writer.write("A"+a_name+" "+amap[a_name]+"\n") def endElement(self,name): "Receive an event signalling the end of an element." self.writer.write(")"+name+"\n") def characters(self,data,start_ix,length): "Receive an event signalling that character data has been found." self.writer.write("-"+data[start_ix:start_ix+length]+"\n") # --- XML canonizer class Canonizer(saxlib.HandlerBase): "A SAX document handler that produces canonized XML output." def __init__(self,writer=sys.stdout): self.elem_level=0 self.writer=writer def processingInstruction (self,target, remainder): if not target=="xml": self.writer.write("") def startElement(self,name,amap): self.writer.write("<"+name) a_names=amap.keys() a_names.sort() for a_name in a_names: self.writer.write(" "+a_name+"=\"") self.write_data(amap[a_name]) self.writer.write("\"") self.writer.write(">") self.elem_level=self.elem_level+1 def endElement(self,name): self.writer.write("") self.elem_level=self.elem_level-1 def ignorableWhitespace(self,data,start_ix,length): self.characters(data,start_ix,length) def characters(self,data,start_ix,length): if self.elem_level>0: self.write_data(data[start_ix:start_ix+length]) def write_data(self,data): "Writes datachars to writer." data=data.replace("&","&") data=data.replace("<","<") data=data.replace("\"",""") data=data.replace(">",">") data=data.replace(chr(9)," ") data=data.replace(chr(10)," ") data=data.replace(chr(13)," ") self.writer.write(data) # --- mllib class mllib: """A re-implementation of the htmllib, sgmllib and xmllib interfaces as a SAX DocumentHandler.""" # Unsupported: # - setnomoretags # - setliteral # - translate_references # - handle_xml # - handle_doctype # - handle_charref # - handle_entityref # - handle_comment # - handle_cdata # - tag_attributes def __init__(self): self.reset() def reset(self): import saxexts # only used here self.parser=saxexts.XMLParserFactory.make_parser() self.handler=mllib.Handler(self.parser,self) self.handler.reset() def feed(self,data): self.parser.feed(data) def close(self): self.parser.close() def get_stack(self): return self.handler.get_stack() # --- Handler methods (to be overridden) def handle_starttag(self,name,method,atts): method(atts) def handle_endtag(self,name,method): method() def handle_data(self,data): pass def handle_proc(self,target,data): pass def unknown_starttag(self,name,atts): pass def unknown_endtag(self,name): pass def syntax_error(self,message): pass # --- The internal handler class class Handler(saxlib.DocumentHandler,saxlib.ErrorHandler): """An internal class to handle SAX events and translate them to mllib events.""" def __init__(self,driver,handler): self.driver=driver self.driver.setDocumentHandler(self) self.driver.setErrorHandler(self) self.handler=handler self.reset() def get_stack(self): return self.stack def reset(self): self.stack=[] # --- DocumentHandler methods def characters(self, ch, start, length): self.handler.handle_data(ch[start:start+length]) def endElement(self, name): if hasattr(self.handler,"end_"+name): self.handler.handle_endtag(name, getattr(self.handler,"end_"+name)) else: self.handler.unknown_endtag(name) del self.stack[-1] def ignorableWhitespace(self, ch, start, length): self.handler.handle_data(ch[start:start+length]) def processingInstruction(self, target, data): self.handler.handle_proc(target,data) def startElement(self, name, atts): self.stack.append(name) if hasattr(self.handler,"start_"+name): self.handler.handle_starttag(name, getattr(self.handler, "start_"+name), atts) else: self.handler.unknown_starttag(name,atts) # --- ErrorHandler methods def error(self, exception): self.handler.syntax_error(str(exception)) def fatalError(self, exception): raise RuntimeError(str(exception)) PyXML-0.8.2/xml/sax/writer.py0100644000076400001440000004460307452522607015211 0ustar martinusers"""SAX document handlers that support output generation of XML, SGML, and XHTML. This module provides three different groups of objects: the actual SAX document handlers that drive the output, DTD information containers, and syntax descriptors (of limited public use in most cases). Output Drivers -------------- The output drivers conform to the SAX C protocol. They can be used anywhere a C is used. Two drivers are provided: a `basic' driver which creates a fairly minimal output without much intelligence, and a `pretty-printing' driver that performs pretty-printing with nice indentation and the like. Both can optionally make use of DTD information and syntax objects. DTD Information Containers -------------------------- Each DTD information object provides an attribute C which describes the expected output syntax; an alternate can be provided to the output drivers if desired. Syntax Descriptors ------------------ Syntax descriptor objects provide several attributes which describe the various lexical components of XML & SGML markup. The attributes have names that reflect the shorthand notation from the SGML world, but the values are strings which give the appropriate characters for the markup language being described. The one addition is the C attribute which should be used to end the start tag of elements which have no content. This is needed to properly support XML and XHTML. """ __version__ = '$Revision: 1.8 $' import string import xml.parsers.xmlproc.dtdparser import xml.parsers.xmlproc.xmlapp from xml.sax.saxutils import escape DEFAULT_LINELENGTH = 74 class Syntax: com = "--" # comment start or end cro = "&#" # character reference open refc = ";" # reference close dso = "[" # declaration subset open dsc = "]" # declaration subset close ero = "&" # entity reference open lit = '"' # literal start or end lit_quoted = '"' # quoted literal lita = "'" # literal start or end (alternative) mdo = "" # markup declaration close msc = "]]" # marked section close pio = "" # tag close vi = "=" # value indicator def __init__(self): if self.__class__ is Syntax: raise RuntimeError, "Syntax must be subclassed to be used!" class SGMLSyntax(Syntax): empty_stagc = ">" pic = ">" # processing instruction close net = "/" # null end tag class XMLSyntax(Syntax): empty_stagc = "/>" pic = "?>" # processing instruction close net = None # null end tag not supported class XHTMLSyntax(XMLSyntax): empty_stagc = " />" class DoctypeInfo: syntax = XMLSyntax() fpi = None sysid = None def __init__(self): self.__empties = {} self.__elements_only = {} self.__attribs = {} def is_empty(self, gi): return self.__empties.has_key(gi) def get_empties_list(self): return self.__empties.keys() def has_element_content(self, gi): return self.__elements_only.has_key(gi) def get_element_containers_list(self): return self.__elements_only.keys() def get_attributes_list(self, gi): return self.__attribs.get(gi, {}).keys() def get_attribute_info(self, gi, attr): return self.__attribs[gi][attr] def add_empty(self, gi): self.__empties[gi] = 1 def add_element_container(self, gi): self.__elements_only[gi] = gi def add_attribute_defn(self, gi, attr, type, decl, default): try: d = self.__attribs[gi] except KeyError: d = self.__attribs[gi] = {} if not d.has_key(attr): d[attr] = (type, decl, default) else: print "<%s> attribute %s already defined" % (gi, attr) def load_pubtext(self, pubtext): raise NotImplementedError, "sublasses must implement load_pubtext()" class _XMLDTDLoader(xml.parsers.xmlproc.xmlapp.DTDConsumer): def __init__(self, info, parser): self.info = info xml.parsers.xmlproc.xmlapp.DTDConsumer.__init__(self, parser) self.new_attribute = info.add_attribute_defn def new_element_type(self, gi, model): if model[0] == "|" and model[1][0] == ("#PCDATA", ""): # no action required pass elif model == ("", [], ""): self.info.add_empty(gi) else: self.info.add_element_container(gi) class XMLDoctypeInfo(DoctypeInfo): def load_pubtext(self, sysid): parser = xml.parsers.xmlproc.dtdparser.DTDParser() loader = _XMLDTDLoader(self, parser) parser.set_dtd_consumer(loader) parser.parse_resource(sysid) class XHTMLDoctypeInfo(XMLDoctypeInfo): # Bogus W3C cruft requires the extra space when terminating empty elements. syntax = XHTMLSyntax() class SGMLDoctypeInfo(DoctypeInfo): syntax = SGMLSyntax() import re __element_prefix_search = re.compile("": lit = self.__syntax.lit s = '%sxml version=%s1.0%s encoding%s%s%s%s' % ( self.__syntax.pio, lit, lit, self.__syntax.vi, lit, self._encoding, lit) if self.__standalone: s = '%s standalone%s%s%s%s' % ( s, self.__syntax.vi, lit, self.__standalone, lit) self._write("%s%s\n" % (s, self.__syntax.pic)) def endDocument(self): if self.__stack: raise RuntimeError, "open element stack cannot be empty on close" def startElement(self, tag, attrs={}): if self.__pending_doctype: self.handle_doctype(tag) self._check_pending_content() self.__pushtag(tag) self.__check_flowing(tag, attrs) if attrs.has_key("xml:lang"): self.__lang = attrs["xml:lang"] del attrs["xml:lang"] if self._packing: prefix = "" elif self._flowing: prefix = self._prefix[:-self.indentation] else: prefix = "" stag = "%s%s%s" % (prefix, self.__syntax.stago, tag) prefix = "%s %s" % (prefix, (len(tag) * " ")) lit = self.__syntax.lit lita = self.__syntax.lita vi = self.__syntax.vi a = '' if self._flowing != self.__stack[-1][0]: if self._dtdflowing is not None \ and self._flowing == self._dtdflowing: pass else: a = ' xml:space%s%s%s%s' \ % (vi, lit, ["default", "preserve"][self._flowing], lit) if self.__lang != self.__stack[-1][1]: a = '%s xml:lang%s%s%s%s' % (a, vi, lit, self.lang, lit) line = stag + a self._offset = self._offset + len(line) a = '' for k, v in attrs.items(): if v is None: continue v = str(v) if string.find(v, lit) == -1: a = ' %s%s%s%s%s' % (k, vi, lit, escape(str(v)), lit) elif string.find(v, lita) == -1: a = ' %s%s%s%s%s' % (k, vi, lita, escape(str(v)), lita) else: a = ' %s%s%s%s%s' % (k, vi, lit, escape(str(v), {lit:self.__syntax.lit_quoted}), lita) if (self._offset + len(a)) > self.lineLength: self._write(line + "\n") line = prefix + a self._offset = len(line) else: line = line + a self._offset = self._offset + len(a) self._write(line) self.__pending_content = 1 if ( self.__dtdinfo and not (self.__dtdinfo.has_element_content(tag) or self.__dtdinfo.is_empty(tag))): self._packing = 1 def endElement(self, tag): if self.__pending_content: if self._flowing: self._write(self.__syntax.empty_stagc) if self._packing: self._offset = self._offset \ + len(self.__syntax.empty_stagc) else: self._write("\n") self._offset = 0 else: self._write(self.__syntax.empty_stagc) self._offset = self._offset + len(self.__syntax.empty_stagc) self.__pending_content = 0 self.__poptag(tag) return depth = len(self.__stack) if depth == 1 or self._packing or not self._flowing: prefix = '' else: prefix = self._prefix[:-self.indentation] \ + (" " * self.indentEndTags) self.__poptag(tag) self._write("%s%s%s%s" % ( prefix, self.__syntax.etago, tag, self.__syntax.tagc)) if self._packing: self._offset = self._offset + len(tag) + 3 else: self._write("\n") self._offset = 0 def characters(self, data, start, length): data = data[start: start+length] if data: self._check_pending_content() data = escape(data) if "\n" in data: p = string.find(data, "\n") self._offset = len(data) - (p + 1) else: self._offset = self._offset + len(data) self._check_pending_content() self._write(data) def comment(self, data, start, length): data = data[start: start+length] self._check_pending_content() s = "%s%s%s%s%s" % (self.__syntax.mdo, self.__syntax.com, data, self.__syntax.com, self.__syntax.mdc) p = string.rfind(s, "\n") if self._packing: if p >= 0: self._offset = len(s) - (p + 1) else: self._offset = self._offset + len(s) else: self._write("%s%s\n" % (self._prefix, s)) self._offset = 0 def ignorableWhitespace(self, data, start, length): pass def processingInstruction(self, target, data): s = "%s%s %s%s" % (self.__syntax.pio, target, data, self.__syntax.pic) prefix = self._prefix[:-self.indentation] \ + (" " * self.indentEndTags) if "\n" in s: pos = string.rfind(s, "\n") if self._flowing and not self._packing: self._write(prefix + s + "\n") self._offset = 0 else: self._write(s) self._offset = len(s) - (p + 1) elif self._flowing and not self._packing: self._write(prefix + s + "\n") self._offset = 0 else: self._write(s) self._offset = len(s) - (p + 1) # This doesn't actually have a SAX equivalent, so we'll use it as # an internal helper. def handle_doctype(self, root): self.__pending_doctype = 0 if self.__dtdinfo: fpi = self.__dtdinfo.fpi sysid = self.__dtdinfo.sysid else: fpi = sysid = None lit = self.__syntax.lit isxml = self.__syntax.pic == "?>" if isxml and sysid: s = '%sDOCTYPE %s\n' % (self.__syntax.mdo, root) if fpi: s = s + ' PUBLIC %s%s%s\n' % (lit, fpi, lit) s = s + ' %s%s%s>\n' % (lit, sysid, lit) else: s = s + ' SYSTEM %s%s%s>\n' % (lit, sysid, lit) self._write(s) self._offset = 0 elif not isxml: s = "%sDOCTYPE %s" % (self.__syntax.mdo, root) if fpi: s = '%s\n PUBLIC %s%s%s' % (s, lit, fpi, lit) if sysid: s = '%s\n SYSTEM %s%s%s' % (s, lit, sysid, lit) self._write("%s%s\n" % (s, self.__syntax.mdc)) self._offset = 0 def handle_cdata(self, data): self._check_pending_content() # There should be a better way to generate '[CDATA[' start = self.__syntax.mdo + "[CDATA[" end = self.__syntax.msc + self.__syntax.mdc s = "%s%s%s" % (start, escape(data), end) if self._packing: if "\n" in s: rpos = string.rfind(s, "\n") self._offset = len(s) - (rpos + 1) + len(end) else: self._offset = self._offset + len(s) + len(start + end) self._write(s) else: self._offset = 0 self._write(s + "\n") # Internal helper methods. def __poptag(self, tag): state = self.__stack.pop() self._flowing, self.__lang, expected_tag, \ self._packing, self._dtdflowing = state if tag != expected_tag: raise RuntimeError, \ "expected , got " % (expected_tag, tag) self._prefix = self._prefix[:-self.indentation] def __pushtag(self, tag): self.__stack.append((self._flowing, self.__lang, tag, self._packing, self._dtdflowing)) self._prefix = self._prefix + " " * self.indentation def __check_flowing(self, tag, attrs): """Check the contents of attrs and the DTD information to determine whether the following content should be flowed. tag -- general identifier of the element being opened attrs -- attributes dictionary as reported by the parser or application This sets up both the _flowing and _dtdflowing (object) attributes. """ docspec = dtdspec = None if self.__dtdinfo: try: info = self.__dtdinfo.get_attribute_info(tag, "xml:space") except KeyError: info = None if info is not None: self._flowing = info[2] != "preserve" self._dtdflowing = self._flowing if attrs.has_key("xml:space"): self._flowing = attrs["xml:space"] != "preserve" del attrs["xml:space"] def _check_pending_content(self): if self.__pending_content: s = self.__syntax.tagc if self._flowing and not self._packing: s = s + "\n" self._offset = 0 else: self._offset = self._offset + len(s) self._write(s) self.__pending_content = 0 class PrettyPrinter(XmlWriter): """Pretty-printing XML output handler.""" def __init__(self, fp, standalone=None, dtdinfo=None, syntax=None, linelength=None, indentation=2, endtagindentation=None): XmlWriter.__init__(self, fp, standalone=standalone, dtdinfo=dtdinfo, syntax=syntax, linelength=linelength) self.indentation = indentation if endtagindentation is not None: self.indentEndTags = endtagindentation else: self.indentEndTags = indentation def characters(self, data, start, length): data = data[start: start + length] if not data: return self._check_pending_content() data = escape(data) if not self._flowing: self._write(data) return words = string.split(data) begspace = data[0] in string.whitespace endspace = words and (data[-1] in string.whitespace) prefix = self._prefix if len(prefix) > 40: prefix = " " offset = self._offset L = [] append = L.append if begspace: append(" ") offset = offset + 1 ws = "" ws_len = 0 while words: w = words[0] del words[0] if (offset + ws_len + len(w)) > self.lineLength: append("\n") append(prefix) append(w) offset = len(prefix) + len(w) else: append(ws) ws, ws_len = " ", 1 append(w) offset = offset + 1 + len(w) if endspace: append(" ") offset = offset + 1 self._offset = offset self._write(string.join(L, "")) PyXML-0.8.2/xml/sax/xmlreader.py0100644000076400001440000003044407256416334015657 0ustar martinusers"""An XML Reader is the SAX 2 name for an XML parser. XML Parsers should be based on this code. """ import handler from _exceptions import SAXNotSupportedException, SAXNotRecognizedException # ===== XMLREADER ===== class XMLReader: """Interface for reading an XML document using callbacks. XMLReader is the interface that an XML parser's SAX2 driver must implement. This interface allows an application to set and query features and properties in the parser, to register event handlers for document processing, and to initiate a document parse. All SAX interfaces are assumed to be synchronous: the parse methods must not return until parsing is complete, and readers must wait for an event-handler callback to return before reporting the next event.""" def __init__(self): self._cont_handler = handler.ContentHandler() self._dtd_handler = handler.DTDHandler() self._ent_handler = handler.EntityResolver() self._err_handler = handler.ErrorHandler() def parse(self, source): "Parse an XML document from a system identifier or an InputSource." raise NotImplementedError("This method must be implemented!") def getContentHandler(self): "Returns the current ContentHandler." return self._cont_handler def setContentHandler(self, handler): "Registers a new object to receive document content events." self._cont_handler = handler def getDTDHandler(self): "Returns the current DTD handler." return self._dtd_handler def setDTDHandler(self, handler): "Register an object to receive basic DTD-related events." self._dtd_handler = handler def getEntityResolver(self): "Returns the current EntityResolver." return self._ent_handler def setEntityResolver(self, resolver): "Register an object to resolve external entities." self._ent_handler = resolver def getErrorHandler(self): "Returns the current ErrorHandler." return self._err_handler def setErrorHandler(self, handler): "Register an object to receive error-message events." self._err_handler = handler def setLocale(self, locale): """Allow an application to set the locale for errors and warnings. SAX parsers are not required to provide localization for errors and warnings; if they cannot support the requested locale, however, they must throw a SAX exception. Applications may request a locale change in the middle of a parse.""" raise SAXNotSupportedException("Locale support not implemented") def getFeature(self, name): "Looks up and returns the state of a SAX2 feature." raise SAXNotRecognizedException("Feature '%s' not recognized" % name) def setFeature(self, name, state): "Sets the state of a SAX2 feature." raise SAXNotRecognizedException("Feature '%s' not recognized" % name) def getProperty(self, name): "Looks up and returns the value of a SAX2 property." raise SAXNotRecognizedException("Property '%s' not recognized" % name) def setProperty(self, name, value): "Sets the value of a SAX2 property." raise SAXNotRecognizedException("Property '%s' not recognized" % name) class IncrementalParser(XMLReader): """This interface adds three extra methods to the XMLReader interface that allow XML parsers to support incremental parsing. Support for this interface is optional, since not all underlying XML parsers support this functionality. When the parser is instantiated it is ready to begin accepting data from the feed method immediately. After parsing has been finished with a call to close the reset method must be called to make the parser ready to accept new data, either from feed or using the parse method. Note that these methods must _not_ be called during parsing, that is, after parse has been called and before it returns. By default, the class also implements the parse method of the XMLReader interface using the feed, close and reset methods of the IncrementalParser interface as a convenience to SAX 2.0 driver writers.""" def __init__(self, bufsize=2**16): self._bufsize = bufsize XMLReader.__init__(self) def parse(self, source): import saxutils source = saxutils.prepare_input_source(source) self.prepareParser(source) file = source.getByteStream() buffer = file.read(self._bufsize) while buffer != "": self.feed(buffer) buffer = file.read(self._bufsize) self.close() def feed(self, data): """This method gives the raw XML data in the data parameter to the parser and makes it parse the data, emitting the corresponding events. It is allowed for XML constructs to be split across several calls to feed. feed may raise SAXException.""" raise NotImplementedError("This method must be implemented!") def prepareParser(self, source): """This method is called by the parse implementation to allow the SAX 2.0 driver to prepare itself for parsing.""" raise NotImplementedError("prepareParser must be overridden!") def close(self): """This method is called when the entire XML document has been passed to the parser through the feed method, to notify the parser that there are no more data. This allows the parser to do the final checks on the document and empty the internal data buffer. The parser will not be ready to parse another document until the reset method has been called. close may raise SAXException.""" raise NotImplementedError("This method must be implemented!") def reset(self): """This method is called after close has been called to reset the parser so that it is ready to parse new documents. The results of calling parse or feed after close without calling reset are undefined.""" raise NotImplementedError("This method must be implemented!") # ===== LOCATOR ===== class Locator: """Interface for associating a SAX event with a document location. A locator object will return valid results only during calls to DocumentHandler methods; at any other time, the results are unpredictable.""" def getColumnNumber(self): "Return the column number where the current event ends." return -1 def getLineNumber(self): "Return the line number where the current event ends." return -1 def getPublicId(self): "Return the public identifier for the current event." return None def getSystemId(self): "Return the system identifier for the current event." return None # ===== INPUTSOURCE ===== class InputSource: """Encapsulation of the information needed by the XMLReader to read entities. This class may include information about the public identifier, system identifier, byte stream (possibly with character encoding information) and/or the character stream of an entity. Applications will create objects of this class for use in the XMLReader.parse method and for returning from EntityResolver.resolveEntity. An InputSource belongs to the application, the XMLReader is not allowed to modify InputSource objects passed to it from the application, although it may make copies and modify those.""" def __init__(self, system_id = None): self.__system_id = system_id self.__public_id = None self.__encoding = None self.__bytefile = None self.__charfile = None def setPublicId(self, public_id): "Sets the public identifier of this InputSource." self.__public_id = public_id def getPublicId(self): "Returns the public identifier of this InputSource." return self.__public_id def setSystemId(self, system_id): "Sets the system identifier of this InputSource." self.__system_id = system_id def getSystemId(self): "Returns the system identifier of this InputSource." return self.__system_id def setEncoding(self, encoding): """Sets the character encoding of this InputSource. The encoding must be a string acceptable for an XML encoding declaration (see section 4.3.3 of the XML recommendation). The encoding attribute of the InputSource is ignored if the InputSource also contains a character stream.""" self.__encoding = encoding def getEncoding(self): "Get the character encoding of this InputSource." return self.__encoding def setByteStream(self, bytefile): """Set the byte stream (a Python file-like object which does not perform byte-to-character conversion) for this input source. The SAX parser will ignore this if there is also a character stream specified, but it will use a byte stream in preference to opening a URI connection itself. If the application knows the character encoding of the byte stream, it should set it with the setEncoding method.""" self.__bytefile = bytefile def getByteStream(self): """Get the byte stream for this input source. The getEncoding method will return the character encoding for this byte stream, or None if unknown.""" return self.__bytefile def setCharacterStream(self, charfile): """Set the character stream for this input source. (The stream must be a Python 2.0 Unicode-wrapped file-like that performs conversion to Unicode strings.) If there is a character stream specified, the SAX parser will ignore any byte stream and will not attempt to open a URI connection to the system identifier.""" self.__charfile = charfile def getCharacterStream(self): "Get the character stream for this input source." return self.__charfile # ===== ATTRIBUTESIMPL ===== class AttributesImpl: def __init__(self, attrs): """Non-NS-aware implementation. attrs should be of the form {name : value}.""" self._attrs = attrs def getLength(self): return len(self._attrs) def getType(self, name): return "CDATA" def getValue(self, name): return self._attrs[name] def getValueByQName(self, name): return self._attrs[name] def getNameByQName(self, name): if not self._attrs.has_key(name): raise KeyError, name return name def getQNameByName(self, name): if not self._attrs.has_key(name): raise KeyError, name return name def getNames(self): return self._attrs.keys() def getQNames(self): return self._attrs.keys() def __len__(self): return len(self._attrs) def __getitem__(self, name): return self._attrs[name] def keys(self): return self._attrs.keys() def has_key(self, name): return self._attrs.has_key(name) def get(self, name, alternative=None): return self._attrs.get(name, alternative) def copy(self): return self.__class__(self._attrs) def items(self): return self._attrs.items() def values(self): return self._attrs.values() # ===== ATTRIBUTESNSIMPL ===== class AttributesNSImpl(AttributesImpl): def __init__(self, attrs, qnames): """NS-aware implementation. attrs should be of the form {(ns_uri, lname): value, ...}. qnames of the form {(ns_uri, lname): qname, ...}.""" self._attrs = attrs self._qnames = qnames def getValueByQName(self, name): for (nsname, qname) in self._qnames.items(): if qname == name: return self._attrs[nsname] raise KeyError, name def getNameByQName(self, name): for (nsname, qname) in self._qnames.items(): if qname == name: return nsname raise KeyError, name def getQNameByName(self, name): return self._qnames[name] def getQNames(self): return self._qnames.values() def copy(self): return self.__class__(self._attrs, self._qnames) def _test(): XMLReader() IncrementalParser() Locator() if __name__ == "__main__": _test() PyXML-0.8.2/xml/schema/0040755000076400001440000000000007614726123013763 5ustar martinusersPyXML-0.8.2/xml/schema/__init__.py0100644000076400001440000000004607261345574016076 0ustar martinusers"This package collects XML schemata." PyXML-0.8.2/xml/schema/trex.py0100644000076400001440000016520707534565153015334 0ustar martinusers# PyTREX: A clean-room implementation of TREX in Python # by James Tauber # # http://pytrex.sourceforge.net/ # # Copyright (c) 2001, James Tauber # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * The name "James Tauber" may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. ######################################################################## # # TO USE FROM THE COMMAND LINE: # - python pytrex.py # # TO USE IN OTHER PYTHON SCRIPTS: # - import the pytrex.py file (must be on PYTHONPATH): # from pytrex import * # - parse the TREX file: # trex = parse_TREX("foo.trex") # - parse the instance file: # instance = parse_Instance("bar.xml") # - validate # match = validate(trex, instance) # match will be an Error object if invalid - test with isError() # # You can see an internal representation of the TREX grammar and the # instance with trex.display() and instance.display() respectively # # You can also see a representation of the match object returned by # validate with match.display() # # NOT IMPLEMENTED YET # - ns attribute inheritance that takes into account inclusion # - anonymous datatypes # # questions: # # zeroOrMore = empty | oneOrMore # but empty doesn't allow whitespace and zeroOrMore does # # DATATYPE SUPPORT # # PyTREX has support for named datatypes in general but none in # particular. To add support for a particular datatype, write a # function (or lambda) that takes a string and returns 1 or 0 # depending on whether the datatype allows the given string as a # lexical representation. Then register the datatype by calling: # # register_datatype(, , # ) ######################################################################## ### COMMON class HandlerBase: def __init__(self, parser, parent, atts): self.parser = parser self.parent = parent if self.parent != None: self.ns_decls = self.parent.ns_decls else: self.ns_decls = {} self.set_handlers() def set_handlers(self): self.parser.StartElementHandler = self.child self.parser.CharacterDataHandler = self.char self.parser.EndElementHandler = self.end self.parser.StartNamespaceDeclHandler = self.start_ns_decl self.parser.EndNamespaceDeclHandler = self.end_ns_decl def start_ns_decl(self, prefix, uri): self.ns_decls[prefix] = uri def end_ns_decl(self, prefix): del self.ns_decls[prefix] def child(self, name, atts): pass def char(self, data): pass def child(self, name, atts): pass def end(self, name): if self.parent != None: self.parent.set_handlers() else: # must be root pass ######################################################################## ### TREX PARSING trex_ns = "http://www.thaiopensource.com/trex" def parse_TREX(location, baseURI=None): if baseURI==None: baseURI = location import xml.parsers.expat parser = xml.parsers.expat.ParserCreate(namespace_separator="^") parser.SetBase(baseURI) parser.returns_unicode = 1 r = T_RootHandler(parser) from urllib2 import urlopen # TODO: doesn't catch well-formedness errors in TREX try: f = urlopen(location) parser.ParseFile(f) except IOError, e: print "IOError reading TREX file", e import sys; sys.exit() except xml.parsers.expat.error: print "Error parsing file at line '%s' and column '%s'\n" % (parser.ErrorLineNumber, parser.ErrorColumnNumber) f.close() import sys; sys.exit() except TREXError, e: print "Error parsing TREX file:", e.value f.close() import sys; sys.exit() f.close() return r.product class TREXError: def __init__(self, value): self.value = value class T_HandlerBase(HandlerBase): def __init__(self, parser, parent, atts): HandlerBase.__init__(self, parser, parent, atts) if atts != None: if atts.has_key("ns"): self.ns_attr = atts["ns"] else: self.ns_attr = parent.ns_attr else: # must be root self.ns_attr = "" if parent != None: self.using_trex_ns = parent.using_trex_ns # handle children of elements that can take pattern children def child_pattern(self, name, atts): if not handlePattern(self.parser, self, name, atts): if in_trex_ns(name): raise TREXError, "%s not allowed here" % name elif not self.using_trex_ns and in_default_ns(name): raise TREXError, "%s not allowed here" % name else: T_Ignore(self.parser, self, name, atts) # handle children of elements that take name-class def child_nameclass(self, name, atts): if not handleNameClass(self.parser, self, name, atts): if in_trex_ns(name): raise TREXError, "%s not allowed here" % name elif not self.using_trex_ns and in_default_ns(name): raise TREXError, "%s not allowed here" % name else: T_Ignore(self.parser, self, name, atts) # handle children of elements that take name-class and patterns def child_nameclass_pattern(self, name, atts): if self.product.name_class==None: self.child_nameclass(name, atts) else: self.child_pattern(name, atts) # handle children of elements that take no children def child_none(self, name, atts): raise TREXError, "%s not allowed here" % name # handler children of elements that can only take non-trex children def child_non_trex(self, name, atts): if in_trex_ns(name): raise TREXError, "%s not allowed here" % ncname elif not self.using_trex_ns and in_default_ns(name): raise TREXError, "%s not allowed here" % ncname else: T_Ignore(self.parser, self, name, atts) class T_Ignore(T_HandlerBase): def __init__(self, parser, parent, name, atts): T_HandlerBase.__init__(self, parser, parent, None) child = T_HandlerBase.child_non_trex class T_RootHandler(T_HandlerBase): def __init__(self, parser, parent = None, atts = None): T_HandlerBase.__init__(self, parser, parent, atts) def child(self, name, atts): if name[:len(trex_ns)+1] == trex_ns+"^": self.using_trex_ns = 1 else: self.using_trex_ns = 0 if not handlePattern(self.parser, self, name, atts): raise TREXError, "%s not supported as root" % name def add_pattern(self, pattern): self.product = pattern def in_trex_ns(name): return name[:len(trex_ns)+1] == trex_ns+"^" def in_default_ns(name): return not "^" in name def trex_ncname(name, using_trex_ns): if in_trex_ns(name): if using_trex_ns: return name[len(trex_ns)+1:] else: raise TREXError, "root pattern isn't in trex namespace but descendant is" else: if using_trex_ns: return "" else: return name def handleNameClass(parser, handler, name, atts): name = trex_ncname(name, handler.using_trex_ns) if name == "name": T_NameHandler(parser, handler, atts) elif name == "anyName": T_AnyNameHandler(parser, handler, atts) elif name == "nsName": T_NSNameHandler(parser, handler, atts) elif name == "choice": T_NameClass_ChoiceHandler(parser, handler, atts) elif name == "difference": T_DifferenceHandler(parser, handler, atts) elif name == "not": T_NotHandler(parser, handler, atts) else: return 0 return 1 def handlePattern(parser, handler, name, atts): name = trex_ncname(name, handler.using_trex_ns) if name=="element": T_ElementHandler(parser, handler, atts) elif name=="empty": T_EmptyHandler(parser, handler, atts) elif name=="notAllowed": T_NotAllowedHandler(parser, handler, atts) elif name=="zeroOrMore": T_ZeroOrMoreHandler(parser, handler, atts) elif name=="oneOrMore": T_OneOrMoreHandler(parser, handler, atts) elif name=="anyString": T_AnyStringHandler(parser, handler, atts) elif name=="string": T_StringHandler(parser, handler, atts) elif name=="optional": T_OptionalHandler(parser, handler, atts) elif name=="choice": T_ChoiceHandler(parser, handler, atts) elif name=="concur": T_ConcurHandler(parser, handler, atts) elif name=="interleave": T_InterleaveHandler(parser, handler, atts) elif name=="mixed": T_MixedHandler(parser, handler, atts) elif name=="group": T_GroupHandler(parser, handler, atts) elif name=="attribute": T_AttributeHandler(parser, handler, atts) elif name=="grammar": T_GrammarHandler(parser, handler, atts) elif name=="ref": T_RefHandler(parser, handler, atts) elif name=="include": T_IncludeHandler(parser, handler, atts) elif name=="data": T_DataHandler(parser, handler, atts) else: return 0 return 1 class T_ElementHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = T_Element() if atts.has_key("name"): name = atts["name"] if ":" in name: # QName from string import split prefix, ncname = split(name, ":") if self.ns_decls.has_key(prefix): ns = self.ns_decls[prefix] else: raise TREXError, "QName %s has unknown prefix" % name else: ns = self.ns_attr ncname = name self.add_nameclass(ExpandedName(ns, ncname)) child = T_HandlerBase.child_nameclass_pattern def end(self, name): if self.product.name_class==None: raise TREXError, "element must have a name" self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_nameclass(self, name_class): self.product.name_class = name_class def add_pattern(self, pattern): if self.product.pattern==None: self.product.pattern = pattern else: group = T_Group(self.product.pattern, pattern) self.product.pattern = group class T_AttributeHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = T_Attribute() if atts.has_key("ns"): local_ns = atts["ns"] else: local_ns = "" if atts.has_key("global") and atts["global"] == "true": ns = self.ns_attr else: ns = local_ns if atts.has_key("name"): name = atts["name"] if ":" in name: # QName from string import split prefix, ncname = split(name, ":") if self.ns_decls.has_key(prefix): ns = self.ns_decls[prefix] else: raise TREXError, "QName %s has unknown prefix" % name else: # ns already established earlier ncname = name self.add_nameclass(ExpandedName(ns, ncname)) child = T_HandlerBase.child_nameclass_pattern def end(self, name): if self.product.name_class==None: raise TREXError, "attribute must have a name" if self.product.pattern==None: self.product.pattern = T_AnyString() self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_nameclass(self, name_class): self.product.name_class = name_class def add_pattern(self, pattern): self.product.pattern = pattern class T_NameHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = ExpandedName() self.chardata = "" def char(self, data): self.chardata = self.chardata + data child = T_HandlerBase.child_none def end(self, name): self.product.namespaceURI = "" self.product.NCName = self.chardata self.parent.add_nameclass(self.product) T_HandlerBase.end(self, name) class T_AnyNameHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = AnyName() def char(self, data): raise TREXError, "anyName should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_nameclass(self.product) T_HandlerBase.end(self, name) class T_NSNameHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = NSName(self.ns_attr) def char(self, data): raise TREXError, "nsName should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_nameclass(self.product) T_HandlerBase.end(self, name) class T_EmptyHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = T_Empty() def char(self, data): raise TREXError, "empty should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) class T_NotAllowedHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = T_NotAllowed() def char(self, data): raise TREXError, "notAllowed should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) class T_AnyStringHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = T_AnyString() def char(self, data): raise TREXError, "anyString should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) class T_StringHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.chardata = "" self.whitespace_normalize = 1 if atts.has_key("whiteSpace"): if atts["whiteSpace"]=="normalize": self.whitespace_normalize = 1 elif atts["whiteSpace"]=="preserve": self.whitespace_normalize = 0 else: raise TREXError, "whiteSpace attribute on string must be normalize or preserve, not %s" % atts["whiteSpace"] def char(self, data): self.chardata = self.chardata + data child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_pattern(T_String(self.chardata, self.whitespace_normalize)) T_HandlerBase.end(self, name) class T_DataHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) if atts.has_key("type"): type = atts["type"] if ":" in type: # QName from string import split prefix, ncname = split(type, ":") if self.ns_decls.has_key(prefix): ns = self.ns_decls[prefix] else: raise TREXError, "QName %s has unknown prefix" % name else: ns = self.ns_attr ncname = type self.type_namespace = ns self.type_ncname = ncname else: raise TREXError, "data must have type attribute" def char(self, data): raise TREXError, "data should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_pattern(T_Data(self.type_namespace, self.type_ncname)) T_HandlerBase.end(self, name) class T_IncludeHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) if atts.has_key("href"): self.product = parse_TREX(atts["href"]) else: raise TREXError, "include must have href attribute" def char(self, data): raise TREXError, "include should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) class T_ZeroOrMoreHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): self.product = T_Choice(T_Empty(), T_OneOrMore(pattern)) class T_MixedHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): self.product = T_Interleave(T_AnyString(), pattern) class T_OneOrMoreHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): self.product = T_OneOrMore(pattern) class T_OptionalHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): self.product = T_Choice(T_Empty(), pattern) class T_ChoiceHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.pattern_1 = None self.pattern_2 = None child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): if self.pattern_1==None: self.pattern_1 = pattern self.product = self.pattern_1 elif self.pattern_2==None: self.pattern_2 = pattern self.product = T_Choice(self.pattern_1, self.pattern_2) else: self.product = T_Choice(self.product, pattern) class T_ConcurHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.pattern_1 = None self.pattern_2 = None child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): if self.pattern_1==None: self.pattern_1 = pattern self.product = self.pattern_1 elif self.pattern_2==None: self.pattern_2 = pattern self.product = T_Concur(self.pattern_1, self.pattern_2) else: self.product = T_Concur(self.product, pattern) class T_NameClass_ChoiceHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.nameclass_1 = None self.nameclass_2 = None child = T_HandlerBase.child_nameclass def end(self, name): self.parent.add_nameclass(self.product) T_HandlerBase.end(self, name) def add_nameclass(self, nameclass): if self.nameclass_1==None: self.nameclass_1 = nameclass self.product = self.nameclass_1 elif self.nameclass_2==None: self.nameclass_2 = nameclass self.product = NameClassChoice(self.nameclass_1, self.nameclass_2) else: self.product = NameClassChoice(self.product, nameclass) class T_NotHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.nameclass = None child = T_HandlerBase.child_nameclass def end(self, name): self.parent.add_nameclass(self.product) T_HandlerBase.end(self, name) def add_nameclass(self, nameclass): self.product = Difference(AnyName(), nameclass) class T_DifferenceHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.nameclass_1 = None self.nameclass_2 = None child = T_HandlerBase.child_nameclass def end(self, name): self.parent.add_nameclass(self.product) T_HandlerBase.end(self, name) def add_nameclass(self, nameclass): if self.nameclass_1==None: self.nameclass_1 = nameclass self.product = self.nameclass_1 elif self.nameclass_2==None: self.nameclass_2 = nameclass self.product = Difference(self.nameclass_1, self.nameclass_2) else: self.product = Difference(self.product, nameclass) class T_InterleaveHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.pattern_1 = None self.pattern_2 = None child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): if self.pattern_1==None: self.pattern_1 = pattern self.product = self.pattern_1 elif self.pattern_2==None: self.pattern_2 = pattern self.product = T_Interleave(self.pattern_1, self.pattern_2) else: self.product = T_Interleave(self.product, pattern) class T_GroupHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.pattern_1 = None child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def add_pattern(self, pattern): if self.pattern_1==None: self.product = self.pattern_1 = pattern else: self.product = self.pattern_1 = T_Group(self.pattern_1, pattern) class T_GrammarHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = T_Grammar() def child(self, name, atts): ncname = trex_ncname(name, self.using_trex_ns) if ncname=="start": T_StartHandler(self.parser, self, atts) elif ncname=="define": T_DefineHandler(self.parser, self, atts) elif ncname=="include": T_IncludeGrammarHandler(self.parser, self, atts) else: self.child_non_trex(name, atts) def end(self, name): if self.product.start==None: raise TREXError, "grammar must have a start" self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) def set_start(self, pattern, combine=None): if self.product.start==None: self.product.start = pattern else: if combine=="replace": self.product.start = pattern elif combine=="choice": self.product.start = T_Choice(self.product.start, pattern) elif combine=="group": self.product.start = T_Group(self.product.start, pattern) elif combine=="interleave": self.product.start = T_Interleave(self.product.start, pattern) elif combine=="concur": raise TREXError, "combine='%s' not supported yet" % combine elif combine==None: self.product.start = pattern #TODO is this allowed? else: raise TREXError, "unknown value %s for combine" % combine def add_definition(self, name, pattern, combine=None): if not self.product.definitions.has_key(name): self.product.add_definition(name, pattern) else: if combine=="replace": self.product.add_definition(name, pattern) elif combine=="choice": self.product.add_definition(name, T_Choice(self.product.definitions[name], pattern)) elif combine=="group": self.product.add_definition(name, T_Group(self.product.definitions[name], pattern)) elif combine=="interleave": self.product.add_definition(name, T_Interleave(self.product.definitions[name], pattern)) elif combine=="concur": raise TREXError, "combine='%s' not supported yet" % combine elif combine==None: raise TREXError, "overriding '%s' of grammar" % name else: raise TREXError, "unknown value %s for combine" % combine class T_IncludeGrammarHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) if atts.has_key("href"): self.product = parse_TREX(atts["href"]) else: raise TREXError, "include must have href attribute" def char(self, data): raise TREXError, "include should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.set_start(self.product.start) for definition_name in self.product.definitions.keys(): self.parent.add_definition(definition_name, self.product.definitions[definition_name]) T_HandlerBase.end(self, name) class T_StartHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.product = None if atts.has_key("name"): self.name = atts["name"] else: self.name = None if atts.has_key("combine"): self.combine = atts["combine"] else: self.combine = None child = T_HandlerBase.child_pattern def end(self, name): if self.product==None: raise TREXError, "start must contain a pattern" self.parent.set_start(self.product) if self.name != None: self.parent.add_definition(self.name, self.product, self.combine) T_HandlerBase.end(self, name) def add_pattern(self, pattern): self.product = pattern class T_RefHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) if atts.has_key("name"): name = atts["name"] else: raise TREXError, "ref must have name attribute" if atts.has_key("parent"): if atts["parent"] == "true": parent = 1 elif atts["parent"] == "false": parent = 0 else: raise TREXError, "ref parent attribute must be 'true' or 'false', not '%s'" % atts["parent"] else: parent = 0 self.product = T_Ref(name, parent) def char(self, data): raise TREXError, "ref should not have character data" child = T_HandlerBase.child_non_trex def end(self, name): self.parent.add_pattern(self.product) T_HandlerBase.end(self, name) class T_DefineHandler(T_HandlerBase): def __init__(self, parser, parent, atts): T_HandlerBase.__init__(self, parser, parent, atts) self.pattern = None if atts.has_key("name"): self.name = atts["name"] else: raise TREXError, "define must have a name" if atts.has_key("combine"): self.combine = atts["combine"] else: self.combine = None child = T_HandlerBase.child_pattern def end(self, name): self.parent.add_definition(self.name, self.pattern, self.combine) T_HandlerBase.end(self, name) def add_pattern(self, pattern): if self.pattern==None: self.pattern = pattern else: self.pattern = T_Group(self.pattern, pattern) ######################################################################## ### TREX REPRESENTATION / VALIDATION def validate(trex, instance): return trex.M({}, instance.children, {}) class Pattern: # each pattern has the following methods: # # display() # prints a string representation of the pattern # (recursing over components) # # M(a,c,e) # returns a Match object indicating whether the match succeeded or, # if not, why not # # M_consume(a,c,e) # similar to M above but allows for the match to consume only part of # a and c. Because of non-determinism, multiple consumptions are possible # and so the Match object returned will contain a list of possible # remainders unless no matches are possible # # M_interleave(a,c,e) # similar to M_consume but implements interleaving by allowing # consumption from any part of the given c pass class Match: # returned by M and M_consume def __init__(self, remainder=None): if remainder==None: self.remainders = [] else: self.remainders = [remainder] def add(self, match): self.remainders.extend(match.remainders) def isError(self): return 0 def display(self): print "(MATCH [", for remainder in self.remainders: remainder.display() print "] )", def __repr__(self): return "" % self.remainders def __cmp__(self, other): if self.remainders == other.remainders: return 0 else: return -1 class Error(Match): def __init__(self, message, *children): self.message = message self.children = children def isError(self): return 1 def display(self): print "(ERROR", print self.message, for error in self.children: error.display() print ")", class Remainder: def __init__(self, a, c): self.a = a self.c = c def display(self): print "(",self.a, "[", for node in self.c: node.display() print "] )", def __repr__(self): return "<%s,%s>" % (self.a, self.c) def __cmp__(self, other): if other==None: return -1 if self.a != other.a: return -1 if self.c != other.c: return -1 return 0 class Environment: def __init__(self, e={}, parent=None): self.e = e self.parent = parent def normalize(s): ns = "" state = 0 for c in s: if state==0: if c in [chr(9),chr(10),chr(13),chr(32)]: continue else: ns = ns + c state=1 continue elif state==1: if c in [chr(9),chr(10),chr(13),chr(32)]: state=2 continue else: ns = ns + c continue elif state==2: if c in [chr(9),chr(10),chr(13),chr(32)]: continue else: ns = ns + " " + c state=1 return ns datatype_registry = {} # test_function must take a string and return a boolean (ie 1 or 0) def register_datatype(namespace_uri, ncname, test_function): datatype_registry[namespace_uri + "^" + ncname] = test_function def allows(namespace_uri, ncname, s): key = namespace_uri + "^" + ncname if datatype_registry.has_key(key): if datatype_registry[namespace_uri + "^" + ncname](s): return Match() else: return Error("'%s' not allowed by '%s' in '%s'" % (s, ncname, namespace_uri)) else: return Error("unknown datatype '%s' in '%s'" % (ncname, namespace_uri)) # sample datatype test function (used by tests) def is_integer(cdata): try: int(cdata) except ValueError: return 0 return 1 # sample datatype registration register_datatype("http://pytrex.sourceforge.net/2001/03", "integer", is_integer) class T_Element(Pattern): def __init__(self, name_class=None, pattern=None): self.name_class = name_class self.pattern = pattern def display(self): print "(ELEMENT", self.name_class.display() self.pattern.display() print ")", def M(self, a, c, e): if len(a) > 0: return Error("has attributes") c_state=0 for node in c: if node.is_whitespace(): continue if node.is_element(): if c_state==1: return Error("second element") n = node.expanded_name a_1 = node.attributes c_1 = node.children c_state=1 if c_state==0: return Error("no element") match = self.name_class.C(n) if match.isError(): return Error("name doesn't match", match) match = self.pattern.M(a_1,c_1,e) if match.isError(): return Error("pattern doesn't match", match) return Match() def M_consume(self, a, c, e): c_state=0 for pos in range(0,len(c)): if c[pos].is_whitespace(): continue if c[pos].is_element(): if c_state==1: return Match(Remainder(a, c[pos:])) n = c[pos].expanded_name a_1 = c[pos].attributes c_1 = c[pos].children c_state=1 match = self.name_class.C(n) if match.isError(): return Error("name doesn't match", match) match = self.pattern.M(a_1, c_1, e) if match.isError(): return Error("pattern doesn't match", match) if c_state==0: return Error("no element") match = self.name_class.C(n) if match.isError(): return Error("name doesn't match", match) match = self.pattern.M(a_1, c_1, e) if match.isError(): return Error("pattern doesn't match", match) return Match(Remainder(a, [])) def M_interleave(self, a, c, e): c_2 = [] taken = 0 for pos in range(0,len(c)): if c[pos].is_element(): n = c[pos].expanded_name a_1 = c[pos].attributes c_1 = c[pos].children match = self.name_class.C(n) if match.isError(): c_2.append(c[pos]) continue match = self.pattern.M(a_1, c_1, e) if match.isError(): c_2.append(c[pos]) continue taken = 1 else: c_2.append(c[pos]) if taken: return Match(Remainder(a, c_2)) else: return Error("element in interleave did not match") class T_Attribute(Pattern): def __init__(self, name_class=None, pattern=None): self.name_class = name_class self.pattern = pattern def display(self): print "(ATTRIBUTE", self.name_class.display() self.pattern.display() print ")", def M(self, a, c, e): if len(c)>0: return Error("has children when should be empty") if len(a)!=1: return Error("incorrect number of attributes") n = a[0].expanded_name v = a[0].value match_1 = self.name_class.C(n) match_2 = self.pattern.M({}, v, e) if (not match_1.isError()) and (not match_2.isError()): return Match() return Error("attribute did not match") def M_consume(self, a, c, e): for attr in a: n = attr.expanded_name v = attr.value match_1 = self.name_class.C(n) match_2 = self.pattern.M({}, v, e) if (not match_1.isError()) and (not match_2.isError()): a_2 = [] for attr2 in a: if attr2 != attr: a_2.append(attr2) return Match(Remainder(a_2,c)) return Error("attribute didn't match") # or should this be Match(Remainder(a,c)) M_interleave = M_consume class T_Empty(Pattern): def display(self): print "(EMPTY)", def M(self, a, c, e): if len(a) > 0: return Error("has attributes") if len(c) > 0: return Error("has children when should be empty") return Match() def M_consume(self, a, c, e): return Match(Remainder(a,c)) M_interleave = M_consume class T_NotAllowed(Pattern): def display(self): print "(NOT-ALLOWED)", def M(self, a, c, e): return Error("not allowed") M_consume = M M_interleave = M class T_AnyString(Pattern): def display(self): print "(ANY-STRING)", def M(self, a, c, e): if len(a) > 0: return Error("has attributes") for node in c: if node.is_element(): return Error("anyString but got element") return Match() def M_consume(self, a, c, e): if len(a) > 0: return Error("has attributes") if len(c)==0: return Error("anyString but no children") for pos in range(0,len(c)): if c[pos].is_element(): if pos==0: return Error("element where string required") else: return Match(Remainder(a,c[pos:])) return Match(Remainder(a,[])) def M_interleave(self, a, c, e): c_2 = [] taken = 0 for pos in range(0, len(c)): if c[pos].is_element(): c_2.append(c[pos]) else: taken=1 if taken: return Match(Remainder(a, c_2)) else: return Error("anyString but no characters") # TODO maybe this is okay!?!? class T_String(Pattern): def __init__(self, chardata, whitespace_normalize): self.chardata = chardata self.whitespace_normalize = whitespace_normalize def display(self): print "(STRING '%s')" % self.chardata def M(self, a, c, e): if len(a) > 0: return Error("has attributes") cdata = "" for node in c: if node.is_element(): return Error("string but got element") else: cdata = cdata + node.data if self.whitespace_normalize: if normalize(cdata) == normalize(self.chardata): return Match() else: return Error("character data '%s' did not match string '%s'" % (normalize(cdata), normalize(self.chardata))) else: if cdata == self.chardata: return Match() else: return Error("character data '%s' did not match string '%s'" % (cdata, self.chardata)) # TODO should flag an error in the following cases as string shouldn't # appear in group or interleave M_consume = M M_interleave = M class T_Data(Pattern): def __init__(self, type_namespace, type_ncname): self.type_namespace = type_namespace self.type_ncname = type_ncname def display(self): print "(DATA '%s' '%s')" % (self.type_namespace, self.type_ncname) def M(self, a, c, e): if len(a) > 0: return Error("has attributes") cdata = "" for node in c: if node.is_element(): return Error("string but got element") else: cdata = cdata + node.data return allows(self.type_namespace, self.type_ncname, cdata) # TODO should flag an error in the following cases as data shouldn't # appear in group or interleave M_consume = M M_interleave = M class T_Choice(Pattern): def __init__(self, pattern_1=None, pattern_2=None): self.pattern_1 = pattern_1 self.pattern_2 = pattern_2 def display(self): print "(CHOICE", self.pattern_1.display() self.pattern_2.display() print ")", def M(self, a, c, e): match_1 = self.pattern_1.M(a, c ,e) if not match_1.isError(): return Match() match_2 = self.pattern_2.M(a, c, e) if not match_2.isError(): return Match() return Error("both items of a choice failed", match_1, match_2) def M_consume(self, a, c, e): match = Match() match_1 = self.pattern_1.M_consume(a, c ,e) if not match_1.isError(): match.add(match_1) match_2 = self.pattern_2.M_consume(a, c, e) if not match_2.isError(): match.add(match_2) if match_1.isError() and match_2.isError(): return Error("both items of a choice failed", match_1, match_2) return match def M_interleave(self, a, c, e): match = Match() match_1 = self.pattern_1.M_interleave(a, c ,e) if not match_1.isError(): match.add(match_1) match_2 = self.pattern_2.M_interleave(a, c, e) if not match_2.isError(): match.add(match_2) if match_1.isError() and match_2.isError(): return Error("both items of a choice failed", match_1, match_2) return match class T_Concur(Pattern): def __init__(self, pattern_1=None, pattern_2=None): self.pattern_1 = pattern_1 self.pattern_2 = pattern_2 def display(self): print "(CONCUR", self.pattern_1.display() self.pattern_2.display() print ")", def M(self, a, c, e): match_1 = self.pattern_1.M(a, c ,e) if match_1.isError(): return match_1 match_2 = self.pattern_2.M(a, c, e) if match_2.isError(): return match_2 return Match() def M_consume(self, a, c, e): match_1 = self.pattern_1.M_consume(a, c ,e) if match_1.isError(): return match_1 match_2 = self.pattern_2.M_consume(a, c, e) if match_2.isError(): return match_2 if match_1 == match_2: return match_1 else: return Error("two patterns of concur consumed different amounts") def M_interleave(self, a, c, e): match_1 = self.pattern_1.M_interleave(a, c ,e) if match_1.isError(): return match_1 match_2 = self.pattern_2.M_interleave(a, c, e) if match_2.isError(): return match_2 if match_1 == match_2: return match_1 else: return Error("two patterns of concur interleaved different amounts") class T_Interleave(Pattern): def __init__(self, pattern_1=None, pattern_2=None): self.pattern_1 = pattern_1 self.pattern_2 = pattern_2 def display(self): print "(INTERLEAVE", self.pattern_1.display() self.pattern_2.display() print ")", def M(self, a, c, e): match_1 = self.pattern_1.M_interleave(a,c,e) if match_1.isError(): return Error("first pattern of interleave failed", match_1) match = Match() for remainder in match_1.remainders: a_2 = remainder.a c_2 = remainder.c match = self.pattern_2.M(a_2, c_2, e) if not match.isError(): return Match() return Error("second pattern of interleave failed", match) def M_consume(self, a, c, e): match_1 = self.pattern_1.M_interleave(a,c,e) if match_1.isError(): return Error("first pattern of interleave failed", match_1) match = Match() for remainder in match_1.remainders: a_2 = remainder.a c_2 = remainder.c match = self.pattern_2.M_consume(a_2, c_2, e) if not match.isError(): return match return Error("second pattern of interleave failed", match) def M_interleave(self, a, c, e): match_1 = self.pattern_1.M_interleave(a,c,e) if match_1.isError(): return Error("first pattern of interleave failed", match_1) match = Match() for remainder in match_1.remainders: a_2 = remainder.a c_2 = remainder.c match_2 = self.pattern_2.M_interleave(a_2, c_2, e) if not match.isError(): match.add(match_2) return match class T_OneOrMore(Pattern): def __init__(self, pattern=None): self.pattern = pattern def display(self): print "(ONE-OR-MORE", self.pattern.display() print ")", def M(self, a, c, e): group = T_Group(self.pattern, T_Choice(T_Empty(), T_OneOrMore(self.pattern))) match = group.M(a, c, e) if match.isError(): return Error("oneOrMore failed") return Match() def M_consume(self, a, c, e): group = T_Group(self.pattern, T_Choice(T_Empty(), T_OneOrMore(self.pattern))) return group.M_consume(a, c, e) def M_interleave(self, a, c, e): group = T_Group(self.pattern, T_Choice(T_Empty(), T_OneOrMore(self.pattern))) return group.M_interleave(a, c, e) class T_Group(Pattern): def __init__(self, pattern_1=None, pattern_2=None): self.pattern_1 = pattern_1 self.pattern_2 = pattern_2 def display(self): print "(GROUP", self.pattern_1.display() self.pattern_2.display() print ")", def M(self, a, c, e): match_1 = self.pattern_1.M_consume(a,c,e) if match_1.isError(): return Error("first pattern of group failed", match_1) match = Match() for remainder in match_1.remainders: a_2 = remainder.a c_2 = remainder.c match = self.pattern_2.M(a_2, c_2, e) if not match.isError(): return Match() return Error("second pattern of group failed", match) def M_consume(self, a, c, e): match_1 = self.pattern_1.M_consume(a,c,e) if match_1.isError(): return Error("first pattern of group failed", match_1) match = Match() for remainder in match_1.remainders: a_2 = remainder.a c_2 = remainder.c match_2 = self.pattern_2.M_consume(a_2, c_2, e) if not match_2.isError(): match.add(match_2) return match def M_interleave(self, a, c, e): # TODO I'm not 100% what it means to interleave a group (eg does order matter?) match_1 = self.pattern_1.M_interleave(a,c,e) if match_1.isError(): return Error("first pattern of group failed", match_1) match = Match() for remainder in match_1.remainders: a_2 = remainder.a c_2 = remainder.c match_2 = self.pattern_2.M_interleave(a_2, c_2, e) if not match_2.isError(): match.add(match_2) return match class T_Grammar(Pattern): def __init__(self): self.start = None self.definitions = {} def display(self): print "(GRAMMAR", self.start.display() for definition in self.definitions.keys(): print "(%s=" % definition, self.definitions[definition].display() print ")", print ")", def add_definition(self, name, definition): self.definitions[name] = definition def M(self, a, c, e): return self.start.M(a, c, Environment(self.definitions, e)) def M_consume(self, a, c, e): return self.start.M_consume(a, c, Environment(self.definitions, e)) def M_interleave(self, a, c, e): return self.start.M_interleave(a, c, Environment(self.defintions, e)) class T_Ref(Pattern): def __init__(self, name, parent): self.name = name self.parent = parent def display(self): print "(REF =%s %s)" % (self.name, self.parent) def M(self, a, c, e): if self.parent == 0: if not e.e.has_key(self.name): return Error("ref to unknown pattern '%s'" % self.name) else: pattern = e.e[self.name] return pattern.M(a, c, e) else: if not e.parent.e.has_key(self.name): return Error("ref to unknown pattern '%s'" % self.name) else: pattern = e.parent.e[self.name] return pattern.M(a, c, e.parent) def M_consume(self, a, c, e): if self.parent == 0: if not e.e.has_key(self.name): return Error("ref to unknown pattern '%s'" % self.name) else: pattern = e.e[self.name] return pattern.M_consume(a, c, e) else: if not e.parent.e.has_key(self.name): return Error("ref to unknown pattern '%s'" % self.name) else: pattern = e.parent.e[self.name] return pattern.M_consume(a, c, e.parent) def M_interleave(self, a, c, e): if self.parent == 0: if not e.e.has_key(self.name): return Error("ref to unknown pattern '%s'" % self.name) else: pattern = e.e[self.name] return pattern.M_interleave(a, c, e) else: if not e.parent.e.has_key(self.name): return Error("ref to unknown pattern '%s'" % self.name) else: pattern = e.parent.e[self.name] return pattern.M_interleave(a, c, e.parent) class NameClass: pass class ExpandedName(NameClass): def __init__(self, namespaceURI=None, NCName=None): self.namespaceURI = namespaceURI self.NCName = NCName def display(self): print "(EXPANDED-NAME '%s' '%s')" % (self.namespaceURI, self.NCName), def C(self, n): if self.namespaceURI==n.namespaceURI and self.NCName==n.localName: return Match() else: return Error("expanded name doesn't match: %s^%s != %s^%s" % (self.namespaceURI, self.NCName, n.namespaceURI, n.localName)) class AnyName(NameClass): def display(self): print "(ANY-NAME)", def C(self, n): return Match() class NSName(NameClass): def __init__(self, namespaceURI): self.namespaceURI = namespaceURI def display(self): print "(NS-NAME '%s')" % self.namespaceURI def C(self, n): if self.namespaceURI==n.namespaceURI: return Match() else: return Error("namespace doesn't match: %s != %s" % (self.namespaceURI, n.namespaceURI)) class NameClassChoice(NameClass): def __init__(self, nameclass_1, nameclass_2): self.nameclass_1 = nameclass_1 self.nameclass_2 = nameclass_2 def display(self): print "(CHOICE", self.nameclass_1.display() self.nameclass_2.display() print ")", def C(self, n): match_1 = self.nameclass_1.C(n) if not match_1.isError(): return Match() match_2 = self.nameclass_2.C(n) if not match_2.isError(): return Match() return Error("both items of a choice failed", match_1, match_2) class Difference(NameClass): def __init__(self, nameclass_1, nameclass_2): self.nameclass_1 = nameclass_1 self.nameclass_2 = nameclass_2 def display(self): print "(DIFFERENCE", self.nameclass_1.display() self.nameclass_2.display() print ")", def C(self, n): match = self.nameclass_1.C(n) if match.isError(): return Error("first name-class of a difference failed", match) match = self.nameclass_2.C(n) if not match.isError(): return Error("second name-class of a difference failed", match) return Match() ######################################################################## ### INSTANCE REPRESENTATION # # Basically the instance data model from section 2 # class I_Node: pass class I_Root(I_Node): def __init__(self): self.children = [] def add_child(self, node): self.children.append(node) def is_whitespace(self): return 0 def is_element(self): return 0 def display(self): print "(ROOT", for child in self.children: child.display() print ")" class I_ExpandedName: def __init__(self, namespaceURI, localName): self.namespaceURI = namespaceURI self.localName = localName class I_Element(I_Node): def __init__(self): self.expanded_name = None self.attributes = [] self.children = [] def add_child(self, node): self.children.append(node) def add_attribute(self, node): self.attributes.append(node) def is_whitespace(self): return 0 def is_element(self): return 1 def display(self): print "(%s" % self.expanded_name.localName, for attr in self.attributes: attr.display() for child in self.children: child.display() print ")", def __repr__(self): return "<%s>" % self.expanded_name.localName class I_Attribute(I_Node): def __init__(self, expanded_name=None, value=None): self.expanded_name = expanded_name self.value = value def is_whitespace(self): return 0 def is_element(self): return 1 def display(self): print "(@%s" % self.expanded_name.localName, self.value[0].display() print ")", def __repr__(self): return "<%s=%s>" % (self.expanded_name.localName, self.value) class I_CharData(I_Node): def __init__(self, data): self.data = data def is_whitespace(self): for char in self.data: if char not in [chr(9),chr(10),chr(13),chr(32)]: return 0 return 1 def is_element(self): return 0 def display(self): print "'%s'" % self.data, def __repr__(self): return "'%s'" % self.data ######################################################################## ### INSTANCE PARSING # TODO wellformedness errors don't seem to get reported def parse_Instance(location, baseURI=None): if baseURI==None: baseURI = location import xml.parsers.expat parser = xml.parsers.expat.ParserCreate(namespace_separator="^") parser.SetBase(baseURI) parser.returns_unicode = 1 i = I_RootHandler(parser) from urllib2 import urlopen f = urlopen(location) try: parser.ParseFile(f) except xml.parsers.expat.error: import sys sys.stderr.write("Error parsing file at line '%s' and column '%s'\n" % (parser.ErrorLineNumber, parser.ErrorColumnNumber) ) sys.stderr.flush() f.close() return i.product class I_RootHandler(HandlerBase): def __init__(self, parser, parent = None, atts = None): HandlerBase.__init__(self, parser, parent, atts) self.product = I_Root() def child(self, name, atts): I_ElementHandler(self.parser, self, name, atts) def char(self, data): self.product.add_child(I_CharData(data)) def end(self, name): HandlerBase.end(self, name) def add_child(self, node): self.product.add_child(node) class I_ElementHandler(HandlerBase): def __init__(self, parser, parent, name, atts): HandlerBase.__init__(self, parser, parent, atts) self.product = I_Element() import string n = string.split(name,"^") if len(n)==1: namespaceURI="" localName=n[0] else: namespaceURI=n[0] localName=n[1] self.product.expanded_name = I_ExpandedName(namespaceURI, localName) for attr in atts.keys(): n = string.split(attr,"^") if len(n)==1: namespaceURI="" localName=n[0] else: namespaceURI=n[0] localName=n[1] self.product.add_attribute(I_Attribute(I_ExpandedName(namespaceURI, localName), [I_CharData(atts[attr])])) def child(self, name, atts): I_ElementHandler(self.parser, self, name, atts) def char(self, data): self.product.add_child(I_CharData(data)) def end(self, name): self.parent.add_child(self.product) HandlerBase.end(self, name) def add_child(self, node): self.product.add_child(node) ######################################################################## ### MAIN LINE if __name__ == "__main__": import sys if len(sys.argv)==3: match = validate(parse_TREX(sys.argv[1]),parse_Instance(sys.argv[2])) if match.isError(): match.display() else: print "match" else: print "usage: python pytrex.py " PyXML-0.8.2/xml/unicode/0040755000076400001440000000000007614726123014151 5ustar martinusersPyXML-0.8.2/xml/unicode/__init__.py0100644000076400001440000000023607212412176016252 0ustar martinusers"""This package exists for compatibility with PyXML 0.5.x. Its functionality is superceded by the Python 2.0 Unicode type; it should be used only by 4DOM.""" PyXML-0.8.2/xml/unicode/iso8859.py0100644000076400001440000000545707230663632015662 0ustar martinusers"""This module adds a backwards-compatibility to the older wstring module. It is intended for use by 4Suite only; do not use it in your own code.""" import string import utf8_iso _trans = string.maketrans("_:","- ") def _normalize(codeset): codeset = string.lower(codeset) codeset = string.translate(codeset, _trans) return codeset class _Wstringmod: "Emulator for old wstring module" def __init__(self): self.aliases = {'iso-ir-100' : 'iso-8859-1', 'cp819' : 'iso-8859-1', 'l1' : 'iso-8859-1', 'latin1' : 'iso-8859-1', 'ibm819' : 'iso-8859-1', } self.encodings = {'utf-8' : 0} for i in range(1, len(utf8_iso.code_to_uni)): if utf8_iso.code_to_uni[i]: self.encodings['iso-8859-%d' % i] = i def install_alias(self, newname, oldname): self.aliases[_normalize(newname)] = _normalize(oldname) def from_utf8(self, utf8): return UTF8String(utf8) def decode(self, encoding, string): return UTF8String(string, encoding) def chr(self, ch): return UTF8String(utf8_iso.utf8chr(ch)) wstring = _Wstringmod() class UTF8String: "Emulator for the wstring type" def __init__(self, string, encoding='utf-8'): self.data = string enc = _normalize(encoding) codeset = wstring.encodings.get(enc) if codeset is None: if wstring.aliases.has_key(enc): codeset = wstring.encoding.get(wstring.aliases[enc]) if codeset is None: raise utf8_iso.ConvertError('Unknown encoding: %s' % encoding) self.codeset = codeset def utf8(self): if self.codeset == 0: return self.data output = map(lambda char, codeset=self.codeset: utf8_iso.code_to_utf8(codeset, char), self.data) return string.join(output, '') def encode(self, encoding): enc = _normalize(encoding) codeset = wstring.encodings.get(enc) if codeset is None: if wstring.aliases.has_key(enc): codeset = wstring.encoding.get(wstring.aliases[enc]) if codeset is None: raise utf8_iso.ConvertError('Unknown encoding: %s' % encoding) if codeset == 0: return self.data input = self.data output = [] while input: for i in range(len(input)): if ord(input[i])>128: break if i == 0: char, input = utf8_iso.utf8_to_code(codeset, input) output.append(char) else: output.extend(list(input[:i])) input = input[i:] return string.join(output, '') PyXML-0.8.2/xml/unicode/utf8_iso.py0100644000076400001440000002665207230663632016272 0ustar martinusers"""This module provides UTF-8 conversion into ISO-8859-x. It is partially generated by the code executed when generated is set to 1. The module serves for compatibility with Python 1.5.2 only; Python 2 users should use the Unicode facilities instead. In fact, the tables generated have to be generated with Python 2.""" # Generator part; activate by setting generate to 1 in this source code. generate = 0 if generate: import codecs isocodes = [] for i in range(1,20): try: name = "iso-8859-%d" % i codecs.lookup(name) isocodes.append(name) except LookupError: isocodes.append(None) print "code_to_uni=[None," for code in isocodes: if code is None: print "None," continue print '[', for char in range(128,256): print "%d," % ord(unicode(chr(char),code)), print "]," print "]" class ConvertError(ValueError): pass # Mapping table for unicode code points to iso-8859-x code points. # Keys are encoding number (x), then the code point uni_to_code=[None]*20 def utf8chr(c): if c < 0x800: return chr(0xc0 | (c>>6)) + chr(0x80 | (c & 0x3f)) return chr(0xe0 | (c>>12)) + chr(0x80 | ((c>>6) & 0x3f)) + chr(0x80 | (c & 0x3f)) def code_to_utf8(encoding, c): """code_to_utf8(encoding, char) -> string Convert c from encoding to utf8; return UTF-8 string.""" c = ord(c) if c<128: return chr(c) if code_to_uni[encoding] is None: raise ConvertError("unknown encoding ISO-8859-%d" % encoding) return utf8chr(code_to_uni[encoding][c-128]) def utf8_to_code(encoding, str): """utf8_to_code(encoding, str) -> char,rest Convert an UTF-8 string to encoding. Return the first char, and the remaining UTF-8 bytes.""" if str == "": return str first = ord(str[0]) if first<128: # Identity-map ASCII return str[0],str[1:] if uni_to_code[encoding] is None: # see whether we have reverse direction if code_to_uni[encoding] is None: raise ConvertError("unknown encoding ISO-8859-%d" % encoding) uni_to_code[encoding] = {} for code in range(128): uni = code_to_uni[encoding][code] uni_to_code[encoding][uni] = code+128 if first<0xc0: # 10xxxxxx raise ConvertError("ill-formed UTF-8") if first<0xe0: # 110xxxxx 10xxxxxx val = ((first & 0x1f)<<6) | (ord(str[1]) & 0x3f) rest = str[2:] elif first < 0xf0: # 1110xxxx 10xxxxxx 10xxxxxx val = ((first & 0xf)<<12) | ((ord(str[1]) & 0x3f)<<6) | (ord(str[2]) & 0x3f) rest = str[3:] else: raise ConvertError("UTF-8 character outside BMP") try: return chr(uni_to_code[encoding][val]), rest except KeyError: raise ConvertError("Unicode character %x not supported in ISO-8859-%d"\ % (val, encoding)) ############## GENERATED PART ######################### code_to_uni=[None, [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 728, 321, 164, 317, 346, 167, 168, 352, 350, 356, 377, 173, 381, 379, 176, 261, 731, 322, 180, 318, 347, 711, 184, 353, 351, 357, 378, 733, 382, 380, 340, 193, 194, 258, 196, 313, 262, 199, 268, 201, 280, 203, 282, 205, 206, 270, 272, 323, 327, 211, 212, 336, 214, 215, 344, 366, 218, 368, 220, 221, 354, 223, 341, 225, 226, 259, 228, 314, 263, 231, 269, 233, 281, 235, 283, 237, 238, 271, 273, 324, 328, 243, 244, 337, 246, 247, 345, 367, 250, 369, 252, 253, 355, 729, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 294, 728, 163, 164, 165, 292, 167, 168, 304, 350, 286, 308, 173, 174, 379, 176, 295, 178, 179, 180, 181, 293, 183, 184, 305, 351, 287, 309, 189, 190, 380, 192, 193, 194, 195, 196, 266, 264, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 288, 214, 215, 284, 217, 218, 219, 220, 364, 348, 223, 224, 225, 226, 227, 228, 267, 265, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 289, 246, 247, 285, 249, 250, 251, 252, 365, 349, 729, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 312, 342, 164, 296, 315, 167, 168, 352, 274, 290, 358, 173, 381, 175, 176, 261, 731, 343, 180, 297, 316, 711, 184, 353, 275, 291, 359, 330, 382, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 298, 272, 325, 332, 310, 212, 213, 214, 215, 216, 370, 218, 219, 220, 360, 362, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 299, 273, 326, 333, 311, 244, 245, 246, 247, 248, 371, 250, 251, 252, 361, 363, 729, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 173, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 8470, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 167, 1118, 1119, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 1548, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 1563, 188, 189, 190, 1567, 192, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 219, 220, 221, 222, 223, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8216, 8217, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 8213, 176, 177, 178, 179, 900, 901, 902, 183, 904, 905, 906, 187, 908, 189, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 210, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 255, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 215, 171, 172, 173, 174, 8254, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 247, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 8215, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 251, 252, 253, 254, 255, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 286, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 304, 350, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 287, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 305, 351, 255, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 274, 290, 298, 296, 310, 167, 315, 272, 352, 358, 381, 173, 362, 330, 176, 261, 275, 291, 299, 297, 311, 183, 316, 273, 353, 359, 382, 8213, 363, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 207, 208, 325, 332, 211, 212, 213, 214, 360, 216, 370, 218, 219, 220, 221, 222, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 239, 240, 326, 333, 243, 244, 245, 246, 361, 248, 371, 250, 251, 252, 253, 254, 312, ], None, None, [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8221, 162, 163, 164, 8222, 166, 167, 216, 169, 342, 171, 172, 173, 174, 198, 176, 177, 178, 179, 8220, 181, 182, 183, 248, 185, 343, 187, 188, 189, 190, 230, 260, 302, 256, 262, 196, 197, 280, 274, 268, 201, 377, 278, 290, 310, 298, 315, 352, 323, 325, 211, 332, 213, 214, 215, 370, 321, 346, 362, 220, 379, 381, 223, 261, 303, 257, 263, 228, 229, 281, 275, 269, 233, 378, 279, 291, 311, 299, 316, 353, 324, 326, 243, 333, 245, 246, 247, 371, 322, 347, 363, 252, 380, 382, 8217, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 7682, 7683, 163, 266, 267, 7690, 167, 7808, 169, 7810, 7691, 7922, 173, 174, 376, 7710, 7711, 288, 289, 7744, 7745, 182, 7766, 7809, 7767, 7811, 7776, 7923, 7812, 7813, 7777, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 372, 209, 210, 211, 212, 213, 214, 7786, 216, 217, 218, 219, 220, 221, 374, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 373, 241, 242, 243, 244, 245, 246, 7787, 248, 249, 250, 251, 252, 253, 375, 255, ], [ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 8364, 165, 352, 167, 353, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 381, 181, 182, 183, 382, 185, 186, 187, 338, 339, 376, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, ], None, None, None, None, ] PyXML-0.8.2/xml/utils/0040755000076400001440000000000007614726123013663 5ustar martinusersPyXML-0.8.2/xml/utils/__init__.py0100644000076400001440000000002607244233552015765 0ustar martinusers__all__ = ['iso8601'] PyXML-0.8.2/xml/utils/characters.py0100644000076400001440000006315507420372041016352 0ustar martinusers# This file was generated using xmlchargen.py S = '[\n\t \r]+' BaseChar = unicode('\x00[\x00A\x00-\x00Z\x00a\x00-\x00z\x00\xc0\x00-\x00\xd6\x00\xd8\x00-\x00\xf6\x00\xf8\x00-\x00\xff\x01\x00\x00-\x011\x014\x00-\x01>\x01A\x00-\x01H\x01J\x00-\x01~\x01\x80\x00-\x01\xc3\x01\xcd\x00-\x01\xf0\x01\xf4\x00-\x01\xf5\x01\xfa\x00-\x02\x17\x02P\x00-\x02\xa8\x02\xbb\x00-\x02\xc1\x03\x86\x03\x88\x00-\x03\x8a\x03\x8c\x03\x8e\x00-\x03\xa1\x03\xa3\x00-\x03\xce\x03\xd0\x00-\x03\xd6\x03\xda\x03\xdc\x03\xde\x03\xe0\x03\xe2\x00-\x03\xf3\x04\x01\x00-\x04\x0c\x04\x0e\x00-\x04O\x04Q\x00-\x04\\\x04^\x00-\x04\x81\x04\x90\x00-\x04\xc4\x04\xc7\x00-\x04\xc8\x04\xcb\x00-\x04\xcc\x04\xd0\x00-\x04\xeb\x04\xee\x00-\x04\xf5\x04\xf8\x00-\x04\xf9\x051\x00-\x05V\x05Y\x05a\x00-\x05\x86\x05\xd0\x00-\x05\xea\x05\xf0\x00-\x05\xf2\x06!\x00-\x06:\x06A\x00-\x06J\x06q\x00-\x06\xb7\x06\xba\x00-\x06\xbe\x06\xc0\x00-\x06\xce\x06\xd0\x00-\x06\xd3\x06\xd5\x06\xe5\x00-\x06\xe6\t\x05\x00-\t9\t=\tX\x00-\ta\t\x85\x00-\t\x8c\t\x8f\x00-\t\x90\t\x93\x00-\t\xa8\t\xaa\x00-\t\xb0\t\xb2\t\xb6\x00-\t\xb9\t\xdc\x00-\t\xdd\t\xdf\x00-\t\xe1\t\xf0\x00-\t\xf1\n\x05\x00-\n\n\n\x0f\x00-\n\x10\n\x13\x00-\n(\n*\x00-\n0\n2\x00-\n3\n5\x00-\n6\n8\x00-\n9\nY\x00-\n\\\n^\nr\x00-\nt\n\x85\x00-\n\x8b\n\x8d\n\x8f\x00-\n\x91\n\x93\x00-\n\xa8\n\xaa\x00-\n\xb0\n\xb2\x00-\n\xb3\n\xb5\x00-\n\xb9\n\xbd\n\xe0\x0b\x05\x00-\x0b\x0c\x0b\x0f\x00-\x0b\x10\x0b\x13\x00-\x0b(\x0b*\x00-\x0b0\x0b2\x00-\x0b3\x0b6\x00-\x0b9\x0b=\x0b\\\x00-\x0b]\x0b_\x00-\x0ba\x0b\x85\x00-\x0b\x8a\x0b\x8e\x00-\x0b\x90\x0b\x92\x00-\x0b\x95\x0b\x99\x00-\x0b\x9a\x0b\x9c\x0b\x9e\x00-\x0b\x9f\x0b\xa3\x00-\x0b\xa4\x0b\xa8\x00-\x0b\xaa\x0b\xae\x00-\x0b\xb5\x0b\xb7\x00-\x0b\xb9\x0c\x05\x00-\x0c\x0c\x0c\x0e\x00-\x0c\x10\x0c\x12\x00-\x0c(\x0c*\x00-\x0c3\x0c5\x00-\x0c9\x0c`\x00-\x0ca\x0c\x85\x00-\x0c\x8c\x0c\x8e\x00-\x0c\x90\x0c\x92\x00-\x0c\xa8\x0c\xaa\x00-\x0c\xb3\x0c\xb5\x00-\x0c\xb9\x0c\xde\x0c\xe0\x00-\x0c\xe1\r\x05\x00-\r\x0c\r\x0e\x00-\r\x10\r\x12\x00-\r(\r*\x00-\r9\r`\x00-\ra\x0e\x01\x00-\x0e.\x0e0\x0e2\x00-\x0e3\x0e@\x00-\x0eE\x0e\x81\x00-\x0e\x82\x0e\x84\x0e\x87\x00-\x0e\x88\x0e\x8a\x0e\x8d\x0e\x94\x00-\x0e\x97\x0e\x99\x00-\x0e\x9f\x0e\xa1\x00-\x0e\xa3\x0e\xa5\x0e\xa7\x0e\xaa\x00-\x0e\xab\x0e\xad\x00-\x0e\xae\x0e\xb0\x0e\xb2\x00-\x0e\xb3\x0e\xbd\x0e\xc0\x00-\x0e\xc4\x0f@\x00-\x0fG\x0fI\x00-\x0fi\x10\xa0\x00-\x10\xc5\x10\xd0\x00-\x10\xf6\x11\x00\x11\x02\x00-\x11\x03\x11\x05\x00-\x11\x07\x11\t\x11\x0b\x00-\x11\x0c\x11\x0e\x00-\x11\x12\x11<\x11>\x11@\x11L\x11N\x11P\x11T\x00-\x11U\x11Y\x11_\x00-\x11a\x11c\x11e\x11g\x11i\x11m\x00-\x11n\x11r\x00-\x11s\x11u\x11\x9e\x11\xa8\x11\xab\x11\xae\x00-\x11\xaf\x11\xb7\x00-\x11\xb8\x11\xba\x11\xbc\x00-\x11\xc2\x11\xeb\x11\xf0\x11\xf9\x1e\x00\x00-\x1e\x9b\x1e\xa0\x00-\x1e\xf9\x1f\x00\x00-\x1f\x15\x1f\x18\x00-\x1f\x1d\x1f \x00-\x1fE\x1fH\x00-\x1fM\x1fP\x00-\x1fW\x1fY\x1f[\x1f]\x1f_\x00-\x1f}\x1f\x80\x00-\x1f\xb4\x1f\xb6\x00-\x1f\xbc\x1f\xbe\x1f\xc2\x00-\x1f\xc4\x1f\xc6\x00-\x1f\xcc\x1f\xd0\x00-\x1f\xd3\x1f\xd6\x00-\x1f\xdb\x1f\xe0\x00-\x1f\xec\x1f\xf2\x00-\x1f\xf4\x1f\xf6\x00-\x1f\xfc!&!*\x00-!+!.!\x80\x00-!\x820A\x00-0\x940\xa1\x00-0\xfa1\x05\x00-1,\xac\x00\x00-\xd7\xa3\x00]','utf-16-be') Ideographic = unicode('\x00[N\x00\x00-\x9f\xa50\x070!\x00-0)\x00]','utf-16-be') CombiningChar = unicode('\x00[\x03\x00\x00-\x03E\x03`\x00-\x03a\x04\x83\x00-\x04\x86\x05\x91\x00-\x05\xa1\x05\xa3\x00-\x05\xb9\x05\xbb\x00-\x05\xbd\x05\xbf\x05\xc1\x00-\x05\xc2\x05\xc4\x06K\x00-\x06R\x06p\x06\xd6\x00-\x06\xdc\x06\xdd\x00-\x06\xdf\x06\xe0\x00-\x06\xe4\x06\xe7\x00-\x06\xe8\x06\xea\x00-\x06\xed\t\x01\x00-\t\x03\t<\t>\x00-\tL\tM\tQ\x00-\tT\tb\x00-\tc\t\x81\x00-\t\x83\t\xbc\t\xbe\t\xbf\t\xc0\x00-\t\xc4\t\xc7\x00-\t\xc8\t\xcb\x00-\t\xcd\t\xd7\t\xe2\x00-\t\xe3\n\x02\n<\n>\n?\n@\x00-\nB\nG\x00-\nH\nK\x00-\nM\np\x00-\nq\n\x81\x00-\n\x83\n\xbc\n\xbe\x00-\n\xc5\n\xc7\x00-\n\xc9\n\xcb\x00-\n\xcd\x0b\x01\x00-\x0b\x03\x0b<\x0b>\x00-\x0bC\x0bG\x00-\x0bH\x0bK\x00-\x0bM\x0bV\x00-\x0bW\x0b\x82\x00-\x0b\x83\x0b\xbe\x00-\x0b\xc2\x0b\xc6\x00-\x0b\xc8\x0b\xca\x00-\x0b\xcd\x0b\xd7\x0c\x01\x00-\x0c\x03\x0c>\x00-\x0cD\x0cF\x00-\x0cH\x0cJ\x00-\x0cM\x0cU\x00-\x0cV\x0c\x82\x00-\x0c\x83\x0c\xbe\x00-\x0c\xc4\x0c\xc6\x00-\x0c\xc8\x0c\xca\x00-\x0c\xcd\x0c\xd5\x00-\x0c\xd6\r\x02\x00-\r\x03\r>\x00-\rC\rF\x00-\rH\rJ\x00-\rM\rW\x0e1\x0e4\x00-\x0e:\x0eG\x00-\x0eN\x0e\xb1\x0e\xb4\x00-\x0e\xb9\x0e\xbb\x00-\x0e\xbc\x0e\xc8\x00-\x0e\xcd\x0f\x18\x00-\x0f\x19\x0f5\x0f7\x0f9\x0f>\x0f?\x0fq\x00-\x0f\x84\x0f\x86\x00-\x0f\x8b\x0f\x90\x00-\x0f\x95\x0f\x97\x0f\x99\x00-\x0f\xad\x0f\xb1\x00-\x0f\xb7\x0f\xb9 \xd0\x00- \xdc \xe10*\x00-0/0\x990\x9a\x00]','utf-16-be') Digit = unicode('\x00[\x000\x00-\x009\x06`\x00-\x06i\x06\xf0\x00-\x06\xf9\tf\x00-\to\t\xe6\x00-\t\xef\nf\x00-\no\n\xe6\x00-\n\xef\x0bf\x00-\x0bo\x0b\xe7\x00-\x0b\xef\x0cf\x00-\x0co\x0c\xe6\x00-\x0c\xef\rf\x00-\ro\x0eP\x00-\x0eY\x0e\xd0\x00-\x0e\xd9\x0f \x00-\x0f)\x00]','utf-16-be') Extender = unicode('\x00[\x00\xb7\x02\xd0\x02\xd1\x03\x87\x06@\x0eF\x0e\xc60\x0501\x00-050\x9d\x00-0\x9e0\xfc\x00-0\xfe\x00]','utf-16-be') Letter = unicode('\x00[\x00A\x00-\x00Z\x00a\x00-\x00z\x00\xc0\x00-\x00\xd6\x00\xd8\x00-\x00\xf6\x00\xf8\x00-\x011\x014\x00-\x01>\x01A\x00-\x01H\x01J\x00-\x01~\x01\x80\x00-\x01\xc3\x01\xcd\x00-\x01\xf0\x01\xf4\x00-\x01\xf5\x01\xfa\x00-\x02\x17\x02P\x00-\x02\xa8\x02\xbb\x00-\x02\xc1\x03\x86\x03\x88\x00-\x03\x8a\x03\x8c\x03\x8e\x00-\x03\xa1\x03\xa3\x00-\x03\xce\x03\xd0\x00-\x03\xd6\x03\xda\x03\xdc\x03\xde\x03\xe0\x03\xe2\x00-\x03\xf3\x04\x01\x00-\x04\x0c\x04\x0e\x00-\x04O\x04Q\x00-\x04\\\x04^\x00-\x04\x81\x04\x90\x00-\x04\xc4\x04\xc7\x00-\x04\xc8\x04\xcb\x00-\x04\xcc\x04\xd0\x00-\x04\xeb\x04\xee\x00-\x04\xf5\x04\xf8\x00-\x04\xf9\x051\x00-\x05V\x05Y\x05a\x00-\x05\x86\x05\xd0\x00-\x05\xea\x05\xf0\x00-\x05\xf2\x06!\x00-\x06:\x06A\x00-\x06J\x06q\x00-\x06\xb7\x06\xba\x00-\x06\xbe\x06\xc0\x00-\x06\xce\x06\xd0\x00-\x06\xd3\x06\xd5\x06\xe5\x00-\x06\xe6\t\x05\x00-\t9\t=\tX\x00-\ta\t\x85\x00-\t\x8c\t\x8f\x00-\t\x90\t\x93\x00-\t\xa8\t\xaa\x00-\t\xb0\t\xb2\t\xb6\x00-\t\xb9\t\xdc\x00-\t\xdd\t\xdf\x00-\t\xe1\t\xf0\x00-\t\xf1\n\x05\x00-\n\n\n\x0f\x00-\n\x10\n\x13\x00-\n(\n*\x00-\n0\n2\x00-\n3\n5\x00-\n6\n8\x00-\n9\nY\x00-\n\\\n^\nr\x00-\nt\n\x85\x00-\n\x8b\n\x8d\n\x8f\x00-\n\x91\n\x93\x00-\n\xa8\n\xaa\x00-\n\xb0\n\xb2\x00-\n\xb3\n\xb5\x00-\n\xb9\n\xbd\n\xe0\x0b\x05\x00-\x0b\x0c\x0b\x0f\x00-\x0b\x10\x0b\x13\x00-\x0b(\x0b*\x00-\x0b0\x0b2\x00-\x0b3\x0b6\x00-\x0b9\x0b=\x0b\\\x00-\x0b]\x0b_\x00-\x0ba\x0b\x85\x00-\x0b\x8a\x0b\x8e\x00-\x0b\x90\x0b\x92\x00-\x0b\x95\x0b\x99\x00-\x0b\x9a\x0b\x9c\x0b\x9e\x00-\x0b\x9f\x0b\xa3\x00-\x0b\xa4\x0b\xa8\x00-\x0b\xaa\x0b\xae\x00-\x0b\xb5\x0b\xb7\x00-\x0b\xb9\x0c\x05\x00-\x0c\x0c\x0c\x0e\x00-\x0c\x10\x0c\x12\x00-\x0c(\x0c*\x00-\x0c3\x0c5\x00-\x0c9\x0c`\x00-\x0ca\x0c\x85\x00-\x0c\x8c\x0c\x8e\x00-\x0c\x90\x0c\x92\x00-\x0c\xa8\x0c\xaa\x00-\x0c\xb3\x0c\xb5\x00-\x0c\xb9\x0c\xde\x0c\xe0\x00-\x0c\xe1\r\x05\x00-\r\x0c\r\x0e\x00-\r\x10\r\x12\x00-\r(\r*\x00-\r9\r`\x00-\ra\x0e\x01\x00-\x0e.\x0e0\x0e2\x00-\x0e3\x0e@\x00-\x0eE\x0e\x81\x00-\x0e\x82\x0e\x84\x0e\x87\x00-\x0e\x88\x0e\x8a\x0e\x8d\x0e\x94\x00-\x0e\x97\x0e\x99\x00-\x0e\x9f\x0e\xa1\x00-\x0e\xa3\x0e\xa5\x0e\xa7\x0e\xaa\x00-\x0e\xab\x0e\xad\x00-\x0e\xae\x0e\xb0\x0e\xb2\x00-\x0e\xb3\x0e\xbd\x0e\xc0\x00-\x0e\xc4\x0f@\x00-\x0fG\x0fI\x00-\x0fi\x10\xa0\x00-\x10\xc5\x10\xd0\x00-\x10\xf6\x11\x00\x11\x02\x00-\x11\x03\x11\x05\x00-\x11\x07\x11\t\x11\x0b\x00-\x11\x0c\x11\x0e\x00-\x11\x12\x11<\x11>\x11@\x11L\x11N\x11P\x11T\x00-\x11U\x11Y\x11_\x00-\x11a\x11c\x11e\x11g\x11i\x11m\x00-\x11n\x11r\x00-\x11s\x11u\x11\x9e\x11\xa8\x11\xab\x11\xae\x00-\x11\xaf\x11\xb7\x00-\x11\xb8\x11\xba\x11\xbc\x00-\x11\xc2\x11\xeb\x11\xf0\x11\xf9\x1e\x00\x00-\x1e\x9b\x1e\xa0\x00-\x1e\xf9\x1f\x00\x00-\x1f\x15\x1f\x18\x00-\x1f\x1d\x1f \x00-\x1fE\x1fH\x00-\x1fM\x1fP\x00-\x1fW\x1fY\x1f[\x1f]\x1f_\x00-\x1f}\x1f\x80\x00-\x1f\xb4\x1f\xb6\x00-\x1f\xbc\x1f\xbe\x1f\xc2\x00-\x1f\xc4\x1f\xc6\x00-\x1f\xcc\x1f\xd0\x00-\x1f\xd3\x1f\xd6\x00-\x1f\xdb\x1f\xe0\x00-\x1f\xec\x1f\xf2\x00-\x1f\xf4\x1f\xf6\x00-\x1f\xfc!&!*\x00-!+!.!\x80\x00-!\x820\x070!\x00-0)0A\x00-0\x940\xa1\x00-0\xfa1\x05\x00-1,N\x00\x00-\x9f\xa5\xac\x00\x00-\xd7\xa3\x00]','utf-16-be') NameChar = unicode('\x00[\x00\\\x00x\x002\x00d\x00-\x00.\x000\x00-\x00:\x00A\x00-\x00Z\x00_\x00a\x00-\x00z\x00\xb7\x00\xc0\x00-\x00\xd6\x00\xd8\x00-\x00\xf6\x00\xf8\x00-\x011\x014\x00-\x01>\x01A\x00-\x01H\x01J\x00-\x01~\x01\x80\x00-\x01\xc3\x01\xcd\x00-\x01\xf0\x01\xf4\x00-\x01\xf5\x01\xfa\x00-\x02\x17\x02P\x00-\x02\xa8\x02\xbb\x00-\x02\xc1\x02\xd0\x00-\x02\xd1\x03\x00\x00-\x03E\x03`\x00-\x03a\x03\x86\x00-\x03\x8a\x03\x8c\x03\x8e\x00-\x03\xa1\x03\xa3\x00-\x03\xce\x03\xd0\x00-\x03\xd6\x03\xda\x03\xdc\x03\xde\x03\xe0\x03\xe2\x00-\x03\xf3\x04\x01\x00-\x04\x0c\x04\x0e\x00-\x04O\x04Q\x00-\x04\\\x04^\x00-\x04\x81\x04\x83\x00-\x04\x86\x04\x90\x00-\x04\xc4\x04\xc7\x00-\x04\xc8\x04\xcb\x00-\x04\xcc\x04\xd0\x00-\x04\xeb\x04\xee\x00-\x04\xf5\x04\xf8\x00-\x04\xf9\x051\x00-\x05V\x05Y\x05a\x00-\x05\x86\x05\x91\x00-\x05\xa1\x05\xa3\x00-\x05\xb9\x05\xbb\x00-\x05\xbd\x05\xbf\x05\xc1\x00-\x05\xc2\x05\xc4\x05\xd0\x00-\x05\xea\x05\xf0\x00-\x05\xf2\x06!\x00-\x06:\x06@\x00-\x06R\x06`\x00-\x06i\x06p\x00-\x06\xb7\x06\xba\x00-\x06\xbe\x06\xc0\x00-\x06\xce\x06\xd0\x00-\x06\xd3\x06\xd5\x00-\x06\xe8\x06\xea\x00-\x06\xed\x06\xf0\x00-\x06\xf9\t\x01\x00-\t\x03\t\x05\x00-\t9\t<\x00-\tM\tQ\x00-\tT\tX\x00-\tc\tf\x00-\to\t\x81\x00-\t\x83\t\x85\x00-\t\x8c\t\x8f\x00-\t\x90\t\x93\x00-\t\xa8\t\xaa\x00-\t\xb0\t\xb2\t\xb6\x00-\t\xb9\t\xbc\t\xbe\x00-\t\xc4\t\xc7\x00-\t\xc8\t\xcb\x00-\t\xcd\t\xd7\t\xdc\x00-\t\xdd\t\xdf\x00-\t\xe3\t\xe6\x00-\t\xf1\n\x02\n\x05\x00-\n\n\n\x0f\x00-\n\x10\n\x13\x00-\n(\n*\x00-\n0\n2\x00-\n3\n5\x00-\n6\n8\x00-\n9\n<\n>\x00-\nB\nG\x00-\nH\nK\x00-\nM\nY\x00-\n\\\n^\nf\x00-\nt\n\x81\x00-\n\x83\n\x85\x00-\n\x8b\n\x8d\n\x8f\x00-\n\x91\n\x93\x00-\n\xa8\n\xaa\x00-\n\xb0\n\xb2\x00-\n\xb3\n\xb5\x00-\n\xb9\n\xbc\x00-\n\xc5\n\xc7\x00-\n\xc9\n\xcb\x00-\n\xcd\n\xe0\n\xe6\x00-\n\xef\x0b\x01\x00-\x0b\x03\x0b\x05\x00-\x0b\x0c\x0b\x0f\x00-\x0b\x10\x0b\x13\x00-\x0b(\x0b*\x00-\x0b0\x0b2\x00-\x0b3\x0b6\x00-\x0b9\x0b<\x00-\x0bC\x0bG\x00-\x0bH\x0bK\x00-\x0bM\x0bV\x00-\x0bW\x0b\\\x00-\x0b]\x0b_\x00-\x0ba\x0bf\x00-\x0bo\x0b\x82\x00-\x0b\x83\x0b\x85\x00-\x0b\x8a\x0b\x8e\x00-\x0b\x90\x0b\x92\x00-\x0b\x95\x0b\x99\x00-\x0b\x9a\x0b\x9c\x0b\x9e\x00-\x0b\x9f\x0b\xa3\x00-\x0b\xa4\x0b\xa8\x00-\x0b\xaa\x0b\xae\x00-\x0b\xb5\x0b\xb7\x00-\x0b\xb9\x0b\xbe\x00-\x0b\xc2\x0b\xc6\x00-\x0b\xc8\x0b\xca\x00-\x0b\xcd\x0b\xd7\x0b\xe7\x00-\x0b\xef\x0c\x01\x00-\x0c\x03\x0c\x05\x00-\x0c\x0c\x0c\x0e\x00-\x0c\x10\x0c\x12\x00-\x0c(\x0c*\x00-\x0c3\x0c5\x00-\x0c9\x0c>\x00-\x0cD\x0cF\x00-\x0cH\x0cJ\x00-\x0cM\x0cU\x00-\x0cV\x0c`\x00-\x0ca\x0cf\x00-\x0co\x0c\x82\x00-\x0c\x83\x0c\x85\x00-\x0c\x8c\x0c\x8e\x00-\x0c\x90\x0c\x92\x00-\x0c\xa8\x0c\xaa\x00-\x0c\xb3\x0c\xb5\x00-\x0c\xb9\x0c\xbe\x00-\x0c\xc4\x0c\xc6\x00-\x0c\xc8\x0c\xca\x00-\x0c\xcd\x0c\xd5\x00-\x0c\xd6\x0c\xde\x0c\xe0\x00-\x0c\xe1\x0c\xe6\x00-\x0c\xef\r\x02\x00-\r\x03\r\x05\x00-\r\x0c\r\x0e\x00-\r\x10\r\x12\x00-\r(\r*\x00-\r9\r>\x00-\rC\rF\x00-\rH\rJ\x00-\rM\rW\r`\x00-\ra\rf\x00-\ro\x0e\x01\x00-\x0e.\x0e0\x00-\x0e:\x0e@\x00-\x0eN\x0eP\x00-\x0eY\x0e\x81\x00-\x0e\x82\x0e\x84\x0e\x87\x00-\x0e\x88\x0e\x8a\x0e\x8d\x0e\x94\x00-\x0e\x97\x0e\x99\x00-\x0e\x9f\x0e\xa1\x00-\x0e\xa3\x0e\xa5\x0e\xa7\x0e\xaa\x00-\x0e\xab\x0e\xad\x00-\x0e\xae\x0e\xb0\x00-\x0e\xb9\x0e\xbb\x00-\x0e\xbd\x0e\xc0\x00-\x0e\xc4\x0e\xc6\x0e\xc8\x00-\x0e\xcd\x0e\xd0\x00-\x0e\xd9\x0f\x18\x00-\x0f\x19\x0f \x00-\x0f)\x0f5\x0f7\x0f9\x0f>\x00-\x0fG\x0fI\x00-\x0fi\x0fq\x00-\x0f\x84\x0f\x86\x00-\x0f\x8b\x0f\x90\x00-\x0f\x95\x0f\x97\x0f\x99\x00-\x0f\xad\x0f\xb1\x00-\x0f\xb7\x0f\xb9\x10\xa0\x00-\x10\xc5\x10\xd0\x00-\x10\xf6\x11\x00\x11\x02\x00-\x11\x03\x11\x05\x00-\x11\x07\x11\t\x11\x0b\x00-\x11\x0c\x11\x0e\x00-\x11\x12\x11<\x11>\x11@\x11L\x11N\x11P\x11T\x00-\x11U\x11Y\x11_\x00-\x11a\x11c\x11e\x11g\x11i\x11m\x00-\x11n\x11r\x00-\x11s\x11u\x11\x9e\x11\xa8\x11\xab\x11\xae\x00-\x11\xaf\x11\xb7\x00-\x11\xb8\x11\xba\x11\xbc\x00-\x11\xc2\x11\xeb\x11\xf0\x11\xf9\x1e\x00\x00-\x1e\x9b\x1e\xa0\x00-\x1e\xf9\x1f\x00\x00-\x1f\x15\x1f\x18\x00-\x1f\x1d\x1f \x00-\x1fE\x1fH\x00-\x1fM\x1fP\x00-\x1fW\x1fY\x1f[\x1f]\x1f_\x00-\x1f}\x1f\x80\x00-\x1f\xb4\x1f\xb6\x00-\x1f\xbc\x1f\xbe\x1f\xc2\x00-\x1f\xc4\x1f\xc6\x00-\x1f\xcc\x1f\xd0\x00-\x1f\xd3\x1f\xd6\x00-\x1f\xdb\x1f\xe0\x00-\x1f\xec\x1f\xf2\x00-\x1f\xf4\x1f\xf6\x00-\x1f\xfc \xd0\x00- \xdc \xe1!&!*\x00-!+!.!\x80\x00-!\x820\x050\x070!\x00-0/01\x00-050A\x00-0\x940\x99\x00-0\x9a0\x9d\x00-0\x9e0\xa1\x00-0\xfa0\xfc\x00-0\xfe1\x05\x00-1,N\x00\x00-\x9f\xa5\xac\x00\x00-\xd7\xa3\x00]','utf-16-be') Name = unicode('\x00[\x00:\x00A\x00-\x00Z\x00_\x00a\x00-\x00z\x00\xc0\x00-\x00\xd6\x00\xd8\x00-\x00\xf6\x00\xf8\x00-\x011\x014\x00-\x01>\x01A\x00-\x01H\x01J\x00-\x01~\x01\x80\x00-\x01\xc3\x01\xcd\x00-\x01\xf0\x01\xf4\x00-\x01\xf5\x01\xfa\x00-\x02\x17\x02P\x00-\x02\xa8\x02\xbb\x00-\x02\xc1\x03\x86\x03\x88\x00-\x03\x8a\x03\x8c\x03\x8e\x00-\x03\xa1\x03\xa3\x00-\x03\xce\x03\xd0\x00-\x03\xd6\x03\xda\x03\xdc\x03\xde\x03\xe0\x03\xe2\x00-\x03\xf3\x04\x01\x00-\x04\x0c\x04\x0e\x00-\x04O\x04Q\x00-\x04\\\x04^\x00-\x04\x81\x04\x90\x00-\x04\xc4\x04\xc7\x00-\x04\xc8\x04\xcb\x00-\x04\xcc\x04\xd0\x00-\x04\xeb\x04\xee\x00-\x04\xf5\x04\xf8\x00-\x04\xf9\x051\x00-\x05V\x05Y\x05a\x00-\x05\x86\x05\xd0\x00-\x05\xea\x05\xf0\x00-\x05\xf2\x06!\x00-\x06:\x06A\x00-\x06J\x06q\x00-\x06\xb7\x06\xba\x00-\x06\xbe\x06\xc0\x00-\x06\xce\x06\xd0\x00-\x06\xd3\x06\xd5\x06\xe5\x00-\x06\xe6\t\x05\x00-\t9\t=\tX\x00-\ta\t\x85\x00-\t\x8c\t\x8f\x00-\t\x90\t\x93\x00-\t\xa8\t\xaa\x00-\t\xb0\t\xb2\t\xb6\x00-\t\xb9\t\xdc\x00-\t\xdd\t\xdf\x00-\t\xe1\t\xf0\x00-\t\xf1\n\x05\x00-\n\n\n\x0f\x00-\n\x10\n\x13\x00-\n(\n*\x00-\n0\n2\x00-\n3\n5\x00-\n6\n8\x00-\n9\nY\x00-\n\\\n^\nr\x00-\nt\n\x85\x00-\n\x8b\n\x8d\n\x8f\x00-\n\x91\n\x93\x00-\n\xa8\n\xaa\x00-\n\xb0\n\xb2\x00-\n\xb3\n\xb5\x00-\n\xb9\n\xbd\n\xe0\x0b\x05\x00-\x0b\x0c\x0b\x0f\x00-\x0b\x10\x0b\x13\x00-\x0b(\x0b*\x00-\x0b0\x0b2\x00-\x0b3\x0b6\x00-\x0b9\x0b=\x0b\\\x00-\x0b]\x0b_\x00-\x0ba\x0b\x85\x00-\x0b\x8a\x0b\x8e\x00-\x0b\x90\x0b\x92\x00-\x0b\x95\x0b\x99\x00-\x0b\x9a\x0b\x9c\x0b\x9e\x00-\x0b\x9f\x0b\xa3\x00-\x0b\xa4\x0b\xa8\x00-\x0b\xaa\x0b\xae\x00-\x0b\xb5\x0b\xb7\x00-\x0b\xb9\x0c\x05\x00-\x0c\x0c\x0c\x0e\x00-\x0c\x10\x0c\x12\x00-\x0c(\x0c*\x00-\x0c3\x0c5\x00-\x0c9\x0c`\x00-\x0ca\x0c\x85\x00-\x0c\x8c\x0c\x8e\x00-\x0c\x90\x0c\x92\x00-\x0c\xa8\x0c\xaa\x00-\x0c\xb3\x0c\xb5\x00-\x0c\xb9\x0c\xde\x0c\xe0\x00-\x0c\xe1\r\x05\x00-\r\x0c\r\x0e\x00-\r\x10\r\x12\x00-\r(\r*\x00-\r9\r`\x00-\ra\x0e\x01\x00-\x0e.\x0e0\x0e2\x00-\x0e3\x0e@\x00-\x0eE\x0e\x81\x00-\x0e\x82\x0e\x84\x0e\x87\x00-\x0e\x88\x0e\x8a\x0e\x8d\x0e\x94\x00-\x0e\x97\x0e\x99\x00-\x0e\x9f\x0e\xa1\x00-\x0e\xa3\x0e\xa5\x0e\xa7\x0e\xaa\x00-\x0e\xab\x0e\xad\x00-\x0e\xae\x0e\xb0\x0e\xb2\x00-\x0e\xb3\x0e\xbd\x0e\xc0\x00-\x0e\xc4\x0f@\x00-\x0fG\x0fI\x00-\x0fi\x10\xa0\x00-\x10\xc5\x10\xd0\x00-\x10\xf6\x11\x00\x11\x02\x00-\x11\x03\x11\x05\x00-\x11\x07\x11\t\x11\x0b\x00-\x11\x0c\x11\x0e\x00-\x11\x12\x11<\x11>\x11@\x11L\x11N\x11P\x11T\x00-\x11U\x11Y\x11_\x00-\x11a\x11c\x11e\x11g\x11i\x11m\x00-\x11n\x11r\x00-\x11s\x11u\x11\x9e\x11\xa8\x11\xab\x11\xae\x00-\x11\xaf\x11\xb7\x00-\x11\xb8\x11\xba\x11\xbc\x00-\x11\xc2\x11\xeb\x11\xf0\x11\xf9\x1e\x00\x00-\x1e\x9b\x1e\xa0\x00-\x1e\xf9\x1f\x00\x00-\x1f\x15\x1f\x18\x00-\x1f\x1d\x1f \x00-\x1fE\x1fH\x00-\x1fM\x1fP\x00-\x1fW\x1fY\x1f[\x1f]\x1f_\x00-\x1f}\x1f\x80\x00-\x1f\xb4\x1f\xb6\x00-\x1f\xbc\x1f\xbe\x1f\xc2\x00-\x1f\xc4\x1f\xc6\x00-\x1f\xcc\x1f\xd0\x00-\x1f\xd3\x1f\xd6\x00-\x1f\xdb\x1f\xe0\x00-\x1f\xec\x1f\xf2\x00-\x1f\xf4\x1f\xf6\x00-\x1f\xfc!&!*\x00-!+!.!\x80\x00-!\x820\x070!\x00-0)0A\x00-0\x940\xa1\x00-0\xfa1\x05\x00-1,N\x00\x00-\x9f\xa5\xac\x00\x00-\xd7\xa3\x00]\x00[\x00\\\x00x\x002\x00d\x00-\x00.\x000\x00-\x00:\x00A\x00-\x00Z\x00_\x00a\x00-\x00z\x00\xb7\x00\xc0\x00-\x00\xd6\x00\xd8\x00-\x00\xf6\x00\xf8\x00-\x011\x014\x00-\x01>\x01A\x00-\x01H\x01J\x00-\x01~\x01\x80\x00-\x01\xc3\x01\xcd\x00-\x01\xf0\x01\xf4\x00-\x01\xf5\x01\xfa\x00-\x02\x17\x02P\x00-\x02\xa8\x02\xbb\x00-\x02\xc1\x02\xd0\x00-\x02\xd1\x03\x00\x00-\x03E\x03`\x00-\x03a\x03\x86\x00-\x03\x8a\x03\x8c\x03\x8e\x00-\x03\xa1\x03\xa3\x00-\x03\xce\x03\xd0\x00-\x03\xd6\x03\xda\x03\xdc\x03\xde\x03\xe0\x03\xe2\x00-\x03\xf3\x04\x01\x00-\x04\x0c\x04\x0e\x00-\x04O\x04Q\x00-\x04\\\x04^\x00-\x04\x81\x04\x83\x00-\x04\x86\x04\x90\x00-\x04\xc4\x04\xc7\x00-\x04\xc8\x04\xcb\x00-\x04\xcc\x04\xd0\x00-\x04\xeb\x04\xee\x00-\x04\xf5\x04\xf8\x00-\x04\xf9\x051\x00-\x05V\x05Y\x05a\x00-\x05\x86\x05\x91\x00-\x05\xa1\x05\xa3\x00-\x05\xb9\x05\xbb\x00-\x05\xbd\x05\xbf\x05\xc1\x00-\x05\xc2\x05\xc4\x05\xd0\x00-\x05\xea\x05\xf0\x00-\x05\xf2\x06!\x00-\x06:\x06@\x00-\x06R\x06`\x00-\x06i\x06p\x00-\x06\xb7\x06\xba\x00-\x06\xbe\x06\xc0\x00-\x06\xce\x06\xd0\x00-\x06\xd3\x06\xd5\x00-\x06\xe8\x06\xea\x00-\x06\xed\x06\xf0\x00-\x06\xf9\t\x01\x00-\t\x03\t\x05\x00-\t9\t<\x00-\tM\tQ\x00-\tT\tX\x00-\tc\tf\x00-\to\t\x81\x00-\t\x83\t\x85\x00-\t\x8c\t\x8f\x00-\t\x90\t\x93\x00-\t\xa8\t\xaa\x00-\t\xb0\t\xb2\t\xb6\x00-\t\xb9\t\xbc\t\xbe\x00-\t\xc4\t\xc7\x00-\t\xc8\t\xcb\x00-\t\xcd\t\xd7\t\xdc\x00-\t\xdd\t\xdf\x00-\t\xe3\t\xe6\x00-\t\xf1\n\x02\n\x05\x00-\n\n\n\x0f\x00-\n\x10\n\x13\x00-\n(\n*\x00-\n0\n2\x00-\n3\n5\x00-\n6\n8\x00-\n9\n<\n>\x00-\nB\nG\x00-\nH\nK\x00-\nM\nY\x00-\n\\\n^\nf\x00-\nt\n\x81\x00-\n\x83\n\x85\x00-\n\x8b\n\x8d\n\x8f\x00-\n\x91\n\x93\x00-\n\xa8\n\xaa\x00-\n\xb0\n\xb2\x00-\n\xb3\n\xb5\x00-\n\xb9\n\xbc\x00-\n\xc5\n\xc7\x00-\n\xc9\n\xcb\x00-\n\xcd\n\xe0\n\xe6\x00-\n\xef\x0b\x01\x00-\x0b\x03\x0b\x05\x00-\x0b\x0c\x0b\x0f\x00-\x0b\x10\x0b\x13\x00-\x0b(\x0b*\x00-\x0b0\x0b2\x00-\x0b3\x0b6\x00-\x0b9\x0b<\x00-\x0bC\x0bG\x00-\x0bH\x0bK\x00-\x0bM\x0bV\x00-\x0bW\x0b\\\x00-\x0b]\x0b_\x00-\x0ba\x0bf\x00-\x0bo\x0b\x82\x00-\x0b\x83\x0b\x85\x00-\x0b\x8a\x0b\x8e\x00-\x0b\x90\x0b\x92\x00-\x0b\x95\x0b\x99\x00-\x0b\x9a\x0b\x9c\x0b\x9e\x00-\x0b\x9f\x0b\xa3\x00-\x0b\xa4\x0b\xa8\x00-\x0b\xaa\x0b\xae\x00-\x0b\xb5\x0b\xb7\x00-\x0b\xb9\x0b\xbe\x00-\x0b\xc2\x0b\xc6\x00-\x0b\xc8\x0b\xca\x00-\x0b\xcd\x0b\xd7\x0b\xe7\x00-\x0b\xef\x0c\x01\x00-\x0c\x03\x0c\x05\x00-\x0c\x0c\x0c\x0e\x00-\x0c\x10\x0c\x12\x00-\x0c(\x0c*\x00-\x0c3\x0c5\x00-\x0c9\x0c>\x00-\x0cD\x0cF\x00-\x0cH\x0cJ\x00-\x0cM\x0cU\x00-\x0cV\x0c`\x00-\x0ca\x0cf\x00-\x0co\x0c\x82\x00-\x0c\x83\x0c\x85\x00-\x0c\x8c\x0c\x8e\x00-\x0c\x90\x0c\x92\x00-\x0c\xa8\x0c\xaa\x00-\x0c\xb3\x0c\xb5\x00-\x0c\xb9\x0c\xbe\x00-\x0c\xc4\x0c\xc6\x00-\x0c\xc8\x0c\xca\x00-\x0c\xcd\x0c\xd5\x00-\x0c\xd6\x0c\xde\x0c\xe0\x00-\x0c\xe1\x0c\xe6\x00-\x0c\xef\r\x02\x00-\r\x03\r\x05\x00-\r\x0c\r\x0e\x00-\r\x10\r\x12\x00-\r(\r*\x00-\r9\r>\x00-\rC\rF\x00-\rH\rJ\x00-\rM\rW\r`\x00-\ra\rf\x00-\ro\x0e\x01\x00-\x0e.\x0e0\x00-\x0e:\x0e@\x00-\x0eN\x0eP\x00-\x0eY\x0e\x81\x00-\x0e\x82\x0e\x84\x0e\x87\x00-\x0e\x88\x0e\x8a\x0e\x8d\x0e\x94\x00-\x0e\x97\x0e\x99\x00-\x0e\x9f\x0e\xa1\x00-\x0e\xa3\x0e\xa5\x0e\xa7\x0e\xaa\x00-\x0e\xab\x0e\xad\x00-\x0e\xae\x0e\xb0\x00-\x0e\xb9\x0e\xbb\x00-\x0e\xbd\x0e\xc0\x00-\x0e\xc4\x0e\xc6\x0e\xc8\x00-\x0e\xcd\x0e\xd0\x00-\x0e\xd9\x0f\x18\x00-\x0f\x19\x0f \x00-\x0f)\x0f5\x0f7\x0f9\x0f>\x00-\x0fG\x0fI\x00-\x0fi\x0fq\x00-\x0f\x84\x0f\x86\x00-\x0f\x8b\x0f\x90\x00-\x0f\x95\x0f\x97\x0f\x99\x00-\x0f\xad\x0f\xb1\x00-\x0f\xb7\x0f\xb9\x10\xa0\x00-\x10\xc5\x10\xd0\x00-\x10\xf6\x11\x00\x11\x02\x00-\x11\x03\x11\x05\x00-\x11\x07\x11\t\x11\x0b\x00-\x11\x0c\x11\x0e\x00-\x11\x12\x11<\x11>\x11@\x11L\x11N\x11P\x11T\x00-\x11U\x11Y\x11_\x00-\x11a\x11c\x11e\x11g\x11i\x11m\x00-\x11n\x11r\x00-\x11s\x11u\x11\x9e\x11\xa8\x11\xab\x11\xae\x00-\x11\xaf\x11\xb7\x00-\x11\xb8\x11\xba\x11\xbc\x00-\x11\xc2\x11\xeb\x11\xf0\x11\xf9\x1e\x00\x00-\x1e\x9b\x1e\xa0\x00-\x1e\xf9\x1f\x00\x00-\x1f\x15\x1f\x18\x00-\x1f\x1d\x1f \x00-\x1fE\x1fH\x00-\x1fM\x1fP\x00-\x1fW\x1fY\x1f[\x1f]\x1f_\x00-\x1f}\x1f\x80\x00-\x1f\xb4\x1f\xb6\x00-\x1f\xbc\x1f\xbe\x1f\xc2\x00-\x1f\xc4\x1f\xc6\x00-\x1f\xcc\x1f\xd0\x00-\x1f\xd3\x1f\xd6\x00-\x1f\xdb\x1f\xe0\x00-\x1f\xec\x1f\xf2\x00-\x1f\xf4\x1f\xf6\x00-\x1f\xfc \xd0\x00- \xdc \xe1!&!*\x00-!+!.!\x80\x00-!\x820\x050\x070!\x00-0/01\x00-050A\x00-0\x940\x99\x00-0\x9a0\x9d\x00-0\x9e0\xa1\x00-0\xfa0\xfc\x00-0\xfe1\x05\x00-1,N\x00\x00-\x9f\xa5\xac\x00\x00-\xd7\xa3\x00]\x00*','utf-16-be') Names = Name+'('+S+Name+')*' Nmtoken = unicode('\x00[\x00\\\x00x\x002\x00d\x00-\x00.\x000\x00-\x00:\x00A\x00-\x00Z\x00_\x00a\x00-\x00z\x00\xb7\x00\xc0\x00-\x00\xd6\x00\xd8\x00-\x00\xf6\x00\xf8\x00-\x011\x014\x00-\x01>\x01A\x00-\x01H\x01J\x00-\x01~\x01\x80\x00-\x01\xc3\x01\xcd\x00-\x01\xf0\x01\xf4\x00-\x01\xf5\x01\xfa\x00-\x02\x17\x02P\x00-\x02\xa8\x02\xbb\x00-\x02\xc1\x02\xd0\x00-\x02\xd1\x03\x00\x00-\x03E\x03`\x00-\x03a\x03\x86\x00-\x03\x8a\x03\x8c\x03\x8e\x00-\x03\xa1\x03\xa3\x00-\x03\xce\x03\xd0\x00-\x03\xd6\x03\xda\x03\xdc\x03\xde\x03\xe0\x03\xe2\x00-\x03\xf3\x04\x01\x00-\x04\x0c\x04\x0e\x00-\x04O\x04Q\x00-\x04\\\x04^\x00-\x04\x81\x04\x83\x00-\x04\x86\x04\x90\x00-\x04\xc4\x04\xc7\x00-\x04\xc8\x04\xcb\x00-\x04\xcc\x04\xd0\x00-\x04\xeb\x04\xee\x00-\x04\xf5\x04\xf8\x00-\x04\xf9\x051\x00-\x05V\x05Y\x05a\x00-\x05\x86\x05\x91\x00-\x05\xa1\x05\xa3\x00-\x05\xb9\x05\xbb\x00-\x05\xbd\x05\xbf\x05\xc1\x00-\x05\xc2\x05\xc4\x05\xd0\x00-\x05\xea\x05\xf0\x00-\x05\xf2\x06!\x00-\x06:\x06@\x00-\x06R\x06`\x00-\x06i\x06p\x00-\x06\xb7\x06\xba\x00-\x06\xbe\x06\xc0\x00-\x06\xce\x06\xd0\x00-\x06\xd3\x06\xd5\x00-\x06\xe8\x06\xea\x00-\x06\xed\x06\xf0\x00-\x06\xf9\t\x01\x00-\t\x03\t\x05\x00-\t9\t<\x00-\tM\tQ\x00-\tT\tX\x00-\tc\tf\x00-\to\t\x81\x00-\t\x83\t\x85\x00-\t\x8c\t\x8f\x00-\t\x90\t\x93\x00-\t\xa8\t\xaa\x00-\t\xb0\t\xb2\t\xb6\x00-\t\xb9\t\xbc\t\xbe\x00-\t\xc4\t\xc7\x00-\t\xc8\t\xcb\x00-\t\xcd\t\xd7\t\xdc\x00-\t\xdd\t\xdf\x00-\t\xe3\t\xe6\x00-\t\xf1\n\x02\n\x05\x00-\n\n\n\x0f\x00-\n\x10\n\x13\x00-\n(\n*\x00-\n0\n2\x00-\n3\n5\x00-\n6\n8\x00-\n9\n<\n>\x00-\nB\nG\x00-\nH\nK\x00-\nM\nY\x00-\n\\\n^\nf\x00-\nt\n\x81\x00-\n\x83\n\x85\x00-\n\x8b\n\x8d\n\x8f\x00-\n\x91\n\x93\x00-\n\xa8\n\xaa\x00-\n\xb0\n\xb2\x00-\n\xb3\n\xb5\x00-\n\xb9\n\xbc\x00-\n\xc5\n\xc7\x00-\n\xc9\n\xcb\x00-\n\xcd\n\xe0\n\xe6\x00-\n\xef\x0b\x01\x00-\x0b\x03\x0b\x05\x00-\x0b\x0c\x0b\x0f\x00-\x0b\x10\x0b\x13\x00-\x0b(\x0b*\x00-\x0b0\x0b2\x00-\x0b3\x0b6\x00-\x0b9\x0b<\x00-\x0bC\x0bG\x00-\x0bH\x0bK\x00-\x0bM\x0bV\x00-\x0bW\x0b\\\x00-\x0b]\x0b_\x00-\x0ba\x0bf\x00-\x0bo\x0b\x82\x00-\x0b\x83\x0b\x85\x00-\x0b\x8a\x0b\x8e\x00-\x0b\x90\x0b\x92\x00-\x0b\x95\x0b\x99\x00-\x0b\x9a\x0b\x9c\x0b\x9e\x00-\x0b\x9f\x0b\xa3\x00-\x0b\xa4\x0b\xa8\x00-\x0b\xaa\x0b\xae\x00-\x0b\xb5\x0b\xb7\x00-\x0b\xb9\x0b\xbe\x00-\x0b\xc2\x0b\xc6\x00-\x0b\xc8\x0b\xca\x00-\x0b\xcd\x0b\xd7\x0b\xe7\x00-\x0b\xef\x0c\x01\x00-\x0c\x03\x0c\x05\x00-\x0c\x0c\x0c\x0e\x00-\x0c\x10\x0c\x12\x00-\x0c(\x0c*\x00-\x0c3\x0c5\x00-\x0c9\x0c>\x00-\x0cD\x0cF\x00-\x0cH\x0cJ\x00-\x0cM\x0cU\x00-\x0cV\x0c`\x00-\x0ca\x0cf\x00-\x0co\x0c\x82\x00-\x0c\x83\x0c\x85\x00-\x0c\x8c\x0c\x8e\x00-\x0c\x90\x0c\x92\x00-\x0c\xa8\x0c\xaa\x00-\x0c\xb3\x0c\xb5\x00-\x0c\xb9\x0c\xbe\x00-\x0c\xc4\x0c\xc6\x00-\x0c\xc8\x0c\xca\x00-\x0c\xcd\x0c\xd5\x00-\x0c\xd6\x0c\xde\x0c\xe0\x00-\x0c\xe1\x0c\xe6\x00-\x0c\xef\r\x02\x00-\r\x03\r\x05\x00-\r\x0c\r\x0e\x00-\r\x10\r\x12\x00-\r(\r*\x00-\r9\r>\x00-\rC\rF\x00-\rH\rJ\x00-\rM\rW\r`\x00-\ra\rf\x00-\ro\x0e\x01\x00-\x0e.\x0e0\x00-\x0e:\x0e@\x00-\x0eN\x0eP\x00-\x0eY\x0e\x81\x00-\x0e\x82\x0e\x84\x0e\x87\x00-\x0e\x88\x0e\x8a\x0e\x8d\x0e\x94\x00-\x0e\x97\x0e\x99\x00-\x0e\x9f\x0e\xa1\x00-\x0e\xa3\x0e\xa5\x0e\xa7\x0e\xaa\x00-\x0e\xab\x0e\xad\x00-\x0e\xae\x0e\xb0\x00-\x0e\xb9\x0e\xbb\x00-\x0e\xbd\x0e\xc0\x00-\x0e\xc4\x0e\xc6\x0e\xc8\x00-\x0e\xcd\x0e\xd0\x00-\x0e\xd9\x0f\x18\x00-\x0f\x19\x0f \x00-\x0f)\x0f5\x0f7\x0f9\x0f>\x00-\x0fG\x0fI\x00-\x0fi\x0fq\x00-\x0f\x84\x0f\x86\x00-\x0f\x8b\x0f\x90\x00-\x0f\x95\x0f\x97\x0f\x99\x00-\x0f\xad\x0f\xb1\x00-\x0f\xb7\x0f\xb9\x10\xa0\x00-\x10\xc5\x10\xd0\x00-\x10\xf6\x11\x00\x11\x02\x00-\x11\x03\x11\x05\x00-\x11\x07\x11\t\x11\x0b\x00-\x11\x0c\x11\x0e\x00-\x11\x12\x11<\x11>\x11@\x11L\x11N\x11P\x11T\x00-\x11U\x11Y\x11_\x00-\x11a\x11c\x11e\x11g\x11i\x11m\x00-\x11n\x11r\x00-\x11s\x11u\x11\x9e\x11\xa8\x11\xab\x11\xae\x00-\x11\xaf\x11\xb7\x00-\x11\xb8\x11\xba\x11\xbc\x00-\x11\xc2\x11\xeb\x11\xf0\x11\xf9\x1e\x00\x00-\x1e\x9b\x1e\xa0\x00-\x1e\xf9\x1f\x00\x00-\x1f\x15\x1f\x18\x00-\x1f\x1d\x1f \x00-\x1fE\x1fH\x00-\x1fM\x1fP\x00-\x1fW\x1fY\x1f[\x1f]\x1f_\x00-\x1f}\x1f\x80\x00-\x1f\xb4\x1f\xb6\x00-\x1f\xbc\x1f\xbe\x1f\xc2\x00-\x1f\xc4\x1f\xc6\x00-\x1f\xcc\x1f\xd0\x00-\x1f\xd3\x1f\xd6\x00-\x1f\xdb\x1f\xe0\x00-\x1f\xec\x1f\xf2\x00-\x1f\xf4\x1f\xf6\x00-\x1f\xfc \xd0\x00- \xdc \xe1!&!*\x00-!+!.!\x80\x00-!\x820\x050\x070!\x00-0/01\x00-050A\x00-0\x940\x99\x00-0\x9a0\x9d\x00-0\x9e0\xa1\x00-0\xfa0\xfc\x00-0\xfe1\x05\x00-1,N\x00\x00-\x9f\xa5\xac\x00\x00-\xd7\xa3\x00]\x00+','utf-16-be') Nmtokens = Nmtoken+'('+S+Nmtoken+')*' import re _re_BaseChar = None def re_BaseChar(): global _re_BaseChar if _re_BaseChar is None: _re_BaseChar = re.compile(BaseChar) return _re_BaseChar _re_Ideographic = None def re_Ideographic(): global _re_Ideographic if _re_Ideographic is None: _re_Ideographic = re.compile(Ideographic) return _re_Ideographic _re_CombiningChar = None def re_CombiningChar(): global _re_CombiningChar if _re_CombiningChar is None: _re_CombiningChar = re.compile(CombiningChar) return _re_CombiningChar _re_Digit = None def re_Digit(): global _re_Digit if _re_Digit is None: _re_Digit = re.compile(Digit) return _re_Digit _re_Extender = None def re_Extender(): global _re_Extender if _re_Extender is None: _re_Extender = re.compile(Extender) return _re_Extender _re_Letter = None def re_Letter(): global _re_Letter if _re_Letter is None: _re_Letter = re.compile(Letter) return _re_Letter _re_NameChar = None def re_NameChar(): global _re_NameChar if _re_NameChar is None: _re_NameChar = re.compile(NameChar) return _re_NameChar _re_Name = None def re_Name(): global _re_Name if _re_Name is None: _re_Name = re.compile(Name) return _re_Name _re_Names = None def re_Names(): global _re_Names if _re_Names is None: _re_Names = re.compile(Names) return _re_Names _re_Nmtoken = None def re_Nmtoken(): global _re_Nmtoken if _re_Nmtoken is None: _re_Nmtoken = re.compile(Nmtoken) return _re_Nmtoken _re_Nmtokens = None def re_Nmtokens(): global _re_Nmtokens if _re_Nmtokens is None: _re_Nmtokens = re.compile(Nmtokens) return _re_Nmtokens PyXML-0.8.2/xml/utils/iso8601.py0100644000076400001440000001273007461630230015337 0ustar martinusers"""ISO-8601 date format support, sufficient for the profile defined in . The parser is more flexible on the input format than is required to support the W3C profile, but all accepted date/time values are legal ISO 8601 dates. The tostring() method only generates formatted dates that are conformant to the profile. This module was written by Fred L. Drake, Jr. . """ __version__ = '1.0' import time def parse(s): """Parse an ISO-8601 date/time string, returning the value in seconds since the epoch.""" m = __datetime_rx.match(s) if m is None or m.group() != s: raise ValueError, "unknown or illegal ISO-8601 date format: " + `s` gmt = __extract_date(m) + __extract_time(m) + (0, 0, 0) return time.mktime(gmt) + __extract_tzd(m) - time.timezone def parse_timezone(timezone): """Parse an ISO-8601 time zone designator, returning the value in seconds relative to UTC.""" m = __tzd_rx.match(timezone) if not m: raise ValueError, "unknown timezone specifier: " + `timezone` if m.group() != timezone: raise ValueError, "unknown timezone specifier: " + `timezone` return __extract_tzd(m) def tostring(t, timezone=0): """Format a time in ISO-8601 format. If `timezone' is specified, the time will be specified for that timezone, otherwise for UTC. Some effort is made to avoid adding text for the 'seconds' field, but seconds are supported to the hundredths. """ if type(timezone) is type(''): timezone = parse_timezone(timezone) else: timezone = int(timezone) if timezone: sign = (timezone < 0) and "+" or "-" timezone = abs(timezone) hours = timezone / (60 * 60) minutes = (timezone % (60 * 60)) / 60 tzspecifier = "%c%02d:%02d" % (sign, hours, minutes) else: tzspecifier = "Z" psecs = t - int(t) t = time.gmtime(int(t) - timezone) year, month, day, hours, minutes, seconds = t[:6] if seconds or psecs: if psecs: psecs = int(round(psecs * 100)) f = "%4d-%02d-%02dT%02d:%02d:%02d.%02d%s" v = (year, month, day, hours, minutes, seconds, psecs, tzspecifier) else: f = "%4d-%02d-%02dT%02d:%02d:%02d%s" v = (year, month, day, hours, minutes, seconds, tzspecifier) else: f = "%4d-%02d-%02dT%02d:%02d%s" v = (year, month, day, hours, minutes, tzspecifier) return f % v def ctime(t): """Similar to time.ctime(), but using ISO-8601 format.""" return tostring(t, time.timezone) # Internal data and functions: import re __date_re = ("(?P\d\d\d\d)" "(?:(?P-|)" "(?:(?P\d\d\d)" "|(?P\d\d)(?:(?P=dsep)(?P\d\d))?))?") __tzd_re = "(?P[-+](?P\d\d)(?::?(?P\d\d))|Z)" __tzd_rx = re.compile(__tzd_re) __time_re = ("(?P\d\d)(?P:|)(?P\d\d)" "(?:(?P=tsep)(?P\d\d(?:[.,]\d+)?))?" + __tzd_re) __datetime_re = "%s(?:T%s)?" % (__date_re, __time_re) __datetime_rx = re.compile(__datetime_re) del re def __extract_date(m): year = int(m.group("year")) julian = m.group("julian") if julian: return __find_julian(year, int(julian)) month = m.group("month") day = 1 if month is None: month = 1 else: month = int(month) if not 1 <= month <= 12: raise ValueError, "illegal month number: " + m.group("month") else: day = m.group("day") if day: day = int(day) if not 1 <= day <= 31: raise ValueError, "illegal day number: " + m.group("day") else: day = 1 return year, month, day def __extract_time(m): if not m: return 0, 0, 0 hours = m.group("hours") if not hours: return 0, 0, 0 hours = int(hours) if not 0 <= hours <= 23: raise ValueError, "illegal hour number: " + m.group("hours") minutes = int(m.group("minutes")) if not 0 <= minutes <= 59: raise ValueError, "illegal minutes number: " + m.group("minutes") seconds = m.group("seconds") if seconds: seconds = float(seconds) if not 0 <= seconds <= 60: raise ValueError, "illegal seconds number: " + m.group("seconds") else: seconds = 0 return hours, minutes, seconds def __extract_tzd(m): """Return the Time Zone Designator as an offset in seconds from UTC.""" if not m: return 0 tzd = m.group("tzd") if not tzd: return 0 if tzd == "Z": return 0 hours = int(m.group("tzdhours")) minutes = m.group("tzdminutes") if minutes: minutes = int(minutes) else: minutes = 0 offset = (hours*60 + minutes) * 60 if tzd[0] == "+": return -offset return offset def __find_julian(year, julian): month = julian / 30 + 1 day = julian % 30 + 1 jday = None while jday != julian: t = time.mktime((year, month, day, 0, 0, 0, 0, 0, 0)) jday = time.gmtime(t)[-2] diff = abs(jday - julian) if jday > julian: if diff < day: day = day - diff else: month = month - 1 day = 31 elif jday < julian: if day + diff < 28: day = day + diff else: month = month + 1 return year, month, day PyXML-0.8.2/xml/utils/qp_xml.py0100644000076400001440000001402007357127430015527 0ustar martinusers# # qp_xml: Quick Parsing for XML # # Written by Greg Stein. Public Domain. # No Copyright, no Rights Reserved, and no Warranties. # # This module is maintained by Greg and is available as part of the XML-SIG # distribution. This module and its changelog can be fetched at: # http://www.lyra.org/cgi-bin/viewcvs.cgi/xml/xml/utils/qp_xml.py # # Additional information can be found on Greg's Python page at: # http://www.lyra.org/greg/python/ # # This module was added to the XML-SIG distribution on February 14, 2000. # As part of that distribution, it falls under the XML distribution license. # import string try: import pyexpat except ImportError: from xml.parsers import pyexpat error = __name__ + '.error' # # The parsing class. Instantiate and pass a string/file to .parse() # class Parser: def __init__(self): self.reset() def reset(self): self.root = None self.cur_elem = None def find_prefix(self, prefix): elem = self.cur_elem while elem: if elem.ns_scope.has_key(prefix): return elem.ns_scope[prefix] elem = elem.parent if prefix == '': return '' # empty URL for "no namespace" return None def process_prefix(self, name, use_default): idx = string.find(name, ':') if idx == -1: if use_default: return self.find_prefix(''), name return '', name # no namespace if string.lower(name[:3]) == 'xml': return '', name # name is reserved by XML. don't break out a NS. ns = self.find_prefix(name[:idx]) if ns is None: raise error, 'namespace prefix ("%s") not found' % name[:idx] return ns, name[idx+1:] def start(self, name, attrs): elem = _element(name=name, lang=None, parent=None, children=[], ns_scope={}, attrs={}, first_cdata='', following_cdata='') if self.cur_elem: elem.parent = self.cur_elem elem.parent.children.append(elem) self.cur_elem = elem else: self.cur_elem = self.root = elem work_attrs = [ ] # scan for namespace declarations (and xml:lang while we're at it) for name, value in attrs.items(): if name == 'xmlns': elem.ns_scope[''] = value elif name[:6] == 'xmlns:': elem.ns_scope[name[6:]] = value elif name == 'xml:lang': elem.lang = value else: work_attrs.append((name, value)) # inherit xml:lang from parent if elem.lang is None and elem.parent: elem.lang = elem.parent.lang # process prefix of the element name elem.ns, elem.name = self.process_prefix(elem.name, 1) # process attributes' namespace prefixes for name, value in work_attrs: elem.attrs[self.process_prefix(name, 0)] = value def end(self, name): parent = self.cur_elem.parent del self.cur_elem.ns_scope del self.cur_elem.parent self.cur_elem = parent def cdata(self, data): elem = self.cur_elem if elem.children: last = elem.children[-1] last.following_cdata = last.following_cdata + data else: elem.first_cdata = elem.first_cdata + data def parse(self, input): self.reset() p = pyexpat.ParserCreate() p.StartElementHandler = self.start p.EndElementHandler = self.end p.CharacterDataHandler = self.cdata try: if type(input) == type(''): p.Parse(input, 1) else: while 1: s = input.read(_BLOCKSIZE) if not s: p.Parse('', 1) break p.Parse(s, 0) finally: if self.root: _clean_tree(self.root) return self.root # # handy function for dumping a tree that is returned by Parser # def dump(f, root): f.write('\n') namespaces = _collect_ns(root) _dump_recurse(f, root, namespaces, dump_ns=1) f.write('\n') # # This function returns the element's CDATA. Note: this is not recursive -- # it only returns the CDATA immediately within the element, excluding the # CDATA in child elements. # def textof(elem): return elem.textof() ######################################################################### # # private stuff for qp_xml # _BLOCKSIZE = 16384 # chunk size for parsing input class _element: def __init__(self, **kw): self.__dict__.update(kw) def textof(self): '''Return the CDATA of this element. Note: this is not recursive -- it only returns the CDATA immediately within the element, excluding the CDATA in child elements. ''' s = self.first_cdata for child in self.children: s = s + child.following_cdata return s def find(self, name, ns=''): for elem in self.children: if elem.name == name and elem.ns == ns: return elem return None def _clean_tree(elem): elem.parent = None del elem.parent map(_clean_tree, elem.children) def _collect_recurse(elem, dict): dict[elem.ns] = None for ns, name in elem.attrs.keys(): dict[ns] = None for child in elem.children: _collect_recurse(child, dict) def _collect_ns(elem): "Collect all namespaces into a NAMESPACE -> PREFIX mapping." d = { '' : None } _collect_recurse(elem, d) del d[''] # make sure we don't pick up no-namespace entries keys = d.keys() for i in range(len(keys)): d[keys[i]] = i return d def _dump_recurse(f, elem, namespaces, lang=None, dump_ns=0): if elem.ns: f.write('' + elem.first_cdata) for child in elem.children: _dump_recurse(f, child, namespaces, elem.lang) f.write(child.following_cdata) if elem.ns: f.write('' % (namespaces[elem.ns], elem.name)) else: f.write('' % elem.name) else: f.write('/>') PyXML-0.8.2/xml/xpath/0040755000076400001440000000000007614726123013647 5ustar martinusersPyXML-0.8.2/xml/xpath/BuiltInExtFunctions.py0100644000076400001440000002247107377133277020154 0ustar martinusers######################################################################## # # File Name: BuiltInExtFunctions.py # # Docs: http://docs.4suite.org/XPath/BuiltInExtFunctions.py.html # """ 4XPath-specific Extension functions WWW: http://4suite.org/XSLT e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import sys, re, string, urllib from xml.dom import Node, EMPTY_NAMESPACE from xml.dom.Text import Text from xml.utils import boolean from xml.xpath import CoreFunctions, Conversions, FT_EXT_NAMESPACE, FT_OLD_EXT_NAMESPACE def Version(context): try: from Ft.__init__ import __version__ return __version__ except: return "0.11.1" # XXX Upgrade whenever re-integrated. def NodeSet(context, rtf): """Convert a result-tree fragment to a node-set""" if type(rtf) == type([]): return rtf if hasattr(rtf,'nodeType') and rtf.nodeType == Node.DOCUMENT_NODE: node_set = list(rtf.childNodes) else: node_set = [rtf] return node_set def Match(context, pattern, arg=None): """Do a regular expression match against the argument""" if not arg: arg = context.node arg = Conversions.StringValue(arg) bool = re.match(pattern, arg) and boolean.true or boolean.false return bool def Replace(context, old, new, arg=None): """Do a global search and replace of the string contents""" if not arg: arg = context.node arg = Conversions.StringValue(arg) old = Conversions.StringValue(old) new = Conversions.StringValue(new) return string.replace(arg, old, new) #FIXME: Really only makes sense for XSLT def SearchRe(context, pattern, arg=None): """Do a regular expression search against the argument (i.e. get all matches)""" if not arg: arg = context.node arg = Conversions.StringValue(arg) matches = re.findall(pattern, arg) proc = context.processor matches_nodeset = [] for groups in matches: proc.pushResult() proc.writers[-1].startElement('Match', EMPTY_NAMESPACE) if type(groups) != type(()): groups = (groups,) for group in groups: proc.writers[-1].startElement('Group', EMPTY_NAMESPACE) proc.writers[-1].text(group) proc.writers[-1].endElement('Group') proc.writers[-1].endElement('Match') frag = proc.popResult() context.rtfs.append(frag) matches_nodeset.append(frag.childNodes[0]) return matches_nodeset #This version incorporates a workaround for a Python 2.0 bug in re.findall #Courtesy alexander smishlajev #See http://lists.fourthought.com/pipermail/4suite/2001-June/002188.html def SearchRePy20(context, pattern, arg=None): """Do a regular expression search against the argument (i.e. get all matches)""" if not arg: arg = context.node arg = Conversions.StringValue(arg) proc = context.processor matches_nodeset = [] _re =re.compile(pattern) _match =_re.search(arg) while _match: proc.pushResult() proc.writers[-1].startElement('Match', EMPTY_NAMESPACE) _groups =_match.groups() # .groups() return empty tuple when the pattern did not do grouping if not _groups: _groups =tuple(_match.group()) for group in _groups: proc.writers[-1].startElement('Group', EMPTY_NAMESPACE) # MatchObject groups return None if unmatched # unlike .findall() returning empty strings proc.writers[-1].text(group or '') proc.writers[-1].endElement('Group') proc.writers[-1].endElement('Match') frag = proc.popResult() context.rtfs.append(frag) matches_nodeset.append(frag.childNodes[0]) _match =_re.search(arg, _match.end()) return matches_nodeset #FIXME: Really only makes sense for XSLT (in fact, barely makes sense at all) def Map(context, funcname, *nodesets): """ Apply the function serially over the given node sets. In iteration i, the function is passed N parameters where N is the number of argument node sets. Each parameter is a node set of size 1, whose node is the ith node of the corresponding argument node set. The return value is a node set consisting of a series of result-tree nodes, each of which is a text node whose value is the string value of the result of the ith function invocation. Warning: this function uses the implied ordering of the node set Based on its implementation as a Python list. But in reality There is no reliable ordering of XPath node sets. In other words, this function is voodoo. """ (prefix, local) = ExpandQName(funcname, namespaces=context.processorNss) func = (g_extFunctions.get(expanded) or CoreFunctions.CoreFunctions.get(expanded, None)) if not func: raise Exception('Dynamically invoked function %s not found.'%funcname) flist = [f]*len(nodesets) lf = lambda x, f, *args: apply(f, args) retlist = apply(map, (lf, flist) + nodesets) proc = context.processor result_nodeset = [] for ret in retlist: proc.pushResult() proc.writers[-1].text(Conversions.StringValue(ret)) frag = proc.popResult() context.rtfs.append(frag) result_nodeset.append(frag.childNodes[0]) return result_nodeset def EscapeUrl(context, url): "Escape illegal characters in a URL" return urllib.quote(Conversions.StringValue(url)) def BaseUri(context, arg=None): """Get the base URI of the argument""" #FIXME: Arg must be a node set if not arg: arg = [context.node] if hasattr(arg[0],'baseUri'): return arg[0].baseUri elif hasattr(arg[0],'refUri'): return arg[0].refUri return "" def IsoTime(context): import DateTime d = DateTime.now() return DateTime.ISO.str(d) def Evaluate(context, expr): import xml.xpath return xml.xpath.Evaluate(Conversions.StringValue(st), context=context) try: # Import something small and "safe" import Ft.Lib.DumpBgTuple def GenerateUuid(context): from Ft.Lib import Uuid return Uuid.UuidAsString(Uuid.GenerateUuid()) except: GenerateUuid = None ## ## distinct, split, range if_function and find ## were contributed by Lars Marius Garshol. ## Their namespace URI was originally 'http://garshol.priv.no/symbolic/' ## but has been changed to the 4Suite.org NSRef ## so users don't have to declare yet another namespace. ## def distinct(context, nodeset): if type(nodeset) != type([]): raise Exception("'distinct' parameter must be of type node-set!") nodes = {} for node in nodeset: nodes[Conversions.StringValue(node)] = node return nodes.values() def split(context, arg, delim=None): doc = context.node while doc.parentNode: doc = doc.parentNode nodeset = [] for token in string.split(Conversions.StringValue(arg), delim): nodeset.append(doc.createTextNode(token)) return nodeset def join(context, nodeset, delim=None): comps = map(lambda x: Conversions.StringValue(x), nodeset) if delim: return string.joinfields(comps, delim) else: return string.joinfields(comps) def range(context, lo, hi): doc = context.node while doc.parentNode: doc = doc.parentNode lo = Conversions.NumberValue(lo) hi = Conversions.NumberValue(hi) nodeset = [] for number in xrange(lo, hi): nodeset.append(doc.createTextNode(str(number))) return nodeset def if_function(context, cond, v1, v2): if Conversions.BooleanValue(cond): return v1 else: return v2 def find(context, outer, inner): return string.find(Conversions.StringValue(outer), Conversions.StringValue(inner)) ExtFunctions = { (FT_EXT_NAMESPACE, 'node-set'): NodeSet, (FT_EXT_NAMESPACE, 'match'): Match, (FT_EXT_NAMESPACE, 'search-re'): sys.hexversion != 0x20000f1 and SearchRe or SearchRePy20, (FT_EXT_NAMESPACE, 'base-uri'): BaseUri, (FT_EXT_NAMESPACE, 'escape-url'): EscapeUrl, (FT_EXT_NAMESPACE, 'iso-time'): IsoTime, (FT_EXT_NAMESPACE, 'evaluate'): Evaluate, (FT_EXT_NAMESPACE, 'distinct'): distinct, (FT_EXT_NAMESPACE, 'split'): split, (FT_EXT_NAMESPACE, 'join'): join, (FT_EXT_NAMESPACE, 'range'): range, (FT_EXT_NAMESPACE, 'if'): if_function, (FT_EXT_NAMESPACE, 'find'): find, (FT_EXT_NAMESPACE, 'map'): Map, (FT_EXT_NAMESPACE, 'version'): Version, (FT_EXT_NAMESPACE, 'generate-uuid'): GenerateUuid, (FT_EXT_NAMESPACE, 'replace'): Replace, (FT_OLD_EXT_NAMESPACE, 'node-set'): NodeSet, (FT_OLD_EXT_NAMESPACE, 'match'): Match, (FT_OLD_EXT_NAMESPACE, 'search-re'): sys.hexversion != 0x20000f1 and SearchRe or SearchRePy20, (FT_OLD_EXT_NAMESPACE, 'base-uri'): BaseUri, (FT_OLD_EXT_NAMESPACE, 'escape-url'): EscapeUrl, (FT_OLD_EXT_NAMESPACE, 'iso-time'): IsoTime, (FT_OLD_EXT_NAMESPACE, 'evaluate'): Evaluate, (FT_OLD_EXT_NAMESPACE, 'distinct'): distinct, (FT_OLD_EXT_NAMESPACE, 'split'): split, (FT_OLD_EXT_NAMESPACE, 'join'): join, (FT_OLD_EXT_NAMESPACE, 'range'): range, (FT_OLD_EXT_NAMESPACE, 'if'): if_function, (FT_OLD_EXT_NAMESPACE, 'find'): find, (FT_OLD_EXT_NAMESPACE, 'map'): Map, (FT_OLD_EXT_NAMESPACE, 'version'): Version, } PyXML-0.8.2/xml/xpath/Context.py0100644000076400001440000000431507356637352015655 0ustar martinusers######################################################################## # # File Name: Context.py # # Docs: http://docs.4suite.org/XPATH/Context.py.html # """ The context of an XPath expression. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import xml.dom.ext import CoreFunctions class Context: functions = CoreFunctions.CoreFunctions def __init__(self, node, position=1, size=1, varBindings=None, processorNss=None): self.node = node self.position = position self.size = size self.varBindings = varBindings or {} self.processorNss = processorNss or {} self._cachedNss = None self._cachedNssNode = None self.stringValueCache = {} return def __repr__(self): return "" % ( id(self), self.node, self.position, self.size ) def nss(self): if self._cachedNss is None or self.node != self._cachedNssNode: nss = xml.dom.ext.GetAllNs(self.node) self._cachedNss = nss self._cachedNssNode = self.node return self._cachedNss def next(self): pass def setNamespaces(self, processorNss): self.processorNss = processorNss def copyNamespaces(self): return self.processorNss.copy() def setVarBindings(self, varBindings): self.varBindings = varBindings def copyVarBindings(self): #FIXME: should this be deep copy, because of the possible list entries? return self.varBindings.copy() def copyNodePosSize(self): return (self.node, self.position, self.size) def setNodePosSize(self,(node,pos,size)): self.node = node self.position = pos self.size = size def copy(self): newdict = self.__dict__.copy() newdict["varBindings"] = self.varBindings.copy() return newdict def set(self,d): self.__dict__ = d PyXML-0.8.2/xml/xpath/Conversions.py0100644000076400001440000001345107356637352016542 0ustar martinusers######################################################################## # # File Name: Conversions.py # # Docs: http://docs.4suite.org/XPATH/Conversions.py.html # """ The implementation of all of the core functions for the XPath spec. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import string, cStringIO from xml.dom import Node from xml.xpath import ExpandedNameWrapper from xml.xpath import NamespaceNode from xml.xpath import NaN, Inf from xml.xpath import Util from xml.xpath import NAMESPACE_NODE from xml.utils import boolean import types try: g_stringTypes= [types.StringType, types.UnicodeType] except: g_stringTypes= [types.StringType] def BooleanEvaluate(exp, context): rt = exp.evaluate(context) return BooleanValue(rt) def StringValue(object): #def StringValue(object, context=None): #print "StringValue context", context #if context: # cache = context.stringValueCache #else: # cache = None for func in g_stringConversions: #handled, result = func(object, cache) handled, result = func(object) if handled: break else: result = None return result def BooleanValue(object): for func in g_booleanConversions: handled, result = func(object) if handled: break else: result = None return result def NumberValue(object): for func in g_numberConversions: handled, result = func(object) if handled: break else: result = None return result def NodeSetValue(object): for func in g_nodeSetConversions: handled, result = func(object) if handled: break else: result = None return result def CoreStringValue(object): """Get the string value of any object""" # See bottom of file for conversion functions result = _strConversions.get(type(object), _strUnknown)(object) return result is not None, result def CoreNumberValue(object): """Get the number value of any object""" if type(object) in [type(1), type(2.3), type(4L)]: return 1, object elif boolean.IsBooleanType(object): return 1, int(object) #FIXME: This can probably be optimized object = StringValue(object) try: object = float(object) except: #Many platforms seem to have a problem with strtod() and NaN: reported on Windows and FreeBSD #object = float('NaN') if object == '': object = 0 else: object = NaN return 1, object CoreBooleanValue = lambda obj: (1, boolean.BooleanValue(obj, StringValue)) g_stringConversions = [CoreStringValue] g_numberConversions = [CoreNumberValue] g_booleanConversions = [CoreBooleanValue] #g_nodeSetConversions = [CoreNodeSetValue] # Conversion functions for converting objects to strings def _strUnknown(object): # Allow for non-instance DOM node objects if hasattr(object, 'nodeType'): # Add this type to the mapping for next time through _strConversions[type(object)] = _strInstance return _strInstance(object) return def _strInstance(object): if hasattr(object, 'stringValue'): return object.stringValue if hasattr(object, 'nodeType'): node_type = object.nodeType if node_type == Node.ELEMENT_NODE: # The concatenation of all text descendants text_elem_children = filter(lambda x: x.nodeType in [Node.TEXT_NODE, Node.ELEMENT_NODE, Node.CDATA_SECTION_NODE], object.childNodes) return reduce(lambda x, y: CoreStringValue(x)[1] + CoreStringValue(y)[1], text_elem_children, '') if node_type in [Node.ATTRIBUTE_NODE, NAMESPACE_NODE]: return object.value if node_type in [Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE]: return object.data if node_type == Node.DOCUMENT_NODE: # Use the String value of the document root return CoreStringValue(object.documentElement) return None _strConversions = { types.StringType : str, types.IntType : str, types.LongType : lambda l: repr(l)[:-1], types.FloatType : lambda f: f is NaN and 'NaN' or '%g' % f, boolean.BooleanType : str, types.InstanceType : _strInstance, types.ListType : lambda x: x and _strConversions.get(type(x[0]), _strUnknown)(x[0]) or '', } if hasattr(types, 'UnicodeType'): _strConversions[types.UnicodeType] = unicode try: from Ft.Lib import cDomlettec def _strElementInstance(object): if hasattr(object, 'stringValue'): return object.stringValue if object.nodeType == Node.ELEMENT_NODE: # The concatenation of all text descendants text_elem_children = filter( lambda x: x.nodeType in [Node.TEXT_NODE, Node.ELEMENT_NODE, Node.CDATA_SECTION_NODE], object.childNodes ) return reduce(lambda x, y: CoreStringValue(x)[1] + CoreStringValue(y)[1], text_elem_children, '') _strConversions.update({ cDomlettec.DocumentType : lambda x: _strElementInstance(x.documentElement), cDomlettec.ElementType : _strElementInstance, cDomlettec.TextType : lambda x: x.data, cDomlettec.CommentType : lambda x: x.data, cDomlettec.ProcessingInstructionType : lambda x: x.data, cDomlettec.AttrType : lambda x: x.value, }) except ImportError: pass PyXML-0.8.2/xml/xpath/CoreFunctions.py0100644000076400001440000002635307377133277017020 0ustar martinusers######################################################################## # # File Name: CoreFunctions.py # # Docs: http://docs.4suite.org/XPATH/CoreFunctions.py.html # """ The implementation of all of the core functions for the XPath spec. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import string, cStringIO from xml.dom import Node,EMPTY_NAMESPACE from xml.xpath import ExpandedNameWrapper from xml.xpath import NamespaceNode from xml.xpath import NaN, Inf from xml.xpath import Util, Conversions from xml.xpath import NAMESPACE_NODE from xml.xpath import CompiletimeException, RuntimeException from xml.utils import boolean try: import os, gettext locale_dir = os.path.split(__file__)[0] gettext.install('4Suite', locale_dir) #except ImportError, IOError: #Note, 1.5.2 has gettext, but no install except (ImportError, AttributeError, IOError): def _(msg): return msg class Types: NumberType = 0 StringType = 1 BooleanType = 2 NodeSetType = 3 ObjectType = 4 import types try: g_stringTypes = [types.StringType, types.UnicodeType] except: g_stringTypes = [types.StringType] ### Node Set Functions ### def Last(context): """Function: last()""" return context.size def Position(context): """Function: position()""" return context.position def Count(context, nodeSet): """Function: count()""" if type(nodeSet) != type([]): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'count', _("expected node set argument")) return len(nodeSet) def Id(context, object): """Function: id()""" id_list = [] if type(object) != type([]): st = Conversions.StringValue(object) id_list = string.split(st) else: for n in object: id_list.append(Conversions.StringValue(n)) rt = [] for id in id_list: doc = context.node.ownerDocument or context.node elements = Util.ElementsById(doc.documentElement, id) if len(elements) > 1: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'id', _("argument not unique")) elif elements: # Must be 1 rt.append(elements[0]) return rt def LocalName(context, nodeSet=None): """Function: local-name(?)""" if nodeSet is None: node = context.node else: if type(nodeSet) != type([]): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'local-name', _("expected node set")) nodeSet = Util.SortDocOrder(nodeSet) if type(nodeSet) != type([]) or len(nodeSet) == 0: return '' node = nodeSet[0] en = ExpandedName(node) if en == None or en.localName == None: return '' return en.localName def NamespaceUri(context, nodeSet=None): """Function: namespace-uri(?)""" if nodeSet is None: node = context.node else: if type(nodeSet) != type([]): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'namespace-uri', _("expected node set")) nodeSet = Util.SortDocOrder(nodeSet) if type(nodeSet) != type([]) or len(nodeSet) == 0: return '' node = nodeSet[0] en = ExpandedName(node) if en == None or en.namespaceURI == None: return '' return en.namespaceURI def Name(context, nodeSet=None): """Function: name(?)""" if nodeSet is None: node = context.node else: if type(nodeSet) != type([]): raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'name', _("expected node set")) nodeSet = Util.SortDocOrder(nodeSet) if type(nodeSet) != type([]) or len(nodeSet) == 0: return '' node = nodeSet[0] en = ExpandedName(node) if en == None: return '' return en.qName ### String Functions ### def String(context, object=None): """Function: string(?)""" if type(object) in g_stringTypes: return object if object is None: object = [context.node] return Conversions.StringValue(object) def Concat(context, *args): """Function: concat(, , ...)""" if len(args) < 1: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'concat', _("at least 2 arguments expected")) return reduce(lambda a,b,c=context: a + Conversions.StringValue(b), args, '') def StartsWith(context, outer, inner): """Function: starts-with(, )""" outer = Conversions.StringValue(outer) inner = Conversions.StringValue(inner) return outer[:len(inner)] == inner and boolean.true or boolean.false def Contains(context, outer, inner): """Function: contains(, )""" outer = Conversions.StringValue(outer) inner = Conversions.StringValue(inner) if len(inner) == 1: return inner in outer and boolean.true or boolean.false else: return string.find(outer, inner) != -1 and boolean.true or boolean.false def SubstringBefore(context, outer, inner): """Function: substring-before(, )""" outer = Conversions.StringValue(outer) inner = Conversions.StringValue(inner) index = string.find(outer, inner) if index == -1: return '' return outer[:index] def SubstringAfter(context, outer, inner): """Function: substring-after(, )""" outer = Conversions.StringValue(outer) inner = Conversions.StringValue(inner) index = string.find(outer, inner) if index == -1: return '' return outer[index+len(inner):] def Substring(context, st, start, end=None): """Function: substring(, , ?)""" st = Conversions.StringValue(st) start = Conversions.NumberValue(start) if start is NaN: return '' start = int(round(start)) start = start > 1 and start - 1 or 0 if end is None: return st[start:] end = Conversions.NumberValue(end) if start is NaN: return st[start:] end = int(round(end)) return st[start:start+end] def StringLength(context, st=None): """Function: string-length(?)""" if st is None: st = context.node return len(Conversions.StringValue(st)) def Normalize(context, st=None): """Function: normalize-space(?)""" if st is None: st = context.node st = Conversions.StringValue(st) return string.join(string.split(st)) def Translate(context, source, fromChars, toChars): """Function: translate(, , )""" source = Conversions.StringValue(source) fromChars = Conversions.StringValue(fromChars) toChars = Conversions.StringValue(toChars) # string.maketrans/translate do not handle unicode translate = {} for from_char, to_char in map(None, fromChars, toChars): translate[ord(from_char)] = to_char result = reduce(lambda a, b, t=translate: a + (t.get(ord(b), b) or ''), source, '') return result ### Boolean Functions ### def _Boolean(context, object): """Function: boolean()""" return Conversions.BooleanValue(object) def Not(context, object): """Function: not()""" return (not Conversions.BooleanValue(object) and boolean.true) or boolean.false def True(context): """Function: true()""" return boolean.true def False(context): """Function: false()""" return boolean.false def Lang(context, lang): """Function: lang()""" lang = string.upper(Conversions.StringValue(lang)) node = context.node while node: lang_attr = filter(lambda x:x.name == 'xml:lang' and x.value, node.attributes.values()) value = lang_attr and lang_attr[0].nodeValue or None if value: # See if there is a suffix index = string.find(value, '-') if index != -1: value = value[:index] value = string.upper(value) return value == lang and boolean.true or boolean.false node = node.nodeType == Node.ATTRIBUTE_NODE and node.ownerElement or node.parentNode return boolean.false ### Number Functions ### def Number(context, object=None): """Function: number(?)""" if object is None: object = [context.node] return Conversions.NumberValue(object) def Sum(context, nodeSet): """Function: sum()""" nns = map(lambda x: Conversions.NumberValue(x), nodeSet) return reduce(lambda x,y: x+y, nns, 0) def Floor(context, number): """Function: floor()""" number = Conversions.NumberValue(number) #if type(number) in g_stringTypes: # number = string.atof(number) if int(number) == number: return number elif number < 0: return int(number) - 1 else: return int(number) def Ceiling(context, number): """Function: ceiling()""" number = Conversions.NumberValue(number) #if type(number) in g_stringTypes: # number = string.atof(number) if int(number) == number: return number elif number > 0: return int(number) + 1 else: return int(number) def Round(context, number): """Function: round()""" number = Conversions.NumberValue(number) return round(number, 0) ### Helper Functions ### def ExpandedName(node): """Get the expanded name of any object""" if hasattr(node, 'nodeType') and node.nodeType in [Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.ATTRIBUTE_NODE, NAMESPACE_NODE]: return ExpandedNameWrapper.ExpandedNameWrapper(node) return None ### Function Mappings ### CoreFunctions = { (EMPTY_NAMESPACE, 'last'): Last, (EMPTY_NAMESPACE, 'position'): Position, (EMPTY_NAMESPACE, 'count'): Count, (EMPTY_NAMESPACE, 'id'): Id, (EMPTY_NAMESPACE, 'local-name'): LocalName, (EMPTY_NAMESPACE, 'namespace-uri'): NamespaceUri, (EMPTY_NAMESPACE, 'name'): Name, (EMPTY_NAMESPACE, 'string'): String, (EMPTY_NAMESPACE, 'concat'): Concat, (EMPTY_NAMESPACE, 'starts-with'): StartsWith, (EMPTY_NAMESPACE, 'contains'): Contains, (EMPTY_NAMESPACE, 'substring-before'): SubstringBefore, (EMPTY_NAMESPACE, 'substring-after'): SubstringAfter, (EMPTY_NAMESPACE, 'substring'): Substring, (EMPTY_NAMESPACE, 'string-length'): StringLength, (EMPTY_NAMESPACE, 'normalize-space'): Normalize, (EMPTY_NAMESPACE, 'translate'): Translate, (EMPTY_NAMESPACE, 'boolean'): _Boolean, (EMPTY_NAMESPACE, 'not'): Not, (EMPTY_NAMESPACE, 'true'): True, (EMPTY_NAMESPACE, 'false'): False, (EMPTY_NAMESPACE, 'lang'): Lang, (EMPTY_NAMESPACE, 'number'): Number, (EMPTY_NAMESPACE, 'sum'): Sum, (EMPTY_NAMESPACE, 'floor'): Floor, (EMPTY_NAMESPACE, 'ceiling'): Ceiling, (EMPTY_NAMESPACE, 'round'): Round, (EMPTY_NAMESPACE, 'expanded-name'): ExpandedName } Args = { Substring : (Types.StringType, [Types.StringType, Types.StringType]), } PyXML-0.8.2/xml/xpath/ExpandedNameWrapper.py0100644000076400001440000000231707377133277020123 0ustar martinusers######################################################################## # # File Name: ExpandedNameWrapper.py # # Docs: http://docs.4suite.org/XPATH/ExpandedNameWrapper.py.html # """ A structure to hold a node's expanded name. Internal use only. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.dom import Node,EMPTY_NAMESPACE from xml.xpath import NAMESPACE_NODE from xml.xpath import NamespaceNode class ExpandedNameWrapper: def __init__(self, node): self.namespaceURI = EMPTY_NAMESPACE self.localName = '' self.qName = '' if hasattr(node, 'nodeType'): if node.nodeType in [Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE]: self.namespaceURI = node.namespaceURI self.localName = node.localName self.qName = node.nodeName elif node.nodeType == NAMESPACE_NODE: self.qName = self.localName = node.localName elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: self.qName = self.localName = node.target PyXML-0.8.2/xml/xpath/MessageSource.py0100644000076400001440000000225407356637352016776 0ustar martinusersfrom xml.xpath import RuntimeException, CompiletimeException try: import os, gettext locale_dir = os.path.split(__file__)[0] gettext.install('4Suite', locale_dir) #except ImportError, IOError: #Note, 1.5.2 has gettext, but no install except (ImportError, AttributeError, IOError): def _(msg): return msg COMPILETIME = { CompiletimeException.INTERNAL: _('There is an internal bug in 4XPath. Please report this error code to support@4suite.org: %s'), CompiletimeException.SYNTAX: _('Parse error at line %d, column %d: %s'), CompiletimeException.PROCESSING: _('Error evaluating expression.'), #CompiletimeException.: _(''), } RUNTIME = { RuntimeException.INTERNAL: _('There is an internal bug in 4XPath. Please report this error code to support@4suite.org: %s'), RuntimeException.NO_CONTEXT: _('An XPath Context object is required in order to evaluate an expression.'), RuntimeException.UNDEFINED_VARIABLE: _('Variable undefined: ("%s", "%s").'), RuntimeException.UNDEFINED_PREFIX: _('Undefined namespace prefix: "%s".'), RuntimeException.WRONG_ARGUMENTS: _('Error in arguments to %s: %s'), #RuntimeException.: _(''), } PyXML-0.8.2/xml/xpath/NamespaceNode.py0100644000076400001440000000147207377133277016734 0ustar martinusers######################################################################## # # File Name: NamespaceNode.py # # Docs: http://docs.4suite.org/XPATH/NamespaceNode.py.py.html # """ A container class for the namespace axis results. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE from xml.xpath import NAMESPACE_NODE class NamespaceNode: def __init__(self, prefix, uri, ownerDoc=None): self.prefix = '' self.nodeName = self.localName = prefix self.namespaceURI = EMPTY_NAMESPACE self.value = uri self.nodeType = NAMESPACE_NODE self.ownerDocument = ownerDoc return PyXML-0.8.2/xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py0100644000076400001440000000413107356637352023601 0ustar martinusers######################################################################## # # File Name: ParsedAbbreviatedAbsoluteLocationPath.py # # Docs: http://docs.4suite.org/XPATH/ParsedAbbreviatedAbsoluteLocationPath.py.html # """ A parsed token for an abreviated absolute location path. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.xpath import ParsedNodeTest from xml.xpath import ParsedPredicateList from xml.xpath import ParsedStep from xml.xpath import ParsedAxisSpecifier LOOKAHEAD_OPTIMIZERS = { } class ParsedAbbreviatedAbsoluteLocationPath: def __init__(self,rel): self._rel = rel nt = ParsedNodeTest.ParsedNodeTest('node', '') ppl = ParsedPredicateList.ParsedPredicateList([]) as = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') self._step = ParsedStep.ParsedStep(as, nt, ppl) return def evaluate(self, context): origState = context.copyNodePosSize() root = context.node.ownerDocument or context.node context.setNodePosSize((root,1,1)) rt = self._step.select(context) res = [] l = len(rt) sub_rt = [] for ctr in range(l): n = rt[ctr] context.setNodePosSize((n,ctr+1,l)) sub_rt.extend(self._rel.select(context)) if sub_rt and hasattr(sub_rt[0], 'ownerElement'): result = sub_rt else: result = filter(lambda x, compare=sub_rt: x in compare, rt) context.setNodePosSize(origState) return result select = evaluate def pprint(self, indent=''): print indent + str(self) self._step.pprint(indent + ' ') self._rel.pprint(indent + ' ') def __str__(self): return '' % ( id(self), repr(self) ) def __repr__(self): return '/%s/%s' % (repr(self._step), repr(self._rel)) PyXML-0.8.2/xml/xpath/ParsedAbbreviatedRelativeLocationPath.py0100644000076400001440000000426307356637352023604 0ustar martinusers######################################################################## # # File Name: ParsedAbbreviatedRelativeLocationPath.py # # Docs: http://docs.4suite.org/XPATH/ParsedAbbreviatedRelativeLocationPath.py.html # """ A parsed token that represents a abbreviated relative location path. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.xpath import ParsedNodeTest from xml.xpath import ParsedPredicateList from xml.xpath import ParsedAxisSpecifier from xml.xpath import ParsedStep import Set class ParsedAbbreviatedRelativeLocationPath: def __init__(self,left,right): """ left can be a step or a relative location path right is only a step """ self._left = left self._right = right nt = ParsedNodeTest.ParsedNodeTest('node','') ppl = ParsedPredicateList.ParsedPredicateList([]) as = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') self._middle = ParsedStep.ParsedStep(as, nt, ppl) def evaluate(self, context): res = [] rt = self._left.select(context) l = len(rt) origState = context.copyNodePosSize() for ctr in range(l): context.setNodePosSize((rt[ctr],ctr+1,l)) subRt = self._middle.select(context) res = Set.Union(res,subRt) rt = res res = [] l = len(rt) for ctr in range(l): context.setNodePosSize((rt[ctr],ctr+1,l)) subRt = self._right.select(context) res = Set.Union(res,subRt) context.setNodePosSize(origState) return res select = evaluate def pprint(self, indent=''): print indent + str(self) self._left.pprint(indent + ' ') self._middle.pprint(indent + ' ') self._right.pprint(indent + ' ') def __str__(self): return '' % ( id(self), repr(self), ) def __repr__(self): return repr(self._left) + '//' + repr(self._right) PyXML-0.8.2/xml/xpath/ParsedAbsoluteLocationPath.py0100644000076400001440000000243307356637352021453 0ustar martinusers######################################################################## # # File Name: ParsedAbsoluteLocationPath.py # # Docs: http://docs.4suite.org/XPATH/ParsedAbsoluteLocationPath.py.html # """ A Parsed Token that represents a absolute location path in the parsed tree. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ class ParsedAbsoluteLocationPath: def __init__(self, child): self._child = child def evaluate(self, context): root = context.node.ownerDocument or context.node if self._child is None: return [root] origState = context.copyNodePosSize() context.setNodePosSize((root,1,1)) rt = self._child.select(context) context.setNodePosSize(origState) return rt select = evaluate def pprint(self, indent=''): print indent + str(self) self._child and self._child.pprint(indent + ' ') def __str__(self): return '' % ( id(self), repr(self), ) def __repr__(self): return '/' + (self._child and repr(self._child) or '') PyXML-0.8.2/xml/xpath/ParsedAxisSpecifier.py0100644000076400001440000002170007356637352020123 0ustar martinusers######################################################################## # # File Name: ParsedAxisSpecifier.py # # Docs: http://docs.4suite.org/XPATH/ParsedAxisSpecifier.py.html # """ A Parsed token that represents an acis specifier on the parsed tree. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.dom import Node from xml.xpath import g_xpathRecognizedNodes from xml.xpath import NAMESPACE_NODE from xml.xpath import Util from xml.xpath import NamespaceNode from xml.dom.ext import GetAllNs import string def ParsedAxisSpecifier(axis): try: return g_classMap[axis](axis) except KeyError: raise SyntaxError("Invalid axis: %s" % axis) class AxisSpecifier: principalType = Node.ELEMENT_NODE def __init__(self, axis): self._axis = axis def select(self, context, nodeTest): """ Always returns a tuple of node-set and 0 if forward, 1 if reverse. """ return ([], 0) def descendants(self, context, nodeTest, node, nodeSet): """Select all of the descendants from the context node""" for child in node.childNodes: if nodeTest(context, child, self.principalType): nodeSet.append(child) if child.childNodes: self.descendants(context, nodeTest, child, nodeSet) return (nodeSet, 0) def pprint(self, indent=''): print indent + str(self) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): """Always displays verbose expression""" return self._axis class ParsedAncestorAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the ancestors including the root""" nodeSet = [] parent = ((context.node.nodeType == Node.ATTRIBUTE_NODE) and context.node.ownerElement or context.node.parentNode) while parent: if nodeTest(context, parent, self.principalType): nodeSet.append(parent) parent = parent.parentNode nodeSet.reverse() return (nodeSet, 1) class ParsedAncestorOrSelfAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the ancestors including ourselves through the root""" node = context.node if nodeTest(context, node, self.principalType): nodeSet = [node] else: nodeSet = [] parent = ((node.nodeType == Node.ATTRIBUTE_NODE) and node.ownerElement or node.parentNode) while parent: if nodeTest(context, parent, self.principalType): nodeSet.append(parent) parent = parent.parentNode nodeSet.reverse() return (nodeSet, 1) class ParsedAttributeAxisSpecifier(AxisSpecifier): principalType = Node.ATTRIBUTE_NODE def select(self, context, nodeTest): """Select all of the attributes from the context node""" attrs = context.node.attributes rt = filter(lambda attr, test=nodeTest, context=context, pt=self.principalType: test(context, attr, pt), attrs and attrs.values() or []) return (rt, 0) class ParsedChildAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the children of the context node""" rt = filter(lambda node, test=nodeTest, context=context, pt=self.principalType: test(context, node, pt), context.node.childNodes) return (rt, 0) class ParsedDescendantOrSelfAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select the context node and all of its descendants""" if nodeTest(context, context.node, self.principalType): nodeSet = [context.node] else: nodeSet = [] self.descendants(context, nodeTest, context.node, nodeSet) return (nodeSet, 0) class ParsedDescendantAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): nodeSet = [] self.descendants(context, nodeTest, context.node, nodeSet) return (nodeSet, 0) class ParsedFollowingSiblingAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the siblings that follow the context node""" result = [] sibling = context.node.nextSibling while sibling: if nodeTest(context, sibling, self.principalType): result.append(sibling) sibling = sibling.nextSibling return (result, 0) class ParsedFollowingAxisSpecifier(AxisSpecifier): def select(self,context, nodeTest): """ Select all of the nodes the follow the context node, not including descendants. """ result = [] curr = context.node while curr != (context.node.ownerDocument or context.node): sibling = curr.nextSibling while sibling: if nodeTest(context, sibling, self.principalType): result.append(sibling) self.descendants(context, nodeTest, sibling, result) sibling = sibling.nextSibling curr = ((curr.nodeType == Node.ATTRIBUTE_NODE) and curr.ownerElement or curr.parentNode) return (result, 0) class ParsedNamespaceAxisSpecifier(AxisSpecifier): principalType = NAMESPACE_NODE def select(self, context, nodeTest): """Select all of the namespaces from the context""" if context.node.nodeType != Node.ELEMENT_NODE: return ([], 0) result = [] #nss = context.nss() nss = GetAllNs(context.node) for prefix in nss.keys(): nsNode = NamespaceNode.NamespaceNode( prefix, nss[prefix], (context.node.ownerDocument or context.node) ) if nodeTest(context, nsNode, self.principalType): result.append(nsNode) return (result, 0) class ParsedParentAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select the parent of the context node""" parent = ((context.node.nodeType == Node.ATTRIBUTE_NODE) and context.node.ownerElement or context.node.parentNode) if parent and nodeTest(context, parent, self.principalType): result = [parent] else: result = [] return (result, 1) class ParsedPrecedingSiblingAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the siblings that precede the context node""" result = [] sibling = context.node.previousSibling while sibling: if nodeTest(context, sibling, self.principalType): result.append(sibling) sibling = sibling.previousSibling # Put the list in document order result.reverse() return (result, 1) class ParsedPrecedingAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the nodes the precede the context node, not including ancestors""" # Create a list of lists of descendants of the nodes # that precede the context node. (reverse doc order) doc_list = [] curr = context.node while curr: sib = curr.previousSibling while sib: result = [] if nodeTest(context, sib, self.principalType): result = [sib] self.descendants(context, nodeTest, sib, result) doc_list.append(result) sib = sib.previousSibling curr = curr.nodeType == Node.ATTRIBUTE_NODE and curr.ownerElement or curr.parentNode # Create a single list in document order result = [] for i in range(1, len(doc_list)+1): result.extend(doc_list[-i]) return (result, 1) class ParsedSelfAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select the context node""" if nodeTest(context, context.node, self.principalType): return ([context.node], 0) return ([], 0) g_classMap = { 'ancestor' : ParsedAncestorAxisSpecifier, 'ancestor-or-self' : ParsedAncestorOrSelfAxisSpecifier, 'child' : ParsedChildAxisSpecifier, 'parent' : ParsedParentAxisSpecifier, 'descendant' : ParsedDescendantAxisSpecifier, 'descendant-or-self' : ParsedDescendantOrSelfAxisSpecifier, 'attribute' : ParsedAttributeAxisSpecifier, 'following' : ParsedFollowingAxisSpecifier, 'following-sibling' : ParsedFollowingSiblingAxisSpecifier, 'preceding' : ParsedPrecedingAxisSpecifier, 'preceding-sibling' : ParsedPrecedingSiblingAxisSpecifier, 'namespace' : ParsedNamespaceAxisSpecifier, 'self' : ParsedSelfAxisSpecifier, } PyXML-0.8.2/xml/xpath/ParsedExpr.py0100644000076400001440000005174607377133277016320 0ustar martinusers######################################################################## # # File Name: ParsedExpr.py # # Docs: http://docs.4suite.org/XPATH/ParsedExpr.py.html # """ The implementation of all of the expression pared tokens. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import string, UserList, types from xml.dom import EMPTY_NAMESPACE from xml.dom.ext import SplitQName from xml.xpath import CompiletimeException, RuntimeException from xml.xpath import g_extFunctions from xml.xpath import ParsedNodeTest from xml.xpath import CoreFunctions, Conversions from xml.xpath import Util from xml.xpath import ParsedStep from xml.xpath import ParsedAxisSpecifier from xml.utils import boolean import Set class NodeSet(UserList.UserList): def __init__(self, data=None): UserList.UserList.__init__(self, data or []) def __repr__(self): st = '' return st class ParsedLiteralExpr: def __init__(self,literal): if len(literal) >= 2 and ( literal[0] in ['\'', '"'] and literal[0] == literal[-1]): literal = string.strip(literal)[1:-1] self._literal = literal def evaluate(self, context): return self._literal def pprint(self, indent=''): print indent + str(self) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return '"' + self._literal + '"' class ParsedNLiteralExpr(ParsedLiteralExpr): def __init__(self,nliteral): ParsedLiteralExpr.__init__(self,"") self._nliteral = nliteral self._literal = float(nliteral) def pprint(self, indent=''): print indent + str(self) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return str(self._nliteral) class ParsedVariableReferenceExpr: def __init__(self,name): self._name = name self._key = SplitQName(name[1:]) return def evaluate(self, context): """Returns a string""" (prefix, local) = self._key uri = context.processorNss.get(prefix) if prefix and not uri: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) expanded = (prefix and uri or EMPTY_NAMESPACE, local) try: return context.varBindings[expanded] except: raise RuntimeException(RuntimeException.UNDEFINED_VARIABLE, expanded[0], expanded[1]) def pprint(self, indent=''): print indent + str(self) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return self._name def ParsedFunctionCallExpr(name, args): name = string.strip(name) key = SplitQName(name) count = len(args) if count == 0: return FunctionCall(name, key, args) if count == 1: return FunctionCall1(name, key, args) if count == 2: return FunctionCall2(name, key, args) if count == 3: return FunctionCall3(name, key, args) return FunctionCallN(name, key, args) class FunctionCall: def __init__(self, name, key, args): self._name = name self._key = key self._args = args self._func = None def pprint(self, indent=''): print indent + str(self) for arg in self._args: arg.pprint(indent + ' ') def error(self, *args): raise Exception('Unknown function call: %s' % self._name) def evaluate(self, context): """Call the function""" if not self._func: (prefix, local) = self._key uri = context.processorNss.get(prefix) if prefix and not uri: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) expanded = (prefix and uri or EMPTY_NAMESPACE, local) self._func = (g_extFunctions.get(expanded) or CoreFunctions.CoreFunctions.get(expanded, self.error)) try: result = self._func(context) except TypeError: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, str(expanded), '') return result def __getinitargs__(self): return (self._name, self._key, self._args) def __getstate__(self): state = vars(self).copy() del state['_func'] return state def __str__(self): return '<%s at %x: %s>' % (self.__class__.__name__, id(self), repr(self)) def __repr__(self): result = self._name + '(' if len(self._args): result = result + repr(self._args[0]) for arg in self._args[1:]: result = result + ', ' + repr(arg) return result + ')' class FunctionCall1(FunctionCall): def __init__(self, name, key, args): FunctionCall.__init__(self, name, key, args) self._arg0 = args[0] def evaluate(self, context): arg0 = self._arg0.evaluate(context) if not self._func: (prefix, local) = self._key uri = context.processorNss.get(prefix) if prefix and not uri: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) expanded = (prefix and uri or EMPTY_NAMESPACE, local) self._func = (g_extFunctions.get(expanded) or CoreFunctions.CoreFunctions.get(expanded, self.error)) try: result = self._func(context, arg0) except TypeError: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, str(expanded), '') return result class FunctionCall2(FunctionCall): def __init__(self, name, key, args): FunctionCall.__init__(self, name, key, args) self._arg0 = args[0] self._arg1 = args[1] def evaluate(self, context): arg0 = self._arg0.evaluate(context) arg1 = self._arg1.evaluate(context) if not self._func: (prefix, local) = self._key uri = context.processorNss.get(prefix) if prefix and not uri: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) expanded = (prefix and uri or EMPTY_NAMESPACE, local) self._func = (g_extFunctions.get(expanded) or CoreFunctions.CoreFunctions.get(expanded, self.error)) try: result = self._func(context, arg0, arg1) except TypeError: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, str(expanded), '') return result class FunctionCall3(FunctionCall): def __init__(self, name, key, args): FunctionCall.__init__(self, name, key, args) self._arg0 = args[0] self._arg1 = args[1] self._arg2 = args[2] def evaluate(self, context): arg0 = self._arg0.evaluate(context) arg1 = self._arg1.evaluate(context) arg2 = self._arg2.evaluate(context) if not self._func: (prefix, local) = self._key uri = context.processorNss.get(prefix) if prefix and not uri: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) expanded = (prefix and uri or EMPTY_NAMESPACE, local) self._func = (g_extFunctions.get(expanded) or CoreFunctions.CoreFunctions.get(expanded, self.error)) try: result = self._func(context, arg0, arg1, arg2) except TypeError: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, str(expanded), '') return result class FunctionCallN(FunctionCall): def __init__(self, name, key, args): FunctionCall.__init__(self, name, key, args) def evaluate(self, context): args = [context] + map(lambda x, c=context: x.evaluate(c), self._args) if not self._func: (prefix, local) = self._key uri = context.processorNss.get(prefix) if prefix and not uri: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) expanded = (prefix and uri or EMPTY_NAMESPACE, local) self._func = (g_extFunctions.get(expanded) or CoreFunctions.CoreFunctions.get(expanded, self.error)) try: result = apply(self._func, args) except TypeError: raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, str(expanded), '') return result #Node Set Expressions #These must return a node set class ParsedUnionExpr: def __init__(self,left,right): self._left = left self._right = right def pprint(self, indent=''): print indent + str(self) self._left.pprint(indent + ' ') self._right.pprint(indent + ' ') def evaluate(self, context): lSet = self._left.evaluate(context) if type(lSet) != type([]): raise "Left Expression does not evaluate to a node set" rSet = self._right.evaluate(context) if type(rSet) != type([]): raise "Right Expression does not evaluate to a node set" set = Set.Union(lSet, rSet) set = Util.SortDocOrder(set) return set def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return repr(self._left) + ' | ' + repr(self._right) class ParsedPathExpr: def __init__(self, descendant, left, right): self._left = left self._right = right if descendant: nt = ParsedNodeTest.ParsedNodeTest('node', '') axis = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') from xml.xpath import ParsedPredicateList pList = ParsedPredicateList.ParsedPredicateList([]) self._step = ParsedStep.ParsedStep(axis, nt, pList) else: self._step = None def pprint(self, indent=''): print indent + str(self) self._left.pprint(indent + ' ') self._right.pprint(indent + ' ') def evaluate(self, context): """Evaluate the left, then if op =// the parsedStep, then the right, push context each time""" """Returns a node set""" rt = self._left.evaluate(context) if type(rt) != type([]): raise "Invalid Expression for a PathExpr %s" % str(self._left) origState = context.copyNodePosSize() if self._step: res = [] l = len(rt) for ctr in range(l): r = rt[ctr] context.setNodePosSize((r,ctr+1,l)) subRt = self._step.select(context) res = Set.Union(res,subRt) rt = res res = [] l = len(rt) for ctr in range(l): r = rt[ctr] context.setNodePosSize((r,ctr+1,l)) subRt = self._right.select(context) if type(subRt) != type([]): raise Exception("Right Expression does not evaluate to a Node Set") res = Set.Union(res,subRt) context.setNodePosSize(origState) return res def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): op = self._step and '//' or '/' return repr(self._left) + op + repr(self._right) class ParsedFilterExpr: def __init__(self, filter, predicates): self._filter = filter self._predicates = predicates def evaluate(self, context): """ evaluate(context) -> node-set Evaluate our filter into a node set, filter that through the predicates. """ node_set = self._filter.evaluate(context) if type(node_set) != type([]): raise "ParsedFilterExpr: return value must evalute to a node-set" if node_set: node_set = self._predicates.filter(node_set, context, reverse=0) return node_set def pprint(self, indent=''): print indent + str(self) self._filter.pprint(indent + ' ') self._predicates.pprint(indent + ' ') def shiftContext(self,context,index,set,len,func): return func(context) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return repr(self._filter) + repr(self._predicates) #Boolean Expressions #All will return a boolean value class ParsedOrExpr: def __init__(self, left, right): self._left = left self._right = right def pprint(self, indent=''): print indent + str(self) self._left.pprint(indent + ' ') self._right.pprint(indent + ' ') def evaluate(self, context): rt = Conversions.BooleanEvaluate(self._left, context) if not rt: rt = Conversions.BooleanEvaluate(self._right, context) return rt def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return repr(self._left) +' or ' + repr(self._right) class ParsedAndExpr: def __init__(self,left,right): self._left = left self._right = right def evaluate(self, context): rt = Conversions.BooleanEvaluate(self._left, context) if rt: rt = Conversions.BooleanEvaluate(self._right, context) return rt def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return repr(self._left) + ' and ' + repr(self._right) NumberTypes = [types.IntType, types.FloatType, types.LongType] class ParsedEqualityExpr: def __init__(self, op, left, right): self._op = op self._left = left self._right = right def evaluate(self, context): if self._op == '=': true = boolean.true false = boolean.false else: true = boolean.false false = boolean.true lrt = self._left.evaluate(context) rrt = self._right.evaluate(context) lType = type(lrt) rType = type(rrt) if lType == types.ListType == rType: #Node set to node set for right_curr in rrt: right_curr = Conversions.StringValue(right_curr) for left_curr in lrt: if right_curr == Conversions.StringValue(left_curr): return true return false elif lType == types.ListType or rType == types.ListType: func = None if lType == types.ListType: set = lrt val = rrt else: set = rrt val = lrt if type(val) in NumberTypes: func = Conversions.NumberValue elif boolean.IsBooleanType(val): func = Conversions.BooleanValue elif type(val) == types.StringType: func = Conversions.StringValue else: #Deal with e.g. RTFs val = Conversions.StringValue(val) func = Conversions.StringValue for n in set: if func(n) == val: return true return false if boolean.IsBooleanType(lrt) or boolean.IsBooleanType(rrt): rt = Conversions.BooleanValue(lrt) == Conversions.BooleanValue(rrt) elif lType in NumberTypes or rType in NumberTypes: rt = Conversions.NumberValue(lrt) == Conversions.NumberValue(rrt) else: rt = Conversions.StringValue(lrt) == Conversions.StringValue(rrt) if rt: # Due to the swapping of true/false, true might evaluate to 0 # We cannot compact this to 'rt and true or false' return true return false def pprint(self, indent=''): print indent + str(self) self._left.pprint(indent + ' ') self._right.pprint(indent + ' ') def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): if self._op == '=': op = ' = ' else: op = ' != ' return repr(self._left) + op + repr(self._right) class ParsedRelationalExpr: def __init__(self, opcode, left, right): self._op = opcode if isinstance(left, ParsedLiteralExpr): self._left = Conversions.NumberValue(left.evaluate(None)) self._leftLit = 1 else: self._left = left self._leftLit = 0 if isinstance(right, ParsedLiteralExpr): self._right = Conversions.NumberValue(right.evaluate(None)) self._rightLit = 1 else: self._right = right self._rightLit = 0 def evaluate(self, context): if self._leftLit: lrt = self._left else: lrt = Conversions.NumberValue(self._left.evaluate(context)) if self._rightLit: rrt = self._right else: rrt = Conversions.NumberValue(self._right.evaluate(context)) if self._op == 0: rt = (lrt < rrt) elif self._op == 1: rt = (lrt <= rrt) elif self._op == 2: rt = (lrt > rrt) elif self._op == 3: rt = (lrt >= rrt) return rt and boolean.true or boolean.false def pprint(self, indent=''): print indent + str(self) if type(self._left) == types.InstanceType: self._left.pprint(indent + ' ') else: print indent + ' ' + '' % str(self._left) if type(self._right) == types.InstanceType: self._right.pprint(indent + ' ') else: print indent + ' ' + '' % str(self._right) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): if self._op == 0: op = ' < ' elif self._op == 1: op = ' <= ' elif self._op == 2: op = ' > ' elif self._op == 3: op = ' >= ' return repr(self._left) + op + repr(self._right) #Number Expressions class ParsedAdditiveExpr: def __init__(self, sign, left, right): self._sign = sign self._leftLit = 0 self._rightLit = 0 if isinstance(left, ParsedLiteralExpr): self._leftLit = 1 self._left = Conversions.NumberValue(left.evaluate(None)) else: self._left = left if isinstance(right, ParsedLiteralExpr): self._rightLit = 1 self._right = Conversions.NumberValue(right.evaluate(None)) else: self._right = right return def evaluate(self, context): '''returns a number''' if self._leftLit: lrt = self._left else: lrt = self._left.evaluate(context) lrt = Conversions.NumberValue(lrt) if self._rightLit: rrt = self._right else: rrt = self._right.evaluate(context) rrt = Conversions.NumberValue(rrt) return lrt + (rrt * self._sign) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): if self._sign > 0: op = ' + ' else: op = ' - ' return repr(self._left) + op + repr(self._right) from xml.xpath import Inf, NaN class ParsedMultiplicativeExpr: def __init__(self, opcode, left, right): self._op = opcode self._left = left self._right = right def evaluate(self, context): '''returns a number''' lrt = self._left.evaluate(context) lrt = Conversions.NumberValue(lrt) rrt = self._right.evaluate(context) rrt = Conversions.NumberValue(rrt) res = 0 if self._op == 0: res = lrt * rrt elif self._op == 1: if rrt == 0: res = NaN else: res = lrt / rrt elif self._op == 2: if rrt == 0: res = NaN else: res = lrt % rrt return res def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): if self._op == 0: op = ' * ' elif self._op == 1: op = ' div ' elif self._op == 2: op = ' mod ' return repr(self._left) + op + repr(self._right) class ParsedUnaryExpr: def __init__(self,exp): self._exp = exp def evaluate(self, context): '''returns a number''' exp = self._exp.evaluate(context) exp = Conversions.NumberValue(exp) rt = exp * -1.0 return rt def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return '-' + repr(self._exp) PyXML-0.8.2/xml/xpath/ParsedNodeTest.py0100644000076400001440000001260607377133277017117 0ustar martinusers######################################################################## # # File Name: ParsedNodeTest.py # # Docs: http://docs.4suite.org/XPATH/ParsedNodeTest.py.html # """ A Parsed Token that represents a node test. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import string from xml.dom import Node,EMPTY_NAMESPACE from xml.xpath import NamespaceNode from xml.xpath import NAMESPACE_NODE, RuntimeException from xml.xpath import g_xpathRecognizedNodes def ParsedNameTest(name): if name == '*': return PrincipalTypeTest() index = string.find(name, ':') if name[index:] == ':*': return LocalNameTest(name[:index]) elif index >= 0: return QualifiedNameTest(name[:index], name[index+1:]) return NodeNameTest(name) def ParsedNodeTest(test, literal=None): if literal: if test != 'processing-instruction': raise SyntaxError('Literal only allowed in processing-instruction') return ProcessingInstructionNodeTest(literal) return g_classMap[test]() class NodeTestBase: def match(self, context, node, principalType=Node.ELEMENT_NODE): """ The principalType is discussed in section [2.3 Node Tests] of the XPath 1.0 spec. Only attribute and namespace axes differ from the default of elements. """ return 0 def pprint(self, indent): print indent + str(self) def __str__(self): return '<%s at %x: %s>' % ( self.__class__.__name__, id(self), repr(self), ) class NodeTest(NodeTestBase): def __init__(self): self.priority = -0.5 def match(self, context, node, principalType=Node.ELEMENT_NODE): return node.nodeType in g_xpathRecognizedNodes or isinstance(node,NamespaceNode.NamespaceNode) def __repr__(self): return 'node()' class CommentNodeTest(NodeTestBase): def __init__(self): self.priority = -0.5 def match(self, context, node, principalType=Node.ELEMENT_NODE): return node.nodeType == Node.COMMENT_NODE def __repr__(self): return 'comment()' class TextNodeTest(NodeTestBase): def __init__(self): self.priority = -0.5 def match(self, context, node, principalType=Node.ELEMENT_NODE): return node.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE] def __repr__(self): return 'text()' class ProcessingInstructionNodeTest(NodeTestBase): def __init__(self, target=None): if target: self.priority = 0 if target[0] not in ['"', "'"]: raise SyntaxError("Invalid literal: %s" % target) self.target = target[1:-1] else: self.priority = -0.5 self.target = '' def match(self, context, node, principalType=Node.ELEMENT_NODE): if node.nodeType != Node.PROCESSING_INSTRUCTION_NODE: return 0 if self.target: return self.target == node.target return 1 def __repr__(self): if self.target: target = repr(self.target) else: target = '' return 'processing-instruction(%s)' % target # Name tests class PrincipalTypeTest(NodeTestBase): def __init__(self): self.priority = -0.5 def match(self, context, node, principalType=Node.ELEMENT_NODE): return node.nodeType == principalType def __repr__(self): return '*' class NodeNameTest(NodeTestBase): def __init__(self, nodeName): self.priority = 0 self._nodeName = nodeName def match(self, context, node, principalType=Node.ELEMENT_NODE): if node.nodeType == principalType: return node.nodeName == self._nodeName return 0 def __repr__(self): return self._nodeName class LocalNameTest(NodeTestBase): def __init__(self, prefix): self.priority = -0.25 self._prefix = prefix def match(self, context, node, principalType=Node.ELEMENT_NODE): if node.nodeType != principalType: return 0 try: uri = self._prefix and context.processorNss[self._prefix] or EMPTY_NAMESPACE except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, self._prefix) return node.namespaceURI == uri def __repr__(self): return self._prefix + ':*' class QualifiedNameTest(NodeTestBase): def __init__(self, prefix, localName): self.priority = 0 self._prefix = prefix self._localName = localName def match(self, context, node, principalType=Node.ELEMENT_NODE): if node.nodeType == principalType: if node.localName == self._localName: try: return node.namespaceURI == context.processorNss[self._prefix] except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, self._prefix) return 0 def __repr__(self): return self._prefix + ':' + self._localName g_classMap = { 'node' : NodeTest, 'comment' : CommentNodeTest, 'text' : TextNodeTest, 'processing-instruction' : ProcessingInstructionNodeTest, } PyXML-0.8.2/xml/xpath/ParsedPredicateList.py0100644000076400001440000000477307356637352020134 0ustar martinusers######################################################################## # # File Name: ParsedPredicateList.py # # Docs: http://docs.4suite.org/XPATH/ParsedPredicateList.py.html # """ A Parsed Token that represents a predicate list. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.xpath import Conversions import types NumberTypes = [types.IntType, types.LongType, types.FloatType] class ParsedPredicateList: def __init__(self, preds): if type(preds) == type(()): preds = list(preds) elif not type(preds) == type([]): raise "Invalid Predicates: ",str(preds) self._predicates = preds self._length = len(preds) def append(self,pred): self._predicates.append(pred) self._length = self._length + 1 def filter(self, nodeList, context, reverse): if self._length: state = context.copyNodePosSize() for pred in self._predicates: size = len(nodeList) ctr = 0 current = nodeList nodeList = [] for node in current: position = (reverse and size - ctr) or (ctr + 1) context.setNodePosSize((node, position, size)) res = pred.evaluate(context) if type(res) in NumberTypes: # This must be separate to prevent falling into # the boolean check. if res == position: nodeList.append(node) elif Conversions.BooleanValue(res): nodeList.append(node) ctr = ctr + 1 context.setNodePosSize(state) return nodeList def __getitem__(self, index): return self._predicates[index] def __len__(self): return self._length def pprint(self, indent=''): print indent + str(self) for pred in self._predicates: pred.pprint(indent + ' ') def __str__(self): return '' % ( id(self), repr(self) or '(empty)', ) def __repr__(self): return reduce(lambda result, pred: result + '[%s]' % repr(pred), self._predicates, '' ) PyXML-0.8.2/xml/xpath/ParsedRelativeLocationPath.py0100644000076400001440000000300707356637352021446 0ustar martinusers######################################################################## # # File Name: ParsedRelativeLocationPath.py # # Docs: http://docs.4suite.org/XPATH/ParsedRelativeLocationPath.py.html # """ A Parsed Token that represents a relative location path in the parsed result tree. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ class ParsedRelativeLocationPath: def __init__(self, left, right): self._left = left self._right = right return def evaluate(self, context): rt = self._left.select(context) if type(rt) != type([]): raise Exception("Expected node set from relative expression. Got %s"%str(rt)) origState = context.copyNodePosSize() result = [] l = len(rt) for ctr in range(l): n = rt[ctr] context.setNodePosSize((n, ctr+1, l)) result.extend(self._right.select(context)) context.setNodePosSize(origState) return result select = evaluate def pprint(self, indent=''): print indent + str(self) self._left.pprint(indent + ' ') self._right.pprint(indent + ' ') def __str__(self): return '' % ( id(self), repr(self), ) def __repr__(self): return repr(self._left) + '/' + repr(self._right) PyXML-0.8.2/xml/xpath/ParsedStep.py0100644000076400001440000000662507356637352016311 0ustar martinusers######################################################################## # # File Name: ParsedStep.py # # Docs: http://docs.4suite.org/XPATH/ParsedStep.py.html # """ A Parsed token that represents a step on the result tree. WWW: http://4suite.org/XPATH e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ from xml.dom import Node from xml.xpath import Util from xml.xpath import NamespaceNode import sys class ParsedStep: def __init__(self, axis, nodeTest, predicates=None): self._axis = axis self._nodeTest = nodeTest self._predicates = predicates return def evaluate(self, context): """ Select a set of nodes from the axis, then filter through the node test and the predicates. """ (node_set, reverse) = self._axis.select(context, self._nodeTest.match) if self._predicates and len(node_set): node_set = self._predicates.filter(node_set, context, reverse) return node_set select = evaluate def pprint(self, indent=''): print indent + str(self) self._axis.pprint(indent + ' ') self._nodeTest.pprint(indent + ' ') self._predicates and self._predicates.pprint(indent + ' ') def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): result = repr(self._axis) + '::' + repr(self._nodeTest) if self._predicates: result = result + repr(self._predicates) return result class ParsedAbbreviatedStep: def __init__(self, parent): self.parent = parent def evaluate(self, context): if self.parent: if context.node.nodeType == Node.ATTRIBUTE_NODE: return [context.node.ownerElement] return context.node.parentNode and [context.node.parentNode] or [] return [context.node] select = evaluate def pprint(self, indent=''): print indent + str(self) def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): return self.parent and '..' or '.' # From the XPath 2.0 Working Draft # Used by XPointer class ParsedNodeSetFunction: def __init__(self, function, predicates=None): self._function = function self._predicates = predicates return def evaluate(self, context): """ Select a set of nodes from the node-set function then filter through the predicates. """ node_set = self._function.evaluate(context) if type(node_set) != type([]): raise SyntaxError('%s does not evaluate to a node-set' % repr(self._function)) if self._predicates and len(node_set): node_set = self._predicates.filter(node_set, context, reverse) return node_set select = evaluate def pprint(self, indent=''): print indent + str(self) self._function.pprint(indent + ' ') self._predicates and self._predicates.pprint(indent + ' ') def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): result = repr(self._function) if self._predicates: result = result + repr(self._predicates) return result PyXML-0.8.2/xml/xpath/Set.py0100644000076400001440000000176207356637352014767 0ustar martinusers######################################################################## # # File Name: Set.py # # Documentation: http://docs.4suite.org/Set.py.html # """ WWW: http://4suite.org/ e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ def Not(original,other): return filter(lambda x,other=other:x not in other,original) def Union(left,right): if len(left) < len(right): loop = left compare = right else: loop = right compare = left return compare + filter(lambda x,compare = compare:x not in compare,loop) def Intersection(left,right): if len(left) < len(right): loop = left compare = right else: loop = right compare = left return filter(lambda x,compare = compare:x in compare,loop) def Unique(left): return reduce(lambda rt,x:x in rt and rt or rt + [x],left,[]) PyXML-0.8.2/xml/xpath/Util.py0100644000076400001440000001366707377133277015160 0ustar martinusers######################################################################## # # File Name: Util.py # # Documentation: http://docs.4suite.org/4XSLT/Util.py.html # """ General Utilities for XPath apps. WWW: http://4suite.org/4XSLT e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import os, glob, string import xml.dom.ext from xml.dom import XML_NAMESPACE,EMPTY_NAMESPACE from xml.dom import Node from xml.dom.NodeFilter import NodeFilter from xml.xpath import g_xpathRecognizedNodes, Compile g_documentOrderIndex = {} g_xmlSpaceDescendant = g_xmlSpaceAncestor = None def ElementsById(element, name): elements = [] attrs = element.attributes idattr = attrs.get((EMPTY_NAMESPACE, 'id')) or attrs.get((EMPTY_NAMESPACE, 'ID')) idattr and idattr.value == name and elements.append(idattr.ownerElement) for element in filter(lambda node: node.nodeType == Node.ELEMENT_NODE, element.childNodes): elements.extend(ElementsById(element, name)) return elements def IndexDocument(doc): global g_documentOrderIndex if g_documentOrderIndex.has_key(id(doc)): return mapping = {} count = __IndexNode(doc, 0, mapping) g_documentOrderIndex[id(doc)] = mapping def FreeDocumentIndex(doc): global g_documentOrderIndex if g_documentOrderIndex.has_key(id(doc)): del g_documentOrderIndex[id(doc)] def SortDocOrder(nList): if len(nList) in [0, 1]: return nList if hasattr(nList[0], 'docIndex'): nList.sort(lambda a, b: cmp(a.docIndex, b.docIndex)) return nList doc = nList[0].ownerDocument or nList[0] IndexDocument(doc) global g_documentOrderIndex if g_documentOrderIndex.has_key(id(doc)): rt = nList[:] rt.sort(IndexSort) else: rt = __recurseSort([doc], nList) return rt def ExpandQName(qname, refNode=None, namespaces=None): ''' Expand the given QName in the context of the given node, or in the given namespace dictionary ''' nss = {} if refNode: nss = xml.dom.ext.GetAllNs(refNode) elif namespaces: nss = namespaces (prefix, local) = xml.dom.ext.SplitQName(qname) #We're not to use the default namespace if prefix != '': split_name = (nss[prefix], local) else: split_name = (EMPTY_NAMESPACE, local) return split_name def __IndexNode(node, curIndex, mapping): if node.nodeType in g_xpathRecognizedNodes: #Add this node mapping[id(node)] = curIndex curIndex = curIndex + 1 if node.nodeType == Node.ELEMENT_NODE: #FIXME how do we get attributes in doc order??? for attr in node.attributes.values(): mapping[id(attr)] = curIndex curIndex = curIndex + 1 for childNode in node.childNodes: curIndex = __IndexNode(childNode, curIndex, mapping) return curIndex def IndexSort(left, right): ldocId = id(left.ownerDocument or left) rdocId = id(right.ownerDocument or right) if ldocId == rdocId: lid = id(left) rid = id(right) return cmp(g_documentOrderIndex[ldocId][lid], g_documentOrderIndex[rdocId][rid]) else: return cmp(ldocId, rdocId) def __recurseSort(test, toSort): """Check whether any of the nodes in toSort are in the list test, and if so, sort them into the result list""" result = [] for node in test: toSort = filter(lambda x, n=node: x != n, toSort) if node in toSort: result.append(node) #See if node has attributes if node.nodeType == Node.ELEMENT_NODE: attrList = node.attributes.values() #FIXME: Optimize by unrolling this level of recursion result = result + __recurseSort(attrList, toSort) if not toSort: #Exit early break #See if any of t's children are in toSort result = result + __recurseSort(node.childNodes, toSort) if not toSort: #Exit early break return result def NormalizeNode(node): """NormalizeNode is used to prepare a DOM for XPath evaluation. 1. Convert CDATA Sections to Text Nodes. 2. Normalize all text nodes """ node = node.firstChild while node: if node.nodeType == Node.CDATA_SECTION_NODE: # If followed by a text node, add this data to it if node.nextSibling and node.nextSibling.nodeType == Node.TEXT_NODE: node.nextSibling.insertData(0, node.data) elif node.data: # Replace this node with a new text node text = node.ownerDocument.createTextNode(node.data) node.parentNode.replaceChild(text, node) node = text else: # It is empty, get rid of it next = node.nextSibling node.parentNode.removeChild(node) node = next # Just in case it is None continue elif node.nodeType == Node.TEXT_NODE: next = node.nextSibling while next and next.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]: node.appendData(next.data) node.parentNode.removeChild(next) next = node.nextSibling if not node.data: # Remove any empty text nodes next = node.nextSibling node.parentNode.removeChild(node) node = next # Just in case it is None continue elif node.nodeType == Node.ELEMENT_NODE: for attr in node.attributes.values(): if len(attr.childNodes) > 1: NormalizeNode(attr) NormalizeNode(node) node = node.nextSibling return PyXML-0.8.2/xml/xpath/XPathGrammar.py0100644000076400001440000010314207534565153016557 0ustar martinusers# -*- coding: utf-8 -*- # Parser for XPath in -*- python -*-, as defined in REC-xpath-19991116 # Copyright 2000, Martin v. Löwis # This parser is generated by Amit J Patel's YAPPS # http://theory.stanford.edu/~amitp/Yapps/ for documentation and updates # The generated Scanner class is not used, and redefined at the end. # Therefore, the token definitions are for illustration only, and to # let YAPPS know what the tokens are. # The grammar rules attempt to follow the XPath recommendation closely, # both in textual order and presentation. The following changes have been # made: # - left-recursion was replaced with right-recursion # - left-factorization was applied where necessary # - semantic values were attached to non-terminals from string import * import re from yappsrt import * class XPathScanner(Scanner): patterns = [ ("'mod'", re.compile('mod')), ("'div'", re.compile('div')), ("'-'", re.compile('-')), ("'>='", re.compile('>=')), ("'>'", re.compile('>')), ("'<='", re.compile('<=')), ("'<'", re.compile('<')), ("'!='", re.compile('!=')), ("'='", re.compile('=')), ("'and'", re.compile('and')), ("'or'", re.compile('or')), ("','", re.compile(',')), ("'@'", re.compile('@')), ("'::'", re.compile('::')), ("'//'", re.compile('//')), ("'/'", re.compile('/')), ('Literal', re.compile('"[^"]*"|\'[^\']*')), ('Number', re.compile('\\d+(.\\d*)?|.\\d+')), ('VariableReference', re.compile('\\$[a-zA-Z_][:a-zA-Z0-9_.-]*')), ('NodeType', re.compile('comment|text|processing-instruction|node')), ('AxisName', re.compile('ancestor|ancestor-or-self|attribute|child|descendant|descendant-or-self|following|following-sibling|namespace|parent|preceding|preceding-sibling|self')), ('NCName', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*')), ('NCNameStar', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*:\\*')), ('QName', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*(:[a-zA-Z_][a-zA-Z0-9_.-])?')), ('MultiplyOperator', re.compile('\\*')), ('LPAREN', re.compile('\\(')), ('RPAREN', re.compile('\\)')), ('STAR', re.compile('\\*')), ('PLUS', re.compile('\\+')), ('LBRACKET', re.compile('\\[')), ('RBRACKET', re.compile('\\]')), ('FunctionName', re.compile('[a-zA-Z_][a-zA-Z0-9_.-]*(:[a-zA-Z_][a-zA-Z0-9_.-]*)?')), ('DOT', re.compile('\\.')), ('DOTDOT', re.compile('\\.\\.')), ('BAR', re.compile('\\|')), ('END', re.compile('#')), ('ID', re.compile('id')), ('KEY', re.compile('key')), ] def __init__(self, str): Scanner.__init__(self,None,[],str) class XPath(Parser): def Start(self): LocationPath = self.LocationPath() END = self._scan('END') return LocationPath def FullExpr(self): Expr = self.Expr() END = self._scan('END') return Expr def LocationPath(self): _token_ = self._peek() if _token_ in ['AxisName', 'NodeType', 'DOT', 'DOTDOT', "'@'", 'STAR', 'QName', 'NCNameStar', 'NCName']: RelativeLocationPath = self.RelativeLocationPath() return RelativeLocationPath elif _token_ in ["'/'", "'//'"]: AbsoluteLocationPath = self.AbsoluteLocationPath() return AbsoluteLocationPath else: raise SyntaxError(self._pos, 'Could not match LocationPath') def AbsoluteLocationPath(self): _token_ = self._peek() if _token_ == "'/'": self._scan("'/'") OptRelativeLocationPath = self.OptRelativeLocationPath() return self.absoluteLocationPath(OptRelativeLocationPath) elif _token_ == "'//'": AbbreviatedAbsoluteLocationPath = self.AbbreviatedAbsoluteLocationPath() return AbbreviatedAbsoluteLocationPath else: raise SyntaxError(self._pos, 'Could not match AbsoluteLocationPath') def OptRelativeLocationPath(self): _token_ = self._peek() if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']: return None elif _token_ not in ["'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'LPAREN', 'LBRACKET', 'FunctionName', 'ID', 'KEY']: RelativeLocationPath = self.RelativeLocationPath() return RelativeLocationPath else: raise SyntaxError(self._pos, 'Could not match OptRelativeLocationPath') def RelativeLocationPath(self): Step = self.Step() RelativeLocationPaths = self.RelativeLocationPaths(Step) return RelativeLocationPaths def RelativeLocationPaths(self, v): _token_ = self._peek() if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']: return v elif _token_ == "'/'": self._scan("'/'") Step = self.Step() RelativeLocationPaths = self.RelativeLocationPaths(self.rlp(v,Step)) return RelativeLocationPaths elif _token_ == "'//'": self._scan("'//'") Step = self.Step() RelativeLocationPaths = self.RelativeLocationPaths(self.arlp(v,Step)) return RelativeLocationPaths else: raise SyntaxError(self._pos, 'Could not match RelativeLocationPaths') def Step(self): _token_ = self._peek() if _token_ in ['AxisName', 'NodeType', "'@'", 'STAR', 'QName', 'NCNameStar', 'NCName']: AxisSpecifier = self.AxisSpecifier() NodeTest = self.NodeTest() Predicates = self.Predicates() return self.step(AxisSpecifier,NodeTest,Predicates) elif _token_ in ['DOT', 'DOTDOT']: AbbreviatedStep = self.AbbreviatedStep() return AbbreviatedStep else: raise SyntaxError(self._pos, 'Could not match Step') def Predicates(self): _token_ = self._peek() if _token_ not in ["'@'", "'::'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']: return [] elif _token_ == 'LBRACKET': Predicate = self.Predicate() Predicates = self.Predicates() return [Predicate]+Predicates else: raise SyntaxError(self._pos, 'Could not match Predicates') def AxisSpecifier(self): _token_ = self._peek() if _token_ == 'AxisName': AxisName = self._scan('AxisName') self._scan("'::'") return self.axisSpecifier(self.anMap[AxisName]) elif _token_ in ["'@'", 'NodeType', 'STAR', 'QName', 'NCNameStar', 'NCName']: AbbreviatedAxisSpecifier = self.AbbreviatedAxisSpecifier() return AbbreviatedAxisSpecifier else: raise SyntaxError(self._pos, 'Could not match AxisSpecifier') def NodeTest(self): _token_ = self._peek() if _token_ in ['STAR', 'QName', 'NCNameStar', 'NCName']: NameTest = self.NameTest() return NameTest elif _token_ == 'NodeType': NodeType = self._scan('NodeType') LPAREN = self._scan('LPAREN') OptLiteral = self.OptLiteral() RPAREN = self._scan('RPAREN') return self.mkNodeTest(NodeType,OptLiteral) else: raise SyntaxError(self._pos, 'Could not match NodeTest') def OptLiteral(self): _token_ = self._peek() if _token_ == 'RPAREN': return None elif _token_ == 'Literal': Literal = self._scan('Literal') return Literal else: raise SyntaxError(self._pos, 'Could not match OptLiteral') def NameTest(self): _token_ = self._peek() if _token_ == 'STAR': STAR = self._scan('STAR') return self.nameTest(None,"*") elif _token_ == 'QName': QName = self._scan('QName') return self.mkQName(QName) elif _token_ == 'NCNameStar': NCNameStar = self._scan('NCNameStar') return self.nameTest(NCNameStar[:-2],'*') elif _token_ == 'NCName': NCName = self._scan('NCName') return self.nameTest(None,NCName) else: raise SyntaxError(self._pos, 'Could not match NameTest') def Predicate(self): LBRACKET = self._scan('LBRACKET') PredicateExpr = self.PredicateExpr() RBRACKET = self._scan('RBRACKET') return PredicateExpr def PredicateExpr(self): Expr = self.Expr() return Expr def AbbreviatedAbsoluteLocationPath(self): self._scan("'//'") RelativeLocationPath = self.RelativeLocationPath() return self.aalp(RelativeLocationPath) def AbbreviatedStep(self): _token_ = self._peek() if _token_ == 'DOT': DOT = self._scan('DOT') return self.abbreviatedStep(0) elif _token_ == 'DOTDOT': DOTDOT = self._scan('DOTDOT') return self.abbreviatedStep(1) else: raise SyntaxError(self._pos, 'Could not match AbbreviatedStep') def AbbreviatedAxisSpecifier(self): _token_ = self._peek() if _token_ in ['NodeType', 'STAR', 'QName', 'NCNameStar', 'NCName']: return self.axisSpecifier(pyxpath.CHILD_AXIS) elif _token_ == "'@'": self._scan("'@'") return self.axisSpecifier(pyxpath.ATTRIBUTE_AXIS) else: raise SyntaxError(self._pos, 'Could not match AbbreviatedAxisSpecifier') def Expr(self): OrExpr = self.OrExpr() return OrExpr def PrimaryExpr(self): _token_ = self._peek() if _token_ == 'VariableReference': VariableReference = self._scan('VariableReference') return self.mkVariableReference(VariableReference) elif _token_ == 'LPAREN': LPAREN = self._scan('LPAREN') Expr = self.Expr() RPAREN = self._scan('RPAREN') return Expr elif _token_ == 'Literal': Literal = self._scan('Literal') return self.literal(Literal) elif _token_ == 'Number': Number = self._scan('Number') return self.number(Number) elif _token_ in ['FunctionName', 'ID', 'KEY']: FunctionCall = self.FunctionCall() return FunctionCall else: raise SyntaxError(self._pos, 'Could not match PrimaryExpr') def FunctionCall(self): _token_ = self._peek() if _token_ == 'FunctionName': FunctionName = self._scan('FunctionName') LPAREN = self._scan('LPAREN') Arguments = self.Arguments() RPAREN = self._scan('RPAREN') return self.mkFunctionCall(FunctionName,Arguments) elif _token_ == 'ID': ID = self._scan('ID') LPAREN = self._scan('LPAREN') Arguments = self.Arguments() RPAREN = self._scan('RPAREN') return self.functionCall(None,'id',Arguments) elif _token_ == 'KEY': KEY = self._scan('KEY') LPAREN = self._scan('LPAREN') Arguments = self.Arguments() RPAREN = self._scan('RPAREN') return self.functionCall(None,'key',Arguments) else: raise SyntaxError(self._pos, 'Could not match FunctionCall') def Arguments(self): _token_ = self._peek() if _token_ == 'RPAREN': return [] elif _token_ not in ["'mod'", "'div'", "'>='", "'>'", "'<='", "'<'", "'!='", "'='", "'and'", "'or'", "','", "'::'", 'MultiplyOperator', 'PLUS', 'LBRACKET', 'RBRACKET', 'BAR', 'END']: Argument = self.Argument() KommaArguments = self.KommaArguments([Argument]) return KommaArguments else: raise SyntaxError(self._pos, 'Could not match Arguments') def KommaArguments(self, v): _token_ = self._peek() if _token_ == 'RPAREN': return v elif _token_ == "','": self._scan("','") Argument = self.Argument() KommaArguments = self.KommaArguments(v+[Argument]) return KommaArguments else: raise SyntaxError(self._pos, 'Could not match KommaArguments') def Argument(self): Expr = self.Expr() return Expr def UnionExpr(self): PathExpr = self.PathExpr() UnionExprs = self.UnionExprs(PathExpr) return UnionExprs def UnionExprs(self, v): _token_ = self._peek() if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'BAR', 'ID', 'KEY']: return v elif _token_ == 'BAR': BAR = self._scan('BAR') PathExpr = self.PathExpr() UnionExprs = self.UnionExprs(self.nop(self.UNION,v,PathExpr)) return UnionExprs else: raise SyntaxError(self._pos, 'Could not match UnionExprs') def PathExpr(self): _token_ = self._peek() if _token_ in ["'/'", "'//'", 'AxisName', 'NodeType', 'DOT', 'DOTDOT', "'@'", 'STAR', 'QName', 'NCNameStar', 'NCName']: LocationPath = self.LocationPath() return LocationPath elif _token_ in ['VariableReference', 'LPAREN', 'Literal', 'Number', 'FunctionName', 'ID', 'KEY']: FilterExpr = self.FilterExpr() PathExprRest = self.PathExprRest(FilterExpr) return PathExprRest else: raise SyntaxError(self._pos, 'Could not match PathExpr') def PathExprRest(self, v): _token_ = self._peek() if _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']: return v elif _token_ == "'/'": self._scan("'/'") RelativeLocationPath = self.RelativeLocationPath() return self.pathExpr(v,RelativeLocationPath) elif _token_ == "'//'": self._scan("'//'") RelativeLocationPath = self.RelativeLocationPath() return self.abbreviatedPathExpr(v,RelativeLocationPath) else: raise SyntaxError(self._pos, 'Could not match PathExprRest') def FilterExpr(self): PrimaryExpr = self.PrimaryExpr() FilterExprs = self.FilterExprs(PrimaryExpr) return FilterExprs def FilterExprs(self, v): _token_ = self._peek() if _token_ not in ["'@'", "'::'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'ID', 'KEY']: return v elif _token_ == 'LBRACKET': Predicate = self.Predicate() e=[Predicate] while self._peek() == 'LBRACKET': Predicate = self.Predicate() e.append(Predicate) return self.filterExpr(v,e) else: raise SyntaxError(self._pos, 'Could not match FilterExprs') def OrExpr(self): AndExpr = self.AndExpr() OrExprs = self.OrExprs(AndExpr) return OrExprs def OrExprs(self, v): _token_ = self._peek() if _token_ == "'or'": self._scan("'or'") AndExpr = self.AndExpr() OrExprs = self.OrExprs(self.bop(self.OR,v,AndExpr)) return OrExprs elif _token_ in ['END', 'RPAREN', 'RBRACKET', "','"]: return v else: raise SyntaxError(self._pos, 'Could not match OrExprs') def AndExpr(self): EqualityExpr = self.EqualityExpr() AndExprs = self.AndExprs(EqualityExpr) return AndExprs def AndExprs(self, v): _token_ = self._peek() if _token_ == "'and'": self._scan("'and'") EqualityExpr = self.EqualityExpr() AndExprs = self.AndExprs(self.bop(self.AND,v,EqualityExpr)) return AndExprs elif _token_ in ["'or'", 'END', 'RPAREN', 'RBRACKET', "','"]: return v else: raise SyntaxError(self._pos, 'Could not match AndExprs') def EqualityExpr(self): RelationalExpr = self.RelationalExpr() EqualityExprs = self.EqualityExprs(RelationalExpr) return EqualityExprs def EqualityExprs(self, v): _token_ = self._peek() if _token_ == "'='": self._scan("'='") RelationalExpr = self.RelationalExpr() EqualityExprs = self.EqualityExprs(self.bop(self.EQ,v,RelationalExpr)) return EqualityExprs elif _token_ == "'!='": self._scan("'!='") RelationalExpr = self.RelationalExpr() EqualityExprs = self.EqualityExprs(self.bop(self.NEQ,v,RelationalExpr)) return EqualityExprs elif _token_ in ["'and'", "'or'", 'END', 'RPAREN', 'RBRACKET', "','"]: return v else: raise SyntaxError(self._pos, 'Could not match EqualityExprs') def RelationalExpr(self): AdditiveExpr = self.AdditiveExpr() RelationalExprs = self.RelationalExprs(AdditiveExpr) return RelationalExprs def RelationalExprs(self, v): _token_ = self._peek() if _token_ == "'<'": self._scan("'<'") AdditiveExpr = self.AdditiveExpr() RelationalExprs = self.RelationalExprs(self.bop(self.LT,v,AdditiveExpr)) return RelationalExprs elif _token_ == "'<='": self._scan("'<='") AdditiveExpr = self.AdditiveExpr() RelationalExprs = self.RelationalExprs(self.bop(self.LE,v,AdditiveExpr)) return RelationalExprs elif _token_ == "'>'": self._scan("'>'") AdditiveExpr = self.AdditiveExpr() RelationalExprs = self.RelationalExprs(self.bop(self.GT,v,AdditiveExpr)) return RelationalExprs elif _token_ == "'>='": self._scan("'>='") AdditiveExpr = self.AdditiveExpr() RelationalExprs = self.RelationalExprs(self.bop(self.GE,v,AdditiveExpr)) return RelationalExprs elif _token_ in ["'='", "'!='", "'and'", "'or'", 'END', 'RPAREN', 'RBRACKET', "','"]: return v else: raise SyntaxError(self._pos, 'Could not match RelationalExprs') def AdditiveExpr(self): MultiplicativeExpr = self.MultiplicativeExpr() AdditiveExprs = self.AdditiveExprs(MultiplicativeExpr) return AdditiveExprs def AdditiveExprs(self, v): _token_ = self._peek() if _token_ == 'PLUS': PLUS = self._scan('PLUS') MultiplicativeExpr = self.MultiplicativeExpr() AdditiveExprs = self.AdditiveExprs(self.nop(self.PLUS,v,MultiplicativeExpr)) return AdditiveExprs elif _token_ == "'-'": self._scan("'-'") MultiplicativeExpr = self.MultiplicativeExpr() AdditiveExprs = self.AdditiveExprs(self.nop(self.MINUS,v,MultiplicativeExpr)) return AdditiveExprs elif _token_ in ["'<'", "'<='", "'>'", "'>='", "'='", "'!='", "'and'", "'or'", 'END', 'RPAREN', 'RBRACKET', "','"]: return v else: raise SyntaxError(self._pos, 'Could not match AdditiveExprs') def MultiplicativeExpr(self): UnaryExpr = self.UnaryExpr() MultiplicativeExprs = self.MultiplicativeExprs(UnaryExpr) return MultiplicativeExprs def MultiplicativeExprs(self, v): _token_ = self._peek() if _token_ == 'MultiplyOperator': MultiplyOperator = self._scan('MultiplyOperator') UnaryExpr = self.UnaryExpr() MultiplicativeExprs = self.MultiplicativeExprs(self.nop(self.TIMES,v,UnaryExpr)) return MultiplicativeExprs elif _token_ == "'div'": self._scan("'div'") UnaryExpr = self.UnaryExpr() MultiplicativeExprs = self.MultiplicativeExprs(self.nop(self.DIV,v,UnaryExpr)) return MultiplicativeExprs elif _token_ == "'mod'": self._scan("'mod'") UnaryExpr = self.UnaryExpr() MultiplicativeExprs = self.MultiplicativeExprs(self.nop(self.MOD,v,UnaryExpr)) return MultiplicativeExprs elif _token_ not in ["'@'", "'::'", "'//'", "'/'", 'Literal', 'Number', 'VariableReference', 'NodeType', 'AxisName', 'NCName', 'NCNameStar', 'QName', 'LPAREN', 'STAR', 'LBRACKET', 'FunctionName', 'DOT', 'DOTDOT', 'BAR', 'ID', 'KEY']: return v else: raise SyntaxError(self._pos, 'Could not match MultiplicativeExprs') def UnaryExpr(self): _token_ = self._peek() if _token_ == "'-'": self._scan("'-'") UnaryExpr = self.UnaryExpr() return self.unaryExpr(UnaryExpr) elif _token_ not in ["'mod'", "'div'", "'>='", "'>'", "'<='", "'<'", "'!='", "'='", "'and'", "'or'", "','", "'::'", 'MultiplyOperator', 'RPAREN', 'PLUS', 'LBRACKET', 'RBRACKET', 'BAR', 'END']: UnionExpr = self.UnionExpr() return UnionExpr else: raise SyntaxError(self._pos, 'Could not match UnaryExpr') def FullPattern(self): Pattern = self.Pattern() END = self._scan('END') return Pattern def Pattern(self): LocationPathPattern = self.LocationPathPattern() p = self.pattern(LocationPathPattern) while self._peek() == 'BAR': BAR = self._scan('BAR') LocationPathPattern = self.LocationPathPattern() p.append(LocationPathPattern) return p def LocationPathPattern(self): _token_ = self._peek() if _token_ == "'/'": self._scan("'/'") OptRelativePathPattern = self.OptRelativePathPattern() return self.locationPathPattern(None,1,OptRelativePathPattern) elif _token_ in ['ID', 'KEY']: IdKeyPattern = self.IdKeyPattern() IdTail = self.IdTail() return self.locationPathPattern(IdKeyPattern,IdTail[0],IdTail[1]) elif _token_ in ['NodeType', "'@'", 'AxisName', 'STAR', 'QName', 'NCNameStar', 'NCName']: RelativePathPattern = self.RelativePathPattern() return RelativePathPattern elif _token_ == "'//'": self._scan("'//'") RelativePathPattern = self.RelativePathPattern() return self.locationPathPattern(None,0,RelativePathPattern) else: raise SyntaxError(self._pos, 'Could not match LocationPathPattern') def OptRelativePathPattern(self): _token_ = self._peek() if _token_ in ['BAR', 'END']: return None elif _token_ in ['NodeType', "'@'", 'AxisName', 'STAR', 'QName', 'NCNameStar', 'NCName']: RelativePathPattern = self.RelativePathPattern() return RelativePathPattern else: raise SyntaxError(self._pos, 'Could not match OptRelativePathPattern') def IdTail(self): _token_ = self._peek() if _token_ in ['BAR', 'END']: return (0,None) elif _token_ == "'/'": self._scan("'/'") RelativePathPattern = self.RelativePathPattern() return (1,RelativePathPattern) elif _token_ == "'//'": self._scan("'//'") RelativePathPattern = self.RelativePathPattern() return (0,RelativePathPattern) else: raise SyntaxError(self._pos, 'Could not match IdTail') def IdKeyPattern(self): _token_ = self._peek() if _token_ == 'ID': ID = self._scan('ID') LPAREN = self._scan('LPAREN') Argument = self.Argument() RPAREN = self._scan('RPAREN') return self.functionCall(None,"id", [Argument]) elif _token_ == 'KEY': KEY = self._scan('KEY') LPAREN = self._scan('LPAREN') Argument = self.Argument() a1=Argument self._scan("','") Argument = self.Argument() RPAREN = self._scan('RPAREN') return self.functionCall(None,"key", [a1,Argument]) else: raise SyntaxError(self._pos, 'Could not match IdKeyPattern') def RelativePathPattern(self): StepPattern = self.StepPattern() p=StepPattern while self._peek() in ["'/'", "'//'"]: _token_ = self._peek() if _token_ == "'/'": self._scan("'/'") StepPattern = self.StepPattern() p=self.rpp(p, 1, StepPattern) elif _token_ == "'//'": self._scan("'//'") StepPattern = self.StepPattern() p=self.rpp(p, 0, StepPattern) else: raise SyntaxError(self._pos, 'Could not match RelativePathPattern') return p def StepPattern(self): ChildOrAttributeAxisSpecifier = self.ChildOrAttributeAxisSpecifier() NodeTest = self.NodeTest() pred=[] while self._peek() == 'LBRACKET': Predicate = self.Predicate() pred.append(Predicate) return self.stepPattern(ChildOrAttributeAxisSpecifier,NodeTest,pred) def ChildOrAttributeAxisSpecifier(self): _token_ = self._peek() if _token_ in ["'@'", 'NodeType', 'STAR', 'QName', 'NCNameStar', 'NCName']: AbbreviatedAxisSpecifier = self.AbbreviatedAxisSpecifier() return AbbreviatedAxisSpecifier elif _token_ == 'AxisName': AxisName = self._scan('AxisName') self._scan("'::'") return self.axisSpecifier(self.anMap[AxisName]) else: raise SyntaxError(self._pos, 'Could not match ChildOrAttributeAxisSpecifier') def parse(rule, text): P = XPath(XPathScanner(text)) return wrap_error_reporter(P, rule) # Reimplement scanner, to properly use disambiguation import re, sys NCName = "[a-zA-Z_](\w|[_.-])*" # In this version of QName, the namespace prefix is not optional. # As a result, QName matches iff there is a colon, NCName otherwise. # All appearances of QName in the grammar then need to allow NCName # as an alternative; currently, QName is used only once. QName = NCName + ":" + NCName XPathExpr=""" (?P\"[^\"]*\"|\'[^\']*\')| (?P\\d+(\\.\\d*)?|\\.\\d+)| (?P\\$""" + NCName + "(:" + NCName + """)?)| (?P"""+QName+""")| (?P"""+NCName+""":\*)| (?P"""+NCName+""")| (?P\\()| (?P\\))| (?P\\*)| (?P\\+)| (?P\\[)| (?P\\])| (?P\\.\\.)| (?P\\.)| (?P\\|)| (?P//|::|>=|<=|!=)| (?P[<>=,/@:-])| (?P[ \t\n\r]+) """ _xpath_exp = re.compile(XPathExpr,re.VERBOSE) OperatorName = ['and','or','mod','div'] AxisName = ['ancestor', 'ancestor-or-self', 'attribute', 'child', 'descendant', 'descendant-or-self', 'following', 'following-sibling', 'namespace', 'parent', 'preceding', 'preceding-sibling', 'self'] SpecialPreceding = map(repr,["@","::","(","["] + OperatorName + ['/', '//', '+', '-', '=', '!=', '<', '<=', '>', '>=']) + ["BAR","MultiplyOperator"] if sys.hexversion > 0x2000000: def _get_type(match): return match.lastgroup,match.group() else: def _get_type(match): type = val = None for t,v in match.groupdict().items(): if v is None: continue if val: raise SyntaxError(pos, "ambiguity:%s could be %s or %s" % (val,type,t)) type = t val = v return type,val class XPathScanner: def __init__(self,input): self.tokens = tokens = [] pos = 0 # Process all tokens, advancing pos for each one while pos != len(input): m = _xpath_exp.match(input, pos) if not m: msg = "Bad Token" raise SyntaxError(pos, msg) type, val = _get_type(m) if type == "ExprWhiteSpace": # If we got white space, ignore it pos = pos + len(val) continue if type in ['SingleOperator', 'Operator']: type = repr(str(val)) start = pos pos = pos + len(val) tokens.append((start, pos, type, val)) # If we are at the end of the string, add END token tokens.append((pos,pos,'END',"")) # Adjust token type according to additional semantic rules for i in range(len(tokens)-1): start,stop,type,val = tokens[i] changed = 0 # If there is a preceding token and the preceding token is not # one of @, ::, (, [, , or an Operator if i>=1 and tokens[i-1][2] not in SpecialPreceding: if type == 'STAR': # then a * must be recognized as a MultiplyOperator type = 'MultiplyOperator' tokens[i] = (start,stop,type,val) elif type == 'NCName' and val in OperatorName: # and an NCName must be recognized as an OperatorName type = repr(str(val)) tokens[i] = (start,stop,type,val) # If the character following an NCName (possibly after # intervening ExprWhitespace) is ( if tokens[i][2] in ['QName','NCName'] and tokens[i+1][2]=='LPAREN': # then the token must be recognized as a NodeType or a # FunctionName if val in ['comment','text','processing-instruction','node']: type = 'NodeType' elif val == 'id': type = 'ID' elif val == 'key': type = 'KEY' else: type = 'FunctionName' tokens[i] = (start,stop,type,val) # If the two characters following an NCName (possibly # after intervening ExprWhitespace) are :: if tokens[i][2] == 'NCName' and tokens[i+1][3]=='::' \ and val in AxisName: # then the token must be recognized as an AxisName. type = 'AxisName' tokens[i] = (start,stop,type,val) def token(self, i, expected): return self.tokens[i] # redefine to add additional attributes import pyxpath,string GeneratedXPath = XPath class XPath(GeneratedXPath): OR = pyxpath.OR_OPERATOR AND = pyxpath.AND_OPERATOR EQ = pyxpath.EQ_OPERATOR NEQ = pyxpath.NEQ_OPERATOR LT = pyxpath.LT_OPERATOR GT = pyxpath.GT_OPERATOR LE = pyxpath.LE_OPERATOR GE = pyxpath.GE_OPERATOR PLUS = pyxpath.PLUS_OPERATOR MINUS = pyxpath.MINUS_OPERATOR TIMES = pyxpath.TIMES_OPERATOR DIV = pyxpath.DIV_OPERATOR MOD = pyxpath.MOD_OPERATOR UNION = pyxpath.UNION_OPERATOR def __init__(self, scanner, factory): GeneratedXPath.__init__(self, scanner) self.factory = factory # shorthands self.rlp = self.factory.createRelativeLocationPath self.arlp = self.factory.createAbbreviatedRelativeLocationPath self.aalp = self.factory.createAbbreviatedAbsoluteLocationPath self.nop = self.factory.createNumericExpr self.bop = self.factory.createBooleanExpr self.rpp = self.factory.createRelativePathPattern def __getattr__(self, name): # convert newname = "create"+string.upper(name[0])+name[1:] try: return getattr(self.factory, newname) except AttributeError: raise AttributeError,"parser has no attribute "+name anMap = { 'ancestor':pyxpath.ANCESTOR_AXIS, 'ancestor-or-self':pyxpath.ANCESTOR_OR_SELF_AXIS, 'attribute':pyxpath.ATTRIBUTE_AXIS, 'child':pyxpath.CHILD_AXIS, 'descendant':pyxpath.DESCENDANT_AXIS, 'descendant-or-self':pyxpath.DESCENDANT_OR_SELF_AXIS, 'following':pyxpath.FOLLOWING_AXIS, 'following-sibling':pyxpath.FOLLOWING_SIBLING_AXIS, 'namespace':pyxpath.NAMESPACE_AXIS, 'parent':pyxpath.PARENT_AXIS, 'preceding':pyxpath.PRECEDING_AXIS, 'preceding-sibling':pyxpath.PRECEDING_SIBLING_AXIS, 'self':pyxpath.SELF_AXIS } nodeTestMap = { 'node': pyxpath.NODE, 'comment': pyxpath.COMMENT, 'text': pyxpath.TEXT, 'processing-instruction': pyxpath.PROCESSING_INSTRUCTION } def mkNodeTest(self,op,val): type = self.nodeTestMap[op] if type != pyxpath.PROCESSING_INSTRUCTION and val is not None: raise SyntaxError("parameter not allowed for "+op) return self.factory.createNodeTest(type,val) def mkQName(self,str): prefix,local = string.split(str,":") return self.factory.createNameTest(prefix,local) def mkVariableReference(self, qname): colon = string.find(qname,':') if colon == -1: return self.variableReference(None, qname[1:]) return self.variableReference(qname[1:colon],qname[colon+1:]) def mkFunctionCall(self, qname, args): colon = string.find(qname,':') if colon == -1: return self.functionCall(None, qname, args) return self.functionCall(qname[:colon],qname[colon+1:],args) PyXML-0.8.2/xml/xpath/XPathParser.py0100644000076400001440000011036007356637352016430 0ustar martinusers# # DO NOT EDIT THIS FILE! # # Parser generated by BisonGen on Fri Jun 1 02:04:24 2001. # # token definitions DOUBLE_DOT = 257 DOUBLE_COLON = 258 AT = 259 LEFT_PAREN = 260 LEFT_SQUARE = 261 COMMA = 262 LITERAL = 263 NLITERAL = 264 VARIABLE_REFERENCE = 265 WILDCARD_NAME = 266 MULTIPLY_OPERATOR = 267 FUNCTION_NAME = 268 DOUBLE_SLASH = 269 NOT_EQUAL = 270 LESS_THAN = 271 GREATER_THAN = 272 LESS_THAN_EQUAL = 273 GREATER_THAN_EQUAL = 274 OR = 275 AND = 276 DIV = 277 MOD = 278 COMMENT = 279 TEXT = 280 PROCESSING_INSTRUCTION = 281 NODE = 282 ANCESTOR = 283 ANCESTOR_OR_SELF = 284 ATTRIBUTE = 285 CHILD = 286 DESCENDANT = 287 DESCENDANT_OR_SELF = 288 FOLLOWING = 289 FOLLOWING_SIBLING = 290 NAMESPACE = 291 PARENT = 292 PRECEDING = 293 PRECEDING_SIBLING = 294 SELF = 295 NODE_TYPE = 296 AXIS_NAME = 297 RELATIONAL_OP = 298 EQUALITY_OP = 299 # vector mapping lexer token numbers into internal token numbers token_translations = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 48, 2, 55, 53, 56, 51, 46, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 49, 2, 50, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 54, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45] YYTRANSLATE = lambda x: x > 299 and 85 or token_translations[x] # vector of items of all rules. rhs_tokens = [None, [59], [58], [46], [46, 59], [66], [60], [59, 46, 60], [67], [62, 63], [62, 63, 61], [68], [64], [61, 64], [43, 4], [69], [12], [42, 47, 48], [42, 47, 9, 48], [49, 65, 50], [70], [15, 59], [59, 15, 60], [51], [3], [52], [], [78], [11], [47, 70, 48], [9], [10], [72], [14, 47, 48], [14, 47, 73, 48], [74], [73, 53, 74], [70], [76], [75, 54, 76], [57], [77], [77, 46, 59], [77, 15, 59], [71], [71, 61], [79], [78, 21, 79], [80], [79, 22, 80], [81], [80, 45, 81], [82], [81, 44, 82], [83], [82, 55, 83], [82, 56, 83], [84], [83, 13, 84], [75], [56, 75], ] # vector of line numbers and filename of all rules rule_info = [": line 0", "XPath/XPathBase.bgen.frag: line 5", "XPath/XPathBase.bgen.frag: line 8", "XPath/XPathBase.bgen.frag: line 15", "XPath/XPathBase.bgen.frag: line 24", "XPath/XPathBase.bgen.frag: line 34", "XPath/XPathBase.bgen.frag: line 41", "XPath/XPathBase.bgen.frag: line 44", "XPath/XPathBase.bgen.frag: line 55", "XPath/XPathBase.bgen.frag: line 62", "XPath/XPathBase.bgen.frag: line 72", "XPath/XPathBase.bgen.frag: line 83", "XPath/XPathBase.bgen.frag: line 90", "XPath/XPathBase.bgen.frag: line 104", "XPath/XPathBase.bgen.frag: line 121", "XPath/XPathBase.bgen.frag: line 131", "XPath/XPathBase.bgen.frag: line 149", "XPath/XPathBase.bgen.frag: line 158", "XPath/XPathBase.bgen.frag: line 169", "XPath/XPathBase.bgen.frag: line 185", "XPath/XPathBase.bgen.frag: line 201", "XPath/XPathBase.bgen.frag: line 208", "XPath/XPathBase.bgen.frag: line 224", "XPath/XPathBase.bgen.frag: line 241", "XPath/XPathBase.bgen.frag: line 250", "XPath/XPathBase.bgen.frag: line 263", "XPath/XPathBase.bgen.frag: line 272", "XPath/XPathBase.bgen.frag: line 285", "XPath/XPathBase.bgen.frag: line 292", "XPath/XPathBase.bgen.frag: line 301", "XPath/XPathBase.bgen.frag: line 313", "XPath/XPathBase.bgen.frag: line 322", "XPath/XPathBase.bgen.frag: line 332", "XPath/XPathBase.bgen.frag: line 339", "XPath/XPathBase.bgen.frag: line 352", "XPath/XPathBase.bgen.frag: line 368", "XPath/XPathBase.bgen.frag: line 380", "XPath/XPathBase.bgen.frag: line 399", "XPath/XPathBase.bgen.frag: line 406", "XPath/XPathBase.bgen.frag: line 409", "XPath/XPathBase.bgen.frag: line 424", "XPath/XPathBase.bgen.frag: line 427", "XPath/XPathBase.bgen.frag: line 430", "XPath/XPathBase.bgen.frag: line 441", "XPath/XPathBase.bgen.frag: line 457", "XPath/XPathBase.bgen.frag: line 460", "XPath/XPathBase.bgen.frag: line 474", "XPath/XPathBase.bgen.frag: line 477", "XPath/XPathBase.bgen.frag: line 492", "XPath/XPathBase.bgen.frag: line 495", "XPath/XPathBase.bgen.frag: line 510", "XPath/XPathBase.bgen.frag: line 513", "XPath/XPathBase.bgen.frag: line 528", "XPath/XPathBase.bgen.frag: line 531", "XPath/XPathBase.bgen.frag: line 566", "XPath/XPathBase.bgen.frag: line 569", "XPath/XPathBase.bgen.frag: line 580", "XPath/XPathBase.bgen.frag: line 595", "XPath/XPathBase.bgen.frag: line 598", "XPath/XPathBase.bgen.frag: line 631", "XPath/XPathBase.bgen.frag: line 634", ] # vector of string-names indexed by token number token_names = ['$', 'error', '$undefined.', 'DOUBLE_DOT', 'DOUBLE_COLON', 'AT', 'LEFT_PAREN', 'LEFT_SQUARE', 'COMMA', 'LITERAL', 'NLITERAL', 'VARIABLE_REFERENCE', 'WILDCARD_NAME', 'MULTIPLY_OPERATOR', 'FUNCTION_NAME', 'DOUBLE_SLASH', 'NOT_EQUAL', 'LESS_THAN', 'GREATER_THAN', 'LESS_THAN_EQUAL', 'GREATER_THAN_EQUAL', 'OR', 'AND', 'DIV', 'MOD', 'COMMENT', 'TEXT', 'PROCESSING_INSTRUCTION', 'NODE', 'ANCESTOR', 'ANCESTOR_OR_SELF', 'ATTRIBUTE', 'CHILD', 'DESCENDANT', 'DESCENDANT_OR_SELF', 'FOLLOWING', 'FOLLOWING_SIBLING', 'NAMESPACE', 'PARENT', 'PRECEDING', 'PRECEDING_SIBLING', 'SELF', 'NODE_TYPE', 'AXIS_NAME', 'RELATIONAL_OP', 'EQUALITY_OP', '/', '(', ')', '[', ']', '.', '@', ',', '|', '+', '-', 'locationPath', 'absoluteLocationPath', 'relativeLocationPath', 'step', 'predicateList', 'axisSpecifier', 'nodeTest', 'predicate', 'predicateExpr', 'abbreviatedAbsoluteLocationPath', 'abbreviatedRelativeLocationPath', 'abbreviatedStep', 'abbreviatedAxisSpecifier', 'expr', 'primaryExpr', 'functionCall', 'argumentList', 'argument', 'unionExpr', 'pathExpr', 'filterExpr', 'orExpr', 'andExpr', 'equalityExpr', 'relationalExpr', 'additiveExpr', 'multiplicativeExpr', 'unaryExpr', '0', ] # symbol number of symbol that rule derives. derives = [0, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 62, 62, 63, 63, 63, 64, 65, 66, 67, 68, 68, 69, 69, 70, 71, 71, 71, 71, 71, 72, 72, 73, 73, 74, 75, 75, 76, 76, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 82, 82, 83, 83, 84, 84] # number of symbols composing right hand side of rule. rhs_size = [0, 1, 1, 1, 2, 1, 1, 3, 1, 2, 3, 1, 1, 2, 2, 1, 1, 3, 4, 3, 1, 2, 3, 1, 1, 1, 0, 1, 1, 3, 1, 1, 1, 3, 4, 1, 3, 1, 1, 3, 1, 1, 3, 3, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 1, 3, 1, 2] # default rule to reduce with in state. 0 means the default is an error. # indexed by state number default_action = [26, 24, 30, 31, 28, 0, 26, 0, 3, 26, 23, 25, 26, 40, 2, 1, 6, 0, 5, 8, 11, 15, 44, 32, 59, 38, 41, 27, 46, 48, 50, 52, 54, 57, 26, 21, 14, 4, 0, 60, 26, 26, 16, 0, 9, 26, 45, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 33, 37, 0, 35, 29, 22, 7, 0, 10, 0, 20, 13, 39, 43, 42, 47, 49, 51, 53, 55, 56, 58, 34, 26, 0, 17, 19, 36, 18, 0, 0, 0] # default state to go to after a reduction of a rule. # indexed by variable number (lhs token) default_goto = [13, 14, 15, 16, 46, 17, 44, 47, 67, 18, 19, 20, 21, 59, 22, 23, 60, 61, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33] # index in yytable of the portion describing state (indexed by state number) # If the value in yytable is positive, we shift the token and go to that state. # If the value is negative, it is minus a rule number to reduce by. # If the value is zero, the default action from yydefact[s] is used. action_idx = [-3, -32768, -32768, -32768, -32768, -42, 13, 31, 43, -3, -32768, -32768, 66, -32768, -32768, -14, -32768, -8, -32768, -32768, -32768, -32768, -32, -32768, -23, -32768, -13, -2, 17, 6, 24, -46, 48, -32768, 11, -14, -32768, -14, 34, -23, 47, 47, -32768, 37, -32, 27, -32, -32768, 93, 49, 49, 27, 27, 27, 27, 27, 27, 27, -32768, -32768, -35, -32768, -32768, -32768, -32768, 18, -32, 41, -32768, -32768, -32768, -14, -14, 17, 6, 24, -46, 48, 48, -32768, -32768, 27, 45, -32768, -32768, -32768, -32768, 87, 97, -32768] # the index in yytable of the portion describing what to do after reducing a rule. # The value from yytable is the state to go to. goto_idx = [-32768, -32768, 39, -12, 61, -32768, -32768, -43, -32768, -32768, -32768, -32768, -32768, 15, -32768, -32768, -32768, 25, 98, 63, -32768, -32768, 64, 62, 67, 65, 16, 59] # a vector filled with portions for different uses. (using action_idx and goto_idx) yytable = [1, 40, 49, 69, 42, 34, 2, 3, 4, 55, 56, 5, 6, 80, 1, 87, 1, 45, 81, 51, 2, 3, 4, 69, 38, 5, 6, 82, 63, 64, 1, 48, 41, 50, 43, 36, 2, 3, 4, 52, 7, 5, 6, 8, 9, 35, 1, 37, 10, 11, 1, 53, 1, 12, 7, -26, 7, 8, 9, 58, 68, 57, 10, 11, 10, 11, 83, 12, 54, 1, 7, 77, 78, 8, 9, 2, 3, 4, 10, 11, 5, 6, 62, 12, 65, -26, 7, 88, 71, 72, 7, 84, 7, 86, 10, 11, 1, 89, 10, 11, 10, 11, 2, 3, 4, 66, 85, 5, 6, 7, 39, 70, 8, 9, 74, 73, 79, 10, 11, 76, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 8, 9, 0, 0, 0, 10, 11] # a vector indexed in parallel with yytable. # It indicates the bounds of the portion you are trying to examine. yycheck = [3, 15, 15, 46, 12, 47, 9, 10, 11, 55, 56, 14, 15, 48, 3, 0, 3, 49, 53, 21, 9, 10, 11, 66, 9, 14, 15, 9, 40, 41, 3, 54, 46, 46, 42, 4, 9, 10, 11, 22, 43, 14, 15, 46, 47, 6, 3, 8, 51, 52, 3, 45, 3, 56, 43, 12, 43, 46, 47, 48, 45, 13, 51, 52, 51, 52, 48, 56, 44, 3, 43, 55, 56, 46, 47, 9, 10, 11, 51, 52, 14, 15, 48, 56, 47, 42, 43, 0, 49, 50, 43, 50, 43, 48, 51, 52, 3, 0, 51, 52, 51, 52, 9, 10, 11, 44, 81, 14, 15, 43, 12, 48, 46, 47, 52, 51, 57, 51, 52, 54, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, 46, 47, -1, -1, -1, 51, 52] YYLAST = 145 YYFINAL = 89 YYFLAG = -32768 YYNTBASE = 57 # Static definitions YYEMPTY = -2 YYEOF = 0 YYINITDEPTH = 1000 LEXER_FUNCTIONS = 0 class Parser: def __init__(self, verbose=0): self.verbose = verbose def debug_mode(self, flag=None): if flag is None: return self.verbose if type(flag) != type(1): raise TypeError('an integer is required') self.verbose = flag return flag def parse(self, text): state_stack = [0]*YYINITDEPTH value_stack = [0]*YYINITDEPTH lexer_pos = 0 lexer_end = len(text) lexer_state = INITIAL lexer_last = 0 yylval = '' yyline = 1 yycolumn = 1 yystate = 0 yychar = YYEMPTY # cause a token to be read # Initialize stack pointers # Waste one element of value and location stack # so that they stay on the same level as the state stack. # The wasted elements are never initialized. state_ptr = -1 value_ptr = 0 while 1: # Push a new state, which is found in yystate. # In all cases, when you get here, the value and location stacks # have just been pushed. So pushing a state here evens the stacks. state_ptr = state_ptr + 1 state_stack[state_ptr] = yystate # Do appropriate processing given the current state. # Read a lookahead token if we need one and don't already have one. # First try to decide what to do without reference to lookahead token. yyn = action_idx[yystate] if yyn == YYFLAG: yyn = default_action[yystate] if yyn == 0: self.report_error(yystate, yyline, yycolumn, yylval) return 1 # Do a reduction. yyn is the number of a rule to reduce with. state_ptr = state_ptr - rhs_size[yyn] value_ptr = value_ptr - rhs_size[yyn] if action_routines[yyn]: yyval = action_routines[yyn](self, value_stack, value_ptr) value_ptr = value_ptr + 1 value_stack[value_ptr] = yyval else: value_ptr = value_ptr + 1 # Now "shift" the result of the reduction. # Determine what state that goes to, based on the state # we popped back to and the rule number reduced by. yyn = derives[yyn] - YYNTBASE yystate = goto_idx[yyn] + state_stack[state_ptr] if 0 <= yystate <= YYLAST and yycheck[yystate] == state_stack[state_ptr]: yystate = yytable[yystate] else: yystate = default_goto[yyn] continue # Not known => get a lookahead token if don't already have one. # yychar is either YYEMPTY, YYEOF or a valid token in external form if yychar == YYEMPTY: # Setup line and column numbers for ch in yylval: if ch == '\n': yyline = yyline + 1 yycolumn = 1 else: yycolumn = yycolumn + 1 ### Lexical analysis ### while lexer_last < lexer_end: lexer_pos = lexer_last try: match = patterns[lexer_state].match(text, lexer_pos) matched = reduce(lambda result, item: item[1] is None and result or item, match.groupdict().items(), (None, None)) except AttributeError: # comes here when match is none, it is an error anyway self.error('No action found for "%s"' % text[lexer_pos:]) lexer_last = lexer_last + len(matched[1]) lexer_action = pattern_actions[matched[0]] if lexer_action: lexer_state = lexer_action[0] or lexer_state if len(lexer_action) > 1: yylval = matched[1] yychar = lexer_action[1] or ord(yylval) break else: # Just a state change, reprocess the text lexer_last = lexer_pos else: # throw away matched text and update position for ch in matched[1]: if ch == '\n': yyline = yyline + 1 yycolumn = 1 else: yycolumn = yycolumn + 1 continue else: # Reached end of input yychar = YYEOF # Convert token to internal form (in yychar1) for indexing tables with if yychar <= 0: # This means end-of-input. yychar1 = 0 else: yychar1 = YYTRANSLATE(yychar) yyn = yyn + yychar1 if yyn < 0 or yyn > YYLAST or yycheck[yyn] != yychar1: # comes here after end of input yyn = default_action[yystate] if yyn == 0: self.report_error(yystate, yyline, yycolumn, yylval) return None # Do a reduction. yyn is the number of a rule to reduce with. state_ptr = state_ptr - rhs_size[yyn] value_ptr = value_ptr - rhs_size[yyn] if action_routines[yyn]: yyval = action_routines[yyn](self, value_stack, value_ptr) value_ptr = value_ptr + 1 value_stack[value_ptr] = yyval else: value_ptr = value_ptr + 1 # Now "shift" the result of the reduction. # Determine what state that goes to, based on the state # we popped back to and the rule number reduced by. yyn = derives[yyn] - YYNTBASE yystate = goto_idx[yyn] + state_stack[state_ptr] if 0 <= yystate <= YYLAST and yycheck[yystate] == state_stack[state_ptr]: yystate = yytable[yystate] else: yystate = default_goto[yyn] continue yyn = yytable[yyn] # yyn is what to do for this token type in this state. # Negative => reduce, -yyn is rule number. # Positive => shift, yyn is new state. # New state is final state => don't bother to shift # just return success. # 0, or max negative number => error. if YYFLAG < yyn < 0: yyn = -yyn # Do a reduction. yyn is the number of a rule to reduce with. state_ptr = state_ptr - rhs_size[yyn] value_ptr = value_ptr - rhs_size[yyn] if action_routines[yyn]: yyval = action_routines[yyn](self, value_stack, value_ptr) value_ptr = value_ptr + 1 value_stack[value_ptr] = yyval else: value_ptr = value_ptr + 1 # Now "shift" the result of the reduction. # Determine what state that goes to, based on the state # we popped back to and the rule number reduced by. yyn = derives[yyn] - YYNTBASE yystate = goto_idx[yyn] + state_stack[state_ptr] if 0 <= yystate <= YYLAST and yycheck[yystate] == state_stack[state_ptr]: yystate = yytable[yystate] else: yystate = default_goto[yyn] continue elif yyn == YYFINAL: return value_stack[value_ptr-1] elif yyn <= 0: # Now it is either 0 or YYFLAG self.report_error(yystate, yyline, yycolumn, yylval) return None # Shift the lookahead token. if yychar != YYEOF: yychar = YYEMPTY value_ptr = value_ptr + 1 value_stack[value_ptr] = yylval yystate = yyn continue # should never get here return None def report_error(self, state, line, column, lval): ruleno = action_idx[state] msg = "parse error at line %d, column %d: matched '%s'" % ( line, column, lval) if YYFLAG < ruleno < YYLAST: # Start X at -ruleno to avoid negative indexes in yycheck start = ruleno < 0 and -ruleno or 0 first = 1 for x in range(start, len(token_names)): if (x + ruleno) < len(yycheck) and yycheck[x + ruleno] == x: if first: msg = msg + ", expecting" first = 0 else: msg = msg + " or" msg = msg + " '%s'" % token_names[x] self.error(msg) return def announce(self, format, *args): sys.stderr.write(format % args) return def error(self, format, *args): raise SyntaxError(format % args) def print_reduce(self, rule): sys.stderr.write("Reducing via rule %d (%s), " % (rule, rule_info[rule])) # print the symbols being reduced and their result. for token in rhs_tokens[rule]: sys.stderr.write("%s " % token_names[token]) sys.stderr.write("-> %s\n" % token_names[derives[rule]]) return def print_state_stack(self, stack, size): sys.stderr.write("state stack now") for i in range(size+1): sys.stderr.write(" %d" % stack[i]) sys.stderr.write("\n") return new = Parser # modules required for action routines from xml.xpath import ParsedAbsoluteLocationPath from xml.xpath import ParsedRelativeLocationPath from xml.xpath import ParsedPredicateList from xml.xpath import ParsedStep from xml.xpath import ParsedAxisSpecifier from xml.xpath import ParsedNodeTest from xml.xpath import ParsedAbbreviatedAbsoluteLocationPath from xml.xpath import ParsedAbbreviatedRelativeLocationPath from xml.xpath import ParsedExpr # the action code for each rule def absoluteLocationPath1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 15 absoluteLocationPath: '/' """ __val = ParsedAbsoluteLocationPath.ParsedAbsoluteLocationPath(None) return __val def absoluteLocationPath2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 24 absoluteLocationPath: '/' relativeLocationPath """ __val = ParsedAbsoluteLocationPath.ParsedAbsoluteLocationPath(__stack[__ptr+2]) return __val def relativeLocationPath2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 44 relativeLocationPath: relativeLocationPath '/' step """ __val = ParsedRelativeLocationPath.ParsedRelativeLocationPath(__stack[__ptr+1], __stack[__ptr+3]) return __val def step1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 62 step: axisSpecifier nodeTest """ __val = ParsedStep.ParsedStep(__stack[__ptr+1], __stack[__ptr+2]) return __val def step2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 72 step: axisSpecifier nodeTest predicateList """ __val = ParsedStep.ParsedStep(__stack[__ptr+1], __stack[__ptr+2], __stack[__ptr+3]) return __val def predicateList1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 90 predicateList: predicate """ __val = ParsedPredicateList.ParsedPredicateList([__stack[__ptr+1]]) return __val def predicateList2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 104 predicateList: predicateList predicate """ __stack[__ptr+1].append(__stack[__ptr+2]) __val = __stack[__ptr+1] return __val def axisSpecifier1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 121 axisSpecifier: AXIS_NAME DOUBLE_COLON """ __val = ParsedAxisSpecifier.ParsedAxisSpecifier(__stack[__ptr+1]) return __val def nodeTest1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 149 nodeTest: WILDCARD_NAME """ __val = ParsedNodeTest.ParsedNameTest(__stack[__ptr+1]) return __val def nodeTest2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 158 nodeTest: NODE_TYPE '(' ')' """ __val = ParsedNodeTest.ParsedNodeTest(__stack[__ptr+1]) return __val def nodeTest3(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 169 nodeTest: NODE_TYPE '(' LITERAL ')' """ __val = ParsedNodeTest.ParsedNodeTest(__stack[__ptr+1], __stack[__ptr+3]) return __val def predicate1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 185 predicate: '[' predicateExpr ']' """ __val = __stack[__ptr+2] return __val def abbreviatedAbsoluteLocationPath1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 208 abbreviatedAbsoluteLocationPath: DOUBLE_SLASH relativeLocationPath """ __val = ParsedAbbreviatedAbsoluteLocationPath.ParsedAbbreviatedAbsoluteLocationPath(__stack[__ptr+2]) return __val def abbreviatedRelativeLocationPath1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 224 abbreviatedRelativeLocationPath: relativeLocationPath DOUBLE_SLASH step """ __val = ParsedAbbreviatedRelativeLocationPath.ParsedAbbreviatedRelativeLocationPath(__stack[__ptr+1], __stack[__ptr+3]) return __val def abbreviatedStep1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 241 abbreviatedStep: '.' """ __val = ParsedStep.ParsedAbbreviatedStep(0) return __val def abbreviatedStep2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 250 abbreviatedStep: DOUBLE_DOT """ __val = ParsedStep.ParsedAbbreviatedStep(1) return __val def abbreviatedAxisSpecifier1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 263 abbreviatedAxisSpecifier: '@' """ __val = ParsedAxisSpecifier.ParsedAxisSpecifier("attribute") return __val def abbreviatedAxisSpecifier2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 272 abbreviatedAxisSpecifier: """ __val = ParsedAxisSpecifier.ParsedAxisSpecifier("child") return __val def primaryExpr1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 292 primaryExpr: VARIABLE_REFERENCE """ __val = ParsedExpr.ParsedVariableReferenceExpr(__stack[__ptr+1]) return __val def primaryExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 301 primaryExpr: '(' expr ')' """ __val = __stack[__ptr+2] return __val def primaryExpr3(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 313 primaryExpr: LITERAL """ __val = ParsedExpr.ParsedLiteralExpr(__stack[__ptr+1]) return __val def primaryExpr4(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 322 primaryExpr: NLITERAL """ __val = ParsedExpr.ParsedNLiteralExpr(__stack[__ptr+1]) return __val def functionCall1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 339 functionCall: FUNCTION_NAME '(' ')' """ __val = ParsedExpr.ParsedFunctionCallExpr(__stack[__ptr+1], []) return __val def functionCall2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 352 functionCall: FUNCTION_NAME '(' argumentList ')' """ __val = ParsedExpr.ParsedFunctionCallExpr(__stack[__ptr+1], __stack[__ptr+3]) return __val def argumentList1(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 368 argumentList: argument """ __val = [__stack[__ptr+1]] return __val def argumentList2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 380 argumentList: argumentList ',' argument """ __stack[__ptr+1].append(__stack[__ptr+3]) __val = __stack[__ptr+1] return __val def unionExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 409 unionExpr: unionExpr '|' pathExpr """ __val = ParsedExpr.ParsedUnionExpr(__stack[__ptr+1], __stack[__ptr+3]) return __val def pathExpr3(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 430 pathExpr: filterExpr '/' relativeLocationPath """ __val = ParsedExpr.ParsedPathExpr(__stack[__ptr+2], __stack[__ptr+1], __stack[__ptr+3]) return __val def pathExpr4(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 441 pathExpr: filterExpr DOUBLE_SLASH relativeLocationPath """ __val = ParsedExpr.ParsedPathExpr(__stack[__ptr+2], __stack[__ptr+1], __stack[__ptr+3]) return __val def filterExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 460 filterExpr: primaryExpr predicateList """ __val = ParsedExpr.ParsedFilterExpr(__stack[__ptr+1], __stack[__ptr+2]) return __val def orExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 477 orExpr: orExpr OR andExpr """ __val = ParsedExpr.ParsedOrExpr(__stack[__ptr+1], __stack[__ptr+3]) return __val def andExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 495 andExpr: andExpr AND equalityExpr """ __val = ParsedExpr.ParsedAndExpr(__stack[__ptr+1], __stack[__ptr+3]) return __val def equalityExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 513 equalityExpr: equalityExpr EQUALITY_OP relationalExpr """ __val = ParsedExpr.ParsedEqualityExpr(__stack[__ptr+2], __stack[__ptr+1], __stack[__ptr+3]) return __val def relationalExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 531 relationalExpr: relationalExpr RELATIONAL_OP additiveExpr """ ops = {'<' : 0, '>' : 2, '<=' : 1, '>=' : 3, } __val = ParsedExpr.ParsedRelationalExpr(ops[__stack[__ptr+2]], __stack[__ptr+1], __stack[__ptr+3]) return __val def additiveExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 569 additiveExpr: additiveExpr '+' multiplicativeExpr """ __val = ParsedExpr.ParsedAdditiveExpr(1, __stack[__ptr+1], __stack[__ptr+3]) return __val def additiveExpr3(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 580 additiveExpr: additiveExpr '-' multiplicativeExpr """ __val = ParsedExpr.ParsedAdditiveExpr(-1, __stack[__ptr+1], __stack[__ptr+3]) return __val def multiplicativeExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 598 multiplicativeExpr: multiplicativeExpr MULTIPLY_OPERATOR unaryExpr """ ops = {'*' : 0, 'div' : 1, 'mod' : 2, } __val = ParsedExpr.ParsedMultiplicativeExpr(ops[__stack[__ptr+2]], __stack[__ptr+1], __stack[__ptr+3]) return __val def unaryExpr2(self, __stack, __ptr): """ from XPath/XPathBase.bgen.frag, line 634 unaryExpr: '-' unionExpr """ __val = ParsedExpr.ParsedUnaryExpr(__stack[__ptr+2]) return __val action_routines = [None, None, None, absoluteLocationPath1, absoluteLocationPath2, None, None, relativeLocationPath2, None, step1, step2, None, predicateList1, predicateList2, axisSpecifier1, None, nodeTest1, nodeTest2, nodeTest3, predicate1, None, abbreviatedAbsoluteLocationPath1, abbreviatedRelativeLocationPath1, abbreviatedStep1, abbreviatedStep2, abbreviatedAxisSpecifier1, abbreviatedAxisSpecifier2, None, primaryExpr1, primaryExpr2, primaryExpr3, primaryExpr4, None, functionCall1, functionCall2, argumentList1, argumentList2, None, None, unionExpr2, None, None, pathExpr3, pathExpr4, None, filterExpr2, None, orExpr2, None, andExpr2, None, equalityExpr2, None, relationalExpr2, None, additiveExpr2, additiveExpr3, None, multiplicativeExpr2, None, unaryExpr2, ] # start condition definitions for the lexer INITIAL = 1 OPERATOR = 2 # the expressions and information for each rule import re patterns = { INITIAL : re.compile('(?P\\)|\\])|(?P::)|(?P\\.\\.)|(?P//)|(?P=|!=)|(?P<=|<|>=|>)|(?P(node|text|comment|processing-instruction)(?=\\s*\\())|(?P[a-zA-Z_][a-zA-Z0-9\\.\\-_]*(?=\\s*::))|(?P(\'[^\']*\')|("[^"]*"))|(?P(\\d+(\\.(\\d+)?)?)|(\\.\\d+))|(?P\\$([a-zA-Z_][a-zA-Z0-9\\.\\-_]*:)?[a-zA-Z_][a-zA-Z0-9\\.\\-_]*)|(?P([a-zA-Z_][a-zA-Z0-9\\.\\-_]*:)?[a-zA-Z_][a-zA-Z0-9\\.\\-_]*(?=\\s*\\())|(?P([a-zA-Z_][a-zA-Z0-9\\.\\-_]*:\\*)|(([a-zA-Z_][a-zA-Z0-9\\.\\-_]*:)?[a-zA-Z_][a-zA-Z0-9\\.\\-_]*)|\\*)|(?P[\\t\\n\\r\\s]+)|(?P.)', re.M), OPERATOR : re.compile('(?Por)|(?Pand)|(?P\\*|mod|div)|(?P[\\t\\n\\r\\s]+)|(?P.)', re.M), } pattern_actions = { 'p00' : (OPERATOR, None), 'p01' : (INITIAL, DOUBLE_COLON), 'p02' : (INITIAL, DOUBLE_DOT), 'p03' : (INITIAL, DOUBLE_SLASH), 'p04' : (INITIAL, EQUALITY_OP), 'p05' : (INITIAL, RELATIONAL_OP), 'p06' : (None, NODE_TYPE), 'p07' : (None, AXIS_NAME), 'p08' : (OPERATOR, LITERAL), 'p09' : (OPERATOR, NLITERAL), 'p10' : (OPERATOR, VARIABLE_REFERENCE), 'p11' : (None, FUNCTION_NAME), 'p12' : (OPERATOR, WILDCARD_NAME), 'p13' : None, 'p14' : (INITIAL, None), 'p15' : (INITIAL, OR), 'p16' : (INITIAL, AND), 'p17' : (INITIAL, MULTIPLY_OPERATOR), 'p18' : None, 'p19' : (INITIAL, ), } if __name__ == '__main__': import sys try: import readline except: pass try: import XPathParserc parser = XPathParserc.new(1) print 'Using C parser' except: import XPathParser parser = XPathParser.new(1) print 'Using Python parser' if len(sys.argv) > 1: result = parser.parse(sys.argv[1]) result.pprint() raise SystemExit() print 'Use -C to exit.' try: while 1: expr = raw_input('>>>') result = parser.parse(expr) result.pprint() except KeyboardInterrupt: raise SystemExit PyXML-0.8.2/xml/xpath/XPathParserBase.py0100644000076400001440000000555407356637352017233 0ustar martinuserstry: import os, gettext locale_dir = os.path.split(__file__)[0] gettext.install('4Suite', locale_dir) except (ImportError,AttributeError,IOError): def _(msg): return msg SYNTAX_ERR_MSG = _("Error parsing expression:\n'%s'\nSyntax error at or near '%s' Line: %d") INTERNAL_ERR_MSG = _("Error parsing expression:\n'%s'\nInternal error in processing at or near '%s', Line: %d, Exception: %s") class SyntaxException(Exception): def __init__(self, source, lineNum, location): Exception.__init__(self, SYNTAX_ERR_MSG%(source, location, lineNum)) self.source = source self.lineNum = lineNum self.loc = location class InternalException(Exception): def __init__(self, source, lineNum, location, exc, val, tb): Exception.__init__(self, INTERNAL_ERR_MSG%(source, location, lineNum, exc)) self.source = source self.lineNum = lineNum self.loc = location self.errorType = exc self.errorValue = val self.errorTraceback = tb class XPathParserBase: def __init__(self): self.initialize() def initialize(self): self.results = None self.__stack = [] XPath.cvar.g_errorOccured = 0 def parse(self,st): g_parseLock.acquire() try: self.initialize() XPath.my_XPathparse(self,st) if XPath.cvar.g_errorOccured == 1: raise SyntaxException( st, XPath.cvar.lineNum, XPath.cvar.g_errorLocation) if XPath.cvar.g_errorOccured == 2: raise InternalException( st, XPath.cvar.lineNum, XPath.cvar.g_errorLocation, XPath.cvar.g_errorType, XPath.cvar.g_errorValue, XPath.cvar.g_errorTraceback) return self.__stack finally: g_parseLock.release() def pop(self): if len(self.__stack): rt = self.__stack[-1] del self.__stack[-1] return rt self.raiseException("Pop with 0 stack length") def push(self,item): self.__stack.append(item) def empty(self): return len(self.__stack) == 0 def size(self): return len(self.__stack) def raiseException(self, message): raise Exception(message) ### Callback methods ### def PrintSyntaxException(e): print "********** Syntax Exception **********" print "Exception at or near '%s'" % e.loc print " Line: %d" % (e.lineNum) def PrintInternalException(e): print "********** Internal Exception **********" print "Exception at or near '%s'" % e.loc print " Line: %d" % (e.lineNum) print " Exception: %s" % e.errorType print "Original traceback:" import traceback traceback.print_tb(e.errorTraceback) PyXML-0.8.2/xml/xpath/__init__.py0100644000076400001440000000627607537736455016005 0ustar martinusers######################################################################## # # File Name: __init__.py # # Documentation: http://docs.4suite.org/4Path/__init__.py.html # """ WWW: http://4suite.org/4XPath e-mail: support@4suite.org Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ NAMESPACE_NODE = 10000 FT_OLD_EXT_NAMESPACE = 'http://xmlns.4suite.org/xpath/extensions' FT_EXT_NAMESPACE = 'http://xmlns.4suite.org/ext' # Simple trick (thanks Tim Peters) to enable crippled IEEE 754 support # until ANSI C (or Python) sorts it all out... Inf = Inf = 1e300 * 1e300 NaN = Inf - Inf from xml.dom import Node from xml.FtCore import FtException g_xpathRecognizedNodes = [ Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.DOCUMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE ] g_extFunctions = {} class CompiletimeException(FtException): INTERNAL = 1 SYNTAX = 2 PROCESSING = 3 def __init__(self, errorCode, *args): FtException.__init__(self, errorCode, MessageSource.COMPILETIME, args) class RuntimeException(FtException): INTERNAL = 1 NO_CONTEXT = 10 UNDEFINED_VARIABLE = 100 UNDEFINED_PREFIX = 101 WRONG_ARGUMENTS = 200 def __init__(self, errorCode, *args): FtException.__init__(self, errorCode, MessageSource.RUNTIME, args) from XPathParserBase import SyntaxException import MessageSource def Evaluate(expr, contextNode=None, context=None): import os if os.environ.has_key('EXTMODULES'): RegisterExtensionModules(os.environ["EXTMODULES"].split(':')) if context: con = context elif contextNode: con = Context.Context(contextNode, 0, 0) else: raise RuntimeException(RuntimeException.NO_CONTEXT_ERROR) retval = parser.new().parse(expr).evaluate(con) return retval def Compile(expr): try: return parser.new().parse(expr) except SyntaxError, error: raise CompiletimeException(CompiletimeException.SYNTAX, str(error)) except: import traceback, cStringIO stream = cStringIO.StringIO() traceback.print_exc(None, stream) raise RuntimeException(RuntimeException.INTERNAL, stream.getvalue()) def CreateContext(contextNode): return Context.Context(contextNode, 0, 0) def RegisterExtensionModules(moduleNames): mod_names = moduleNames[:] mods = [] for mod_name in mod_names: if mod_name: mod = __import__(mod_name,{},{},['ExtFunctions']) if hasattr(mod,'ExtFunctions'): g_extFunctions.update(mod.ExtFunctions) mods.append(mod) return mods #Allow access to the NormalizeNode function from Util import NormalizeNode import Context try: import XPathParserc except ImportError: #import XPathParser #parser = XPathParser from pyxpath import ExprParserFactory parser = ExprParserFactory else: parser = XPathParserc def Init(): from xml.xpath import BuiltInExtFunctions g_extFunctions.update(BuiltInExtFunctions.ExtFunctions) Init() PyXML-0.8.2/xml/xpath/pyxpath.py0100644000076400001440000002602007406341655015715 0ustar martinusers# Expression types ABSOLUTE_LOCATION_PATH = 1 ABBREVIATED_ABSOLUTE_LOCATION_PATH = 2 RELATIVE_LOCATION_PATH = 3 ABBREVIATED_RELATIVE_LOCATION_PATH = 4 STEP_EXPR = 5 NODE_TEST = 6 NAME_TEST = 7 BINARY_EXPR = 8 UNARY_EXPR = 9 PATH_EXPR = 10 ABBREVIATED_PATH_EXPR = 11 FILTER_EXPR = 12 VARIABLE_REFERENCE = 13 LITERAL = 14 NUMBER = 15 FUNCTION_CALL = 16 # Axis specifier ANCESTOR_AXIS = 1 ANCESTOR_OR_SELF_AXIS = 2 ATTRIBUTE_AXIS = 3 CHILD_AXIS = 4 DESCENDANT_AXIS = 5 DESCENDANT_OR_SELF_AXIS = 6 FOLLOWING_AXIS = 7 FOLLOWING_SIBLING_AXIS = 8 NAMESPACE_AXIS = 9 PARENT_AXIS = 10 PRECEDING_AXIS = 11 PRECEDING_SIBLING_AXIS = 12 SELF_AXIS = 13 # Node tests COMMENT = 1 TEXT = 2 PROCESSING_INSTRUCTION = 3 NODE = 4 # Binary operators OR_OPERATOR = 1 AND_OPERATOR = 2 EQ_OPERATOR = 3 NEQ_OPERATOR = 4 LT_OPERATOR = 5 GT_OPERATOR = 6 LE_OPERATOR = 7 GE_OPERATOR = 8 PLUS_OPERATOR = 9 MINUS_OPERATOR = 10 TIMES_OPERATOR = 11 DIV_OPERATOR = 12 MOD_OPERATOR = 13 UNION_OPERATOR = 14 from xml.xpath import ParsedExpr, ParsedNodeTest from xml.xpath.ParsedAbsoluteLocationPath import ParsedAbsoluteLocationPath from xml.xpath.ParsedRelativeLocationPath import ParsedRelativeLocationPath from xml.xpath.ParsedAbbreviatedRelativeLocationPath import ParsedAbbreviatedRelativeLocationPath from xml.xpath.ParsedAbbreviatedAbsoluteLocationPath import ParsedAbbreviatedAbsoluteLocationPath PALP = ParsedAbsoluteLocationPath PRLP = ParsedRelativeLocationPath PAALP = ParsedAbbreviatedAbsoluteLocationPath PARLP = ParsedAbbreviatedRelativeLocationPath from xml.xpath.ParsedStep import ParsedStep from xml.xpath.ParsedAxisSpecifier import ParsedAxisSpecifier from xml.xpath.ParsedPredicateList import ParsedPredicateList from xml.xpath.ParsedAbsoluteLocationPath import ParsedAbsoluteLocationPath from xml.xpath.ParsedRelativeLocationPath import ParsedRelativeLocationPath # XSLT try: from xml.xslt.ParsedPattern import ParsedPattern from xml.xslt import ParsedStepPattern from xml.xslt import ParsedRelativePathPattern from xml.xslt import ParsedLocationPathPattern _xslt_patterns = 1 except: _xslt_patterns = 0 import string,types class FtFactory: createAbsoluteLocationPath = PALP createAbbreviatedAbsoluteLocationPath = PAALP createRelativeLocationPath = PRLP createAbbreviatedRelativeLocationPath = PARLP def createStep(self, axis, test, predicates): return ParsedStep(axis, test, ParsedPredicateList(predicates)) def createAbbreviatedStep(self,parent): if parent: type = 'parent' else: type = 'self' return ParsedStep(ParsedAxisSpecifier(type), ParsedNodeTest.ParsedNodeTest('node',""), ParsedPredicateList([])) axisMap = { ANCESTOR_AXIS: 'ancestor', ANCESTOR_OR_SELF_AXIS: 'ancestor-or-self', ATTRIBUTE_AXIS: 'attribute', CHILD_AXIS: 'child', DESCENDANT_AXIS: 'descendant', DESCENDANT_OR_SELF_AXIS: 'descendant-or-self', FOLLOWING_AXIS: 'following', FOLLOWING_SIBLING_AXIS: 'following-sibling', NAMESPACE_AXIS: 'namespace', PARENT_AXIS: 'parent', PRECEDING_AXIS: 'preceding', PRECEDING_SIBLING_AXIS: 'preceding-sibling', SELF_AXIS: 'self' } def createAxisSpecifier(self,axis): # XXX: may use axis-ANCESTOR+XPATH.ANCESTOR instead return ParsedAxisSpecifier(self.axisMap[axis]) ntMap = { COMMENT: 'comment', TEXT: 'text', PROCESSING_INSTRUCTION: 'processing-instruction', NODE: 'node' } def createNodeTest(self,type,val): if val is None: val = "" return ParsedNodeTest.ParsedNodeTest(self.ntMap[type],val) def createNameTest(self,prefix,local): if local == '*': if prefix: return ParsedNodeTest.LocalNameTest(prefix) else: return ParsedNodeTest.PrincipalTypeTest() if prefix: return ParsedNodeTest.QualifiedNameTest(prefix, local) return ParsedNodeTest.NodeNameTest(local) opMap = { OR_OPERATOR: ParsedExpr.ParsedOrExpr, AND_OPERATOR: ParsedExpr.ParsedAndExpr, EQ_OPERATOR: (ParsedExpr.ParsedEqualityExpr,"="), NEQ_OPERATOR: (ParsedExpr.ParsedEqualityExpr, "!="), LT_OPERATOR: (ParsedExpr.ParsedRelationalExpr, 0), GT_OPERATOR: (ParsedExpr.ParsedRelationalExpr, 2), LE_OPERATOR: (ParsedExpr.ParsedRelationalExpr, 1), GE_OPERATOR: (ParsedExpr.ParsedRelationalExpr, 3), PLUS_OPERATOR: (ParsedExpr.ParsedAdditiveExpr, 1), MINUS_OPERATOR: (ParsedExpr.ParsedAdditiveExpr, -1), TIMES_OPERATOR: (ParsedExpr.ParsedMultiplicativeExpr, 0), DIV_OPERATOR: (ParsedExpr.ParsedMultiplicativeExpr, 1), MOD_OPERATOR: (ParsedExpr.ParsedMultiplicativeExpr, 2), UNION_OPERATOR: ParsedExpr.ParsedUnionExpr, } def createNumericExpr(self,operator,left,right): if operator == MINUS_OPERATOR and right is None: return ParsedExpr.ParsedUnaryExpr(left) cl = self.opMap[operator] if type(cl) is types.TupleType: return cl[0](cl[1],left,right) return cl(left,right) def createBooleanExpr(self,operator,left,right): cl = self.opMap[operator] if type(cl) is types.TupleType: return cl[0](cl[1],left,right) return cl(left,right) def createPathExpr(self,left,right): return ParsedExpr.ParsedPathExpr("/",left,right) def createAbbreviatedPathExpr(self,left,right): return ParsedExpr.ParsedPathExpr(XPATH.DOUBLE_SLASH,left,right) def createFilterExpr(self, filter, predicates): return ParsedExpr.ParsedFilterExpr(filter, ParsedPredicateList(predicates)) def createVariableReference(self,prefix,localName): if prefix: return ParsedExpr.ParsedVariableReferenceExpr('$'+prefix+':'+localName) else: return ParsedExpr.ParsedVariableReferenceExpr('$'+localName) createLiteral = ParsedExpr.ParsedLiteralExpr createNumber = ParsedExpr.ParsedNLiteralExpr # Cannot directly import, since ParsedNLiteralExpr is a function def createFunctionCall(self,prefix,localName,args): if prefix: return ParsedExpr.ParsedFunctionCallExpr(prefix+':'+localName,args) else: return ParsedExpr.ParsedFunctionCallExpr(localName,args) # XSLT if _xslt_patterns: createPattern = ParsedPattern def createLocationPathPattern(self, idkey, isparent, step): if idkey is None and step is None: # / return ParsedLocationPathPattern.RootPattern() if step is None: # idkey return ParsedLocationPathPattern.IdKeyPattern(idkey) if not isparent and idkey is None: # rel # // rel return step last = step while 1: parent = last.parent if hasattr(parent,"parent"): last = parent else: break if isparent and idkey is None: # / rel ctor = ParsedStepPattern.RootParentStepPattern args = () elif isparent: # idkey / rel ctor = ParsedLocationPathPattern.IdKeyParentPattern args = (idkey,) else: # idkey // rel args = (idkey,) if parent is None: ctor = ParsedLocationPathPattern.IdKeyParentPattern else: ctor = ParsedLocationPathPattern.IdKeyAncestorPattern if parent is None: step = apply(ctor, args+last.getShortcut()) else: last.parent = apply(ctor, args+last.parentAxis()) return step def createRelativePathPattern(self, rel, parent, step): parent_test, parent_axis = rel.getShortcut() node_test, axis_type = step.getShortcut() if parent: ctor = ParsedStepPattern.ParentStepPattern else: ctor = ParsedStepPattern.AncestorStepPattern return ctor(node_test, axis_type, parent_test, parent_axis) def createStepPattern(self, axis, test, predicates): axis = axis.principalType if predicates: predicates = ParsedPredicateList(predicates) return ParsedStepPattern.PredicateStepPattern(test, axis, predicates) else: return ParsedStepPattern.StepPattern(test, axis) factory = FtFactory() import yappsrt class SyntaxError(yappsrt.SyntaxError): def __init__(self, pos, msg, str): yappsrt.SyntaxError.__init__(self, pos, msg) self.str = str def __repr__(self): if self.pos < 0: return "#" else: text = self.str if len(self.str) > 30: start = self.pos - 15 if start>3: text = "..."+self.str[start:] if len(text) > 30: text = text[:27]+"..." fmt = "SyntaxError[@ char %s in '%s': %s]" return fmt % (repr(self.pos), text, self.msg) #obsolete class Parser: def parseLocationPath(self, str): try: from XPathGrammar import XPath,XPathScanner return XPath(XPathScanner(str),factory).Start() except yappsrt.SyntaxError,e: raise SyntaxError(e.pos, e.msg, str) def parseExpr(self, str): try: from XPathGrammar import XPath,XPathScanner return XPath(XPathScanner(str),factory).FullExpr() except yappsrt.SyntaxError,e: raise SyntaxError(e.pos, e.msg, str) def parsePattern(self, str): try: from XPathGrammar import XPath,XPathScanner return XPath(XPathScanner(str),factory).FullPattern() except yappsrt.SyntaxError,e: raise SyntaxError(e.pos, e.msg, str) parser = Parser() def Compile(str): return parser.parseExpr(str) def CompilePattern(str): return parser.parsePattern(str) class Factory: def __init__(self, cl): self.new = cl class ExprParser: def parse(self, str): try: from XPathGrammar import XPath,XPathScanner return XPath(XPathScanner(str),factory).FullExpr() except yappsrt.SyntaxError,e: raise SyntaxError(e.pos, e.msg, str) ExprParserFactory = Factory(ExprParser) class PatternParser: def parse(self, str): try: from XPathGrammar import XPath,XPathScanner return XPath(XPathScanner(str),factory).FullPattern() except yappsrt.SyntaxError,e: raise SyntaxError(e.pos, e.msg, str) PatternParserFactory = Factory(PatternParser) PyXML-0.8.2/xml/xpath/yappsrt.py0100644000076400001440000001413407614723023015717 0ustar martinusers# Yapps 2.0 Runtime # # This module is needed to run generated parsers. # from string import * # import exceptions import re class SyntaxError(Exception): """When we run into an unexpected token, this is the exception to use""" def __init__(self, pos=-1, msg="Bad Token"): Exception.__init__(self) self.pos = pos self.msg = msg def __repr__(self): if self.pos < 0: return "#" else: return "SyntaxError[@ char " + `self.pos` + ": " + self.msg + "]" __str__ = __repr__ class NoMoreTokens(Exception): """Another exception object, for when we run out of tokens""" pass class Scanner: def __init__(self, patterns, ignore, input): """Patterns is [(terminal,regex)...] Ignore is [terminal,...]; Input is a string""" self.tokens = [] self.restrictions = [] self.input = input self.pos = 0 self.ignore = ignore # The stored patterns are a pair (compiled regex,source # regex). If the patterns variable passed in to the # constructor is None, we assume that the class already has a # proper .patterns list constructed if patterns is not None: self.patterns = [] for k,r in patterns: self.patterns.append( (k, re.compile(r)) ) def token(self, i, restrict=0): """Get the i'th token, and if i is one past the end, then scan for another token; restrict is a list of tokens that are allowed, or 0 for any token.""" if i == len(self.tokens): self.scan(restrict) if i < len(self.tokens): # Make sure the restriction is more restricted if restrict and self.restrictions[i]: for r in restrict: if r not in self.restrictions[i]: raise "Unimplemented: restriction set changed" return self.tokens[i] raise NoMoreTokens() def __repr__(self): """Print the last 10 tokens that have been scanned in""" output = '' for t in self.tokens[-10:]: output = '%s\n (@%s) %s = %s' % (output,t[0],t[2],`t[3]`) return output def scan(self, restrict): """Should scan another token and add it to the list, self.tokens, and add the restriction to self.restrictions""" # Keep looking for a token, ignoring any in self.ignore while 1: # Search the patterns for the longest match, with earlier # tokens in the list having preference best_match = -1 best_pat = '(error)' for p, regexp in self.patterns: # First check to see if we're ignoring this token if restrict and p not in restrict and p not in self.ignore: continue m = regexp.match(self.input, self.pos) if m and len(m.group(0)) > best_match: # We got a match that's better than the previous one best_pat = p best_match = len(m.group(0)) # If we didn't find anything, raise an error if best_pat == '(error)' and best_match < 0: msg = "Bad Token" if restrict: msg = "Trying to find one of "+join(restrict,", ") raise SyntaxError(self.pos, msg) # If we found something that isn't to be ignored, return it if best_pat not in self.ignore: # Create a token with this data token = (self.pos, self.pos+best_match, best_pat, self.input[self.pos:self.pos+best_match]) self.pos = self.pos + best_match # Only add this token if it's not in the list # (to prevent looping) if not self.tokens or token != self.tokens[-1]: self.tokens.append(token) self.restrictions.append(restrict) return else: # This token should be ignored .. self.pos = self.pos + best_match class Parser: def __init__(self, scanner): self._scanner = scanner self._pos = 0 def _peek(self, *types): """Returns the token type for lookahead; if there are any args then the list of args is the set of token types to allow""" tok = self._scanner.token(self._pos, types) return tok[2] def _scan(self, type): """Returns the matched text, and moves to the next token""" tok = self._scanner.token(self._pos, [type]) if tok[2] != type: raise SyntaxError(tok[0], 'Trying to find '+type) self._pos = 1+self._pos return tok[3] def print_error(input, err, scanner): """This is a really dumb long function to print error messages nicely.""" p = err.pos # Figure out the line number line = count(input[:p], '\n') print err.msg+" on line "+`line+1`+":" # Now try printing part of the line text = input[max(p-80,0):p+80] p = p - max(p-80,0) # Strip to the left i = rfind(text[:p],'\n') j = rfind(text[:p],'\r') if i < 0 or (j < i and j >= 0): i = j if i >= 0 and i < p: p = p - i - 1 text = text[i+1:] # Strip to the right i = find(text,'\n',p) j = find(text,'\r',p) if i < 0 or (j < i and j >= 0): i = j if i >= 0: text = text[:i] # Now shorten the text while len(text) > 70 and p > 60: # Cut off 10 chars text = "..." + text[10:] p = p - 7 # Now print the string, along with an indicator print '> ',text print '> ',' '*p + '^' print 'List of nearby tokens:', scanner def wrap_error_reporter(parser, rule): try: return getattr(parser, rule)() except SyntaxError, s: input = parser._scanner.input try: print_error(input, s, parser._scanner) except ImportError: print 'Syntax Error',s.msg,'on line',1+count(input[:s.pos], '\n') except NoMoreTokens: print 'Could not complete parsing; stopped around here:' print parser._scanner PyXML-0.8.2/xml/xslt/0040755000076400001440000000000007614726124013516 5ustar martinusersPyXML-0.8.2/xml/xslt/ApplyTemplatesElement.py0100644000076400001440000000723107377133277020355 0ustar martinusers######################################################################## # # File Name: ApplyTemplatesElement.py # # Documentation: http://docs.4suite.com/4XSLT/ApplyTemplatesElement.py.html # """ Implementation of the XSLT Spec apply-templates stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.Element import xml.dom.ext import xml.xslt from xml.xslt import XsltElement, XSL_NAMESPACE, XsltException, Error from xml.xpath import XPathParser from xml.xpath import Util, g_xpathRecognizedNodes class ApplyTemplatesElement(XsltElement): legalAttrs = ['select', 'mode'] def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='apply-templates', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) mode_attr = self.getAttributeNS(EMPTY_NAMESPACE, 'mode') if mode_attr == '': self.__dict__['_mode'] = None else: split_name = Util.ExpandQName( mode_attr, namespaces=self._nss ) self.__dict__['_mode'] = split_name select = self.getAttributeNS(EMPTY_NAMESPACE, 'select') if select: parser = XPathParser.XPathParser() self.__dict__['_expr'] = parser.parseExpression(select) else: self.__dict__['_expr'] = None self.__dict__['_sortSpecs'] = [] self.__dict__['_params'] = [] for child in self.childNodes: #All children should be sort and with-param if child.namespaceURI == XSL_NAMESPACE: if child.localName == 'sort': self._sortSpecs.append(child) elif child.localName == 'with-param': self._params.append(child) else: raise XsltException(Error.ILLEGAL_APPLYTEMPLATE_CHILD) else: raise XsltException(Error.ILLEGAL_APPLYTEMPLATE_CHILD) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) params = {} mode = self._instantiateMode(context) for param in self._params: (name, value) = param.instantiate(context, processor)[1] params[name] = value if self._expr: node_set = self._expr.evaluate(context) else: node_set = context.node.childNodes size = len(node_set) if size > 1 and len(self._sortSpecs): node_set = self._sortSpecs[0].instantiate(context, processor, node_set, self._sortSpecs[1:])[1] pos = 1 for node in node_set: context.setNodePosSize((node,pos,size)) processor.applyTemplates(context, mode, params) pos = pos + 1 context.set(origState) return (context,) def _instantiateMode(self,context): return self._mode def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._sortSpecs, self._params,self._expr,self._mode) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._sortSpecs = state[2] self._params = state[3] self._expr = state[4] self._mode = state[5] return PyXML-0.8.2/xml/xslt/AttributeElement.py0100644000076400001440000000545507377133277017362 0ustar martinusers######################################################################## # # File Name: AttributeElement.py # # Documentation: http://docs.4suite.com/4XSLT/AttributeElement.py.html # """ Implementation of the XSLT Spec element stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999 FourThought LLC, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import cStringIO from xml.dom import EMPTY_NAMESPACE import xml.dom.Element import xml.dom.ext import xml.xslt from xml.xslt import XsltElement, XsltException, Error from xml.xslt.AttributeValueTemplate import AttributeValueTemplate from xml.xpath import Conversions #FIXME: Add check for Attribute inside an Element. class AttributeElement(XsltElement): legalAttrs = ('name', 'namespace') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='attribute', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): name = self.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XsltException(Error.ATTRIBUTE_MISSING_NAME) self._name = AttributeValueTemplate(name) namespace = self.getAttributeNS(EMPTY_NAMESPACE, 'namespace') self._namespace = AttributeValueTemplate(namespace) self._nss = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) name = self._name.evaluate(context) namespace = self._namespace.evaluate(context) (prefix, local) = xml.dom.ext.SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] if local == 'xmlns': name = prefix #FIXME: Add error checking of child nodes processor.pushResult() for child in self.childNodes: context = child.instantiate(context, processor)[0] rtf = processor.popResult() value = Conversions.StringValue(rtf) processor.writers[-1].attribute(name, value, namespace) processor.releaseRtf(rtf) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name, self._namespace) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._name = state[2] self._namespace = state[3] return PyXML-0.8.2/xml/xslt/AttributeSetElement.py0100644000076400001440000000641707377133277020035 0ustar martinusers######################################################################## # # File Name: AttributeSetElement.py # # Documentation: http://docs.4suite.com/4XSLT/AttributeSetElement.py.html # """ Implementation of the XSLT Spec attribute-set stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import EMPTY_NAMESPACE import xml.dom.Element import xml.dom.ext import xml.xslt from xml.xslt import XsltElement, XsltException, Error from xml.xpath import Util class AttributeSetElement(XsltElement): legalAttrs = ['name', 'use-attribute-sets'] def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='attribute-set', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_name'] = self.getAttributeNS(EMPTY_NAMESPACE, 'name') if not self._name: raise XsltException(Error.ATTRIBUTESET_REQUIRES_NAME) self.__dict__['_useAttributeSets'] = string.splitfields(self.getAttributeNS(EMPTY_NAMESPACE, 'use-attribute-sets')) self.__dict__['_varBindings'] = {} self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) #Check that all children are attribute instructions for child in self.childNodes: if (child.namespaceURI, child.localName) != (xml.xslt.XSL_NAMESPACE, 'attribute'): raise XsltException(Error.ILLEGAL_ATTRIBUTESET_CHILD) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) split_name = Util.ExpandQName(self._name, namespaces=self._nss) processor.attributeSets[split_name] = self self._varBindings = context.varBindings context.set(origState) return (context,) def use(self, context, processor, used=None): if used is None: used = [] origState = context.copy() context.varBindings = self._varBindings for attr_set_name in self._useAttributeSets: split_name = Util.ExpandQName(attr_set_name, namespaces=context.processorNss) try: attr_set = processor.attributeSets[split_name] except KeyError: raise XsltException(Error.UNDEFINED_ATTRIBUTE_SET, attr_set_name) attr_set.use(context, processor) for child in self.childNodes: context = child.instantiate(context, processor)[0] context.set(origState) return context def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name, self._useAttributeSets, self._varBindings) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._name = state[2] self._useAttributeSets = state[3] self._varBindings = state[4] return PyXML-0.8.2/xml/xslt/AttributeValueTemplate.py0100644000076400001440000000667007255677344020544 0ustar martinusers######################################################################## # # File Name: AttributeValueTemplate.py # # Docs: http://docs.4suite.com/4XSLT/AttributeValueTemplate.py.html # """ Implementation of AVTs from the XSLT Spec. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import re, string from xml.xslt import XsltException, Error from xml.xpath import XPathParser, Conversions g_braceSplitPattern = re.compile(r'([\{\}])') class AttributeValueTemplate: def __init__(self, source,reparse = 1): self.source = source if reparse: self._plainParts = [] self._parsedParts = [] self._parse() def _parse(self): parser = XPathParser.XPathParser() curr_plain_part = '' curr_template_part = '' in_plain_part = 1 split_form = re.split(g_braceSplitPattern, self.source) skip_flag = 0 for i in range(len(split_form)): segment = split_form[i] if skip_flag: skip_flag = skip_flag - 1 continue if segment in ['{', '}']: #Here we are accounting for a possible blank segment in between try: next = split_form[i + 1] + split_form[i + 2] except IndexError: next = None if next == segment: if in_plain_part: curr_plain_part = curr_plain_part + segment else: curr_template_part = curr_template_part + segment skip_flag = 2 elif segment == '{': if in_plain_part: self._plainParts.append(curr_plain_part) in_plain_part = 0 curr_plain_part = '' else: raise XsltException(Error.AVT_SYNTAX) else: if not in_plain_part: parsed = parser.parseExpression(curr_template_part) self._parsedParts.append(parsed) in_plain_part = 1 curr_template_part = '' else: raise XsltException(Error.AVT_SYNTAX) else: if in_plain_part: curr_plain_part = curr_plain_part + segment else: curr_template_part = curr_template_part + segment if in_plain_part: self._plainParts.append(curr_plain_part) else: raise XsltException(Error.AVT_SYNTAX) def evaluate(self, context): result = '' expansions = map( lambda x, c=context: Conversions.StringValue(x.evaluate(c)), self._parsedParts ) for i in range(len(self._parsedParts)): result = result + self._plainParts[i] + expansions[i] result = result + self._plainParts[-1] return result def __repr__(self): return self.source def __getinitargs__(self): return (self.source, 0) def __getstate__(self): return (self._plainParts,self._parsedParts) def __setstate__(self, state): # Nothing to do self._plainParts,self._parsedParts = state PyXML-0.8.2/xml/xslt/BuiltInExtElements.py0100644000076400001440000001636707377133277017635 0ustar martinusers######################################################################## # # File Name: FtElements.py # # Documentation: http://docs.4suite.com/4XSLT/FtElements.py.html # """ FourThought proprietary extension elements WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.ext from xml.xslt import XsltElement, XsltException, Error from xml.xslt import XSL_NAMESPACE from xml.xslt import AttributeValueTemplate, OutputParameters, TextWriter from xml.xpath import Util, FT_EXT_NAMESPACE, XPathParser from xml.xslt import ApplyTemplatesElement class FtApplyTemplates(ApplyTemplatesElement.ApplyTemplatesElement): def setup(self): ApplyTemplatesElement.ApplyTemplatesElement.setup(self) #Overwrite the mode mode_attr = self.getAttributeNS(EMPTY_NAMESPACE, 'mode') if mode_attr != '': parser = XPathParser.XPathParser() self.__dict__['_mode'] = parser.parseExpression(mode_attr) def _instantiateMode(self,context): rt = self._mode.evaluate(context) split_name = Util.ExpandQName( rt, namespaces=self._nss ) return split_name class WriteFileElement(XsltElement): def __init__(self, doc, uri=FT_EXT_NAMESPACE, localName='write-file', prefix='ft', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) self.__dict__['_name'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'name')) self.__dict__['_overwrite'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'overwrite')) out = OutputParameters() for child in self.childNodes: if (child.namespaceURI, child.localName) == (FT_EXT_NAMESPACE, 'output'): method = child.getAttributeNS(EMPTY_NAMESPACE, 'method') if method: out.method = method version = child.getAttributeNS(EMPTY_NAMESPACE, 'version') if version: out.version = version encoding = child.getAttributeNS(EMPTY_NAMESPACE, 'encoding') if encoding: out.encoding = encoding omit_xml_decl = child.getAttributeNS(EMPTY_NAMESPACE, 'omit-xml-declaration') if omit_xml_decl: out.omitXmlDeclaration = omit_xml_decl standalone = child.getAttributeNS(EMPTY_NAMESPACE, 'standalone') if standalone: out.standalone = standalone doctype_system = child.getAttributeNS(EMPTY_NAMESPACE, 'doctype-system') if doctype_system: out.doctypeSystem = doctype_system doctype_public = child.getAttributeNS(EMPTY_NAMESPACE, 'doctype-public') if doctype_public: out.doctypePublic = doctype_public media_type = child.getAttributeNS(EMPTY_NAMESPACE, 'media-type') if media_type: out.mediaType = media_type cdata_sec_elem = child.getAttributeNS(EMPTY_NAMESPACE, 'cdata-section-elements') if cdata_sec_elem: out.cdataSectionElements = cdata_sec_elem indent = child.getAttributeNS(EMPTY_NAMESPACE, 'indent') if indent: out.indent = indent self.__dict__['_outputParams'] = out return def instantiate(self, context, processor): origState = context.copy() context.processorNss = self._nss name = self._name.evaluate(context) overwrite = self._overwrite.evaluate(context) if overwrite == 'yes': f = open(name, 'w') else: f = open(name, 'a') processor.addHandler(self._outputParams, f) for child in self.childNodes: context = child.instantiate(context, processor)[0] processor.removeHandler() f.close() context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name,self._overwrite,self._outputParams) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._name = state[2] self._overwrite = state[3] self._outputParams = state[4] return class FtOutputElement(XsltElement): def __init__(self, doc, uri=FT_EXT_NAMESPACE, localName='output', prefix='ft', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): return def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) class MessageOutputElement(XsltElement): def __init__(self, doc, uri=FT_EXT_NAMESPACE, localName='message-output', prefix='ft', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): #FIXME: disable -> silent self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) if self.getAttributeNS(EMPTY_NAMESPACE, 'file'): self.__dict__['_file'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'file')) else: self.__dict__['_file'] = None if self.getAttributeNS(EMPTY_NAMESPACE, 'disable'): self.__dict__['_disable'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'disable')) else: self.__dict__['_disable'] = None if self.getAttributeNS(EMPTY_NAMESPACE, 'overwrite'): self.__dict__['_overwrite'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'overwrite')) else: self.__dict__['_overwrite'] = None return def instantiate(self, context, processor): if self._file: processor.setMessageFile(self._file.evaluate(context)) if self._disabled: processor._messagesEnabled = self._disabled.evaluate(context) == yes if self._overwrite == 'yes': f = open(name, 'w') else: f = open(name, 'a') return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name,self._overwrite,self._outputParams) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._file = state[2] self._silent = state[3] return ExtElements = { (FT_EXT_NAMESPACE, 'apply-templates'): FtApplyTemplates, (FT_EXT_NAMESPACE, 'output'): FtOutputElement, (FT_EXT_NAMESPACE, 'write-file'): WriteFileElement, (FT_EXT_NAMESPACE, 'message-output'): MessageOutputElement, } PyXML-0.8.2/xml/xslt/CallTemplateElement.py0100644000076400001440000000751107377133277017761 0ustar martinusers######################################################################## # # File Name: CallTemplateElement.py # # Documentation: http://docs.4suite.com/4XSLT/CallTemplateElement.py.html # """ Implementation of the XSLT Spec call-template stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE from xml.dom import Node import xml.dom.ext import xml.xslt from xml.xslt import XsltElement, XsltException, Error, XSL_NAMESPACE from xml.xpath import Util class CallTemplateElement(XsltElement): legalAttrs = ('name', ) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='call-template', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) split_name = Util.ExpandQName( self.getAttributeNS(EMPTY_NAMESPACE, 'name'), namespaces=self._nss ) self.__dict__['_name'] = split_name self.__dict__['_tailRecursive'] = "unknown" self.__dict__['_params'] = filter(lambda node: node.nodeType == Node.ELEMENT_NODE, self.childNodes) for child in self.__dict__['_params']: if child.nodeType == Node.ELEMENT_NODE: if child.namespaceURI == XSL_NAMESPACE: if child.localName != 'with-param': raise XsltException(Error.ILLEGAL_CALLTEMPLATE_CHILD) else: raise XsltException(Error.ILLEGAL_CALLTEMPLATE_CHILD) return def instantiate(self, context, processor, new_level=1): if self._tailRecursive == 'unknown': self.__dict__['_tailRecursive'] = CheckTailRecursion(self, self._name) origState = context.copy() context.setNamespaces(self._nss) params = {} for child in self._params: param = child.instantiate(context, processor)[1] params[param[0]] = param[1] if self._tailRecursive: if not new_level: context.set(origState) return (context, params) while params is not None: params = processor.callTemplate(self._name, context, params, 0) if params: context.varBindings.update(params) else: processor.callTemplate(self._name, context, params, 1) context.set(origState) return (context, None) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name, self._tailRecursive, self._params) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._name = state[2] self._tailRecursive = state[3] self._params = state[4] return def CheckTailRecursion(node, name): if node.nextSibling and node.nodeType == Node.ELEMENT_NODE: return 0 p = node.nodeType == Node.ATTRIBUTE_NODE and node.ownerElement or node.parentNode if p and p.nodeType == Node.ELEMENT_NODE and p.namespaceURI == XSL_NAMESPACE: if p.localName in ['if', 'choose']: return CheckTailRecursion(p, name) elif p.localName == 'template' and name == p._name: return 1 return 0 PyXML-0.8.2/xml/xslt/ChooseElement.py0100644000076400001440000000550607255676734016641 0ustar martinusers######################################################################## # # File Name: ChooseElement.py # # Documentation: http://docs.4suite.com/4XSLT/ChooseElement.py.html # """ Implementation of the XSLT Spec choose instruction WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import xml.dom.ext from xml.xslt import XSL_NAMESPACE from xml.xslt import XsltElement, XsltException, Error from xml.xslt.WhenElement import WhenElement from xml.xslt.OtherwiseElement import OtherwiseElement from xml.xpath import CoreFunctions from xml.dom import Node class ChooseElement(XsltElement): legalAttrs = () def __init__(self, doc, uri=XSL_NAMESPACE, localName='choose', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) when_other_allowed = 1 when_found = 0 for child in self.childNodes: if child.nodeType == Node.ELEMENT_NODE: if child.namespaceURI == XSL_NAMESPACE: if child.localName == 'when': when_found = 1 if not when_other_allowed: raise XsltException(Error.CHOOSE_WHEN_AFTER_OTHERWISE) elif child.localName == 'otherwise': if when_other_allowed: when_other_allowed = 0 else: raise XsltException(Error.CHOOSE_MULTIPLE_OTHERWISE) else: raise XsltException(Error.ILLEGAL_CHOOSE_CHILD) else: raise XsltException(Error.ILLEGAL_CHOOSE_CHILD) if not when_found: raise XsltException(Error.CHOOSE_REQUIRES_WHEN_CHILD) return def instantiate(self, context, processor, new_level=1): origState = context.copy() context.setNamespaces(self._nss) rec_tpl_params = None for child in self.childNodes: context, chosen, rec_tpl_params = child.instantiate(context, processor, new_level) if chosen: break context.set(origState) return (context, rec_tpl_params) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, ) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] return PyXML-0.8.2/xml/xslt/CommentElement.py0100644000076400001440000000365007255676734017021 0ustar martinusers######################################################################## # # File Name: CommentElement.py # # Documentation: http://docs.4suite.com/4XSLT/CommentElement.py.html # """ Implementation of the XSLT Spec comment stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import cStringIO import xml.dom.Element import xml.dom.ext import xml.xslt from xml.xslt import XsltException, Error from xml.xslt import XsltElement from xml.xpath import Conversions class CommentElement(XsltElement): legalAttrs = () def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='comment', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) #FIXME: Add error checking of child nodes processor.pushResult() for child in self.childNodes: context = child.instantiate(context, processor)[0] result = processor.popResult() data = Conversions.StringValue(result) processor.writers[-1].comment(data) processor.releaseRtf(result) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, ) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] return PyXML-0.8.2/xml/xslt/CopyElement.py0100644000076400001440000000750007377133277016322 0ustar martinusers######################################################################## # # File Name: CopyElement.py # # Documentation: http://docs.4suite.com/4XSLT/CopyElement.py.html # """ Implementation of the XSLT Spec copy stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import EMPTY_NAMESPACE import xml.dom.ext from xml.dom import Node, XMLNS_NAMESPACE import xml.xslt from xml.xslt import XsltElement, XsltException, Error from xml.xpath import CoreFunctions, Util class CopyElement(XsltElement): legalAttrs = ('use-attribute-sets',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='copy', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_useAttributeSets'] = string.splitfields(self.getAttributeNS(EMPTY_NAMESPACE, 'use-attribute-sets')) self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) node = context.node if node.nodeType == Node.TEXT_NODE: processor.writers[-1].text(node.data) elif node.nodeType == Node.ELEMENT_NODE: #FIXME: Use proper pysax AttributeList objects processor.writers[-1].startElement(node.nodeName, node.namespaceURI) for attr_set_name in self._useAttributeSets: split_name = Util.ExpandQName(attr_set_name, namespaces=context.processorNss) try: attr_set = processor.attributeSets[split_name] except KeyError: raise XsltException(Error.UNDEFINED_ATTRIBUTE_SET, attr_set_name) attr_set.use(context, processor) for child in self.childNodes: context = child.instantiate(context, processor)[0] processor.writers[-1].endElement(node.nodeName) elif node.nodeType == Node.DOCUMENT_NODE: for child in self.childNodes: context = child.instantiate(context, processor)[0] elif node.nodeType == Node.ATTRIBUTE_NODE: if node.namespaceURI == XMLNS_NAMESPACE: nodeName = 'xmlns' + (node.localName and ':' + node.localName) processor.writers[-1].attribute(nodeName, node.nodeValue, node.namespaceURI) else: processor.writers[-1].attribute(node.nodeName, node.nodeValue, node.namespaceURI) elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: processor.writers[-1].processingInstruction(node.target, node.data) elif node.nodeType == Node.COMMENT_NODE: processor.writers[-1].comment(node.data) else: raise Exception("Unknown Node Type %d" % node.nodeType) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._useAttributeSets) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._useAttributeSets = state[2] return PyXML-0.8.2/xml/xslt/CopyOfElement.py0100644000076400001440000000755007377133277016614 0ustar martinusers######################################################################## # # File Name: CopyOfElement.py # # Documentation: http://docs.4suite.com/4XSLT/CopyOfElement.py.html # """ Implementation of the XSLT Spec copy-of element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.ext from xml.dom import Node import xml.xslt from xml.xslt import XsltElement, XsltException, Error from xml.xslt import g_xsltRecognizedNodes from xml.xpath import XPathParser, Conversions from xml.dom import XMLNS_NAMESPACE class CopyOfElement(XsltElement): legalAttrs = ('select',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='copy-of', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) return def setup(self): parser = XPathParser.XPathParser() self.__dict__['_select'] = self.getAttributeNS(EMPTY_NAMESPACE, 'select') if not self._select: raise XsltException(Error.COPYOF_MISSING_SELECT) self.__dict__['_expr'] = parser.parseExpression(self._select) self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) expResult = self._expr.evaluate(context) if hasattr(expResult, "nodeType") and expResult.nodeType in g_xsltRecognizedNodes: expResult = [expResult] if type(expResult) == type([]) : for child in expResult: self.__copyNode(processor, child) else: st = Conversions.StringValue(expResult) processor.writers[-1].text(st) context.set(origState) return (context,) def __copyNode(self, processor, node): if node.nodeType == Node.DOCUMENT_NODE: for child in node.childNodes: self.__copyNode(processor, child) if node.nodeType == Node.DOCUMENT_FRAGMENT_NODE: for child in node.childNodes: self.__copyNode(processor, child) if node.nodeType == Node.TEXT_NODE: processor.writers[-1].text(node.data) elif node.nodeType == Node.ELEMENT_NODE: #FIXME: check if its a root element, and copy its children only, as the spec requires processor.writers[-1].startElement(node.nodeName,node.namespaceURI) for k in node.attributes.keys(): if k[0] != XMLNS_NAMESPACE: self.__copyNode(processor, node.attributes[k]) for child in node.childNodes: self.__copyNode(processor, child) processor.writers[-1].endElement(node.nodeName) elif node.nodeType == Node.ATTRIBUTE_NODE: if node.namespaceURI != XMLNS_NAMESPACE: processor.writers[-1].attribute(node.name, node.value, node.namespaceURI) elif node.nodeType == Node.COMMENT_NODE: processor.writers[-1].comment(node.data) elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: processor.writers[-1].processingInstruction(node.target, node.data) else: pass return def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._select, self._expr) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._select = state[2] self._expr = state[3] return PyXML-0.8.2/xml/xslt/ElementElement.py0100644000076400001440000000611207377133277016777 0ustar martinusers######################################################################## # # File Name: ElementElement.py # # Documentation: http://docs.4suite.com/4XSLT/ElementElement.py.html # """ Implementation of the XSLT Spec element stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element import xml.xslt from xml.xslt import XsltElement, XsltException, Error, AttributeValueTemplate from xml.xpath import CoreFunctions, Util class ElementElement(XsltElement): legalAttrs = ('name', 'namespace', 'use-attribute-sets') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='element', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_name'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'name')) self.__dict__['_namespace'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'namespace')) self.__dict__['_useAttributeSets'] = string.splitfields(self.getAttributeNS(EMPTY_NAMESPACE, 'use-attribute-sets')) self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) name = self._name.evaluate(context) namespace = self._namespace.evaluate(context) (prefix, local) = xml.dom.ext.SplitQName(name) if not namespace and prefix: namespace = context.processorNss[prefix] #FIXME: Use proper pysax AttributeList objects processor.writers[-1].startElement(name, namespace) for attr_set_name in self._useAttributeSets: split_name = Util.ExpandQName(attr_set_name, namespaces=context.processorNss) try: attr_set = processor.attributeSets[split_name] except KeyError: raise XsltException(Error.UNDEFINED_ATTRIBUTE_SET, attr_set_name) attr_set.use(context, processor) for child in self.childNodes: context = child.instantiate(context, processor)[0] processor.writers[-1].endElement(name) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name, self._namespace, self._useAttributeSets) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._name = state[2] self._namespace = state[3] self._useAttributeSets = state[4] return PyXML-0.8.2/xml/xslt/ForEachElement.py0100644000076400001440000000600107377133277016712 0ustar martinusers######################################################################## # # File Name: ForEachElement.py # # Documentation: http://docs.4suite.com/4XSLT/ForEachElement.py.html # """ Implementation of the XSLT Spec for-each stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.Element import xml.dom.ext import xml.xslt from xml.xslt import XsltElement, XsltException, Error, XSL_NAMESPACE from xml.xpath import XPathParser class ForEachElement(XsltElement): legalAttrs = ('select',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='for-each', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_select'] = self.getAttributeNS(EMPTY_NAMESPACE, 'select') self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) if self._select: parser = XPathParser.XPathParser() self.__dict__['_expr'] = parser.parseExpression(self._select) else: self.__dict__['_expr'] = None self.__dict__['_sortSpecs'] = [] for child in self.childNodes: if (child.namespaceURI, child.localName) == (XSL_NAMESPACE, 'sort'): self._sortSpecs.append(child) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) if self._select: result = self._expr.evaluate(context) #Check the result type. Note: we should really normalize the data typing so that we can throw an error if the result is not a node-set if type(result) != type([]): raise XsltException(Error.INVALID_FOREACH_SELECT) else: result = context.node.childNodes size = len(result) if size > 1 and self._sortSpecs: result = self._sortSpecs[0].instantiate(context, processor, result, self._sortSpecs[1:])[1] for ctr in range(size): node = result[ctr] context.setNodePosSize((node,ctr+1,size)) context.currentNode = node for child in self.childNodes: child.instantiate(context, processor)[0] context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._select, self._sortSpecs, self._expr) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._select = state[2] self._sortSpecs = state[3] self._expr = state[4] return PyXML-0.8.2/xml/xslt/HtmlWriter.py0100644000076400001440000001764507377133277016212 0ustar martinusers######################################################################## # # File Name: HtmlWriter.py # # Documentation: http://docs.4suite.com/4XSLT/HtmlWriter.py.html # """ Implements the HTML output writer for XSLT processor output WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc., USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import EMPTY_NAMESPACE from xml.dom.ext.Printer import TranslateCdata, TranslateCdataAttr from xml.dom.html import TranslateHtmlCdata from xml.xslt import NullWriter, XsltException, Error INDENT = ' '*2 INLINE_ELEMENT = 0 FORBIDDEN_END = 1 PCDATA_ELEMENT = 2 CDATA_CONTENT = 3 HEAD_ELEMENT = 4 NO_STRIP = 5 g_elementTable = {} g_attributeTable = {} g_defaultInfo = (0, 0, 0, 0, 0, 0) def InitTables(): from xml.dom.html import HTML_4_STRICT_INLINE from xml.dom.html import HTML_FORBIDDEN_END from xml.dom.html import HTML_BOOLEAN_ATTRS table = {} for tagname in HTML_4_STRICT_INLINE: info = list(g_defaultInfo) info[INLINE_ELEMENT] = 1 table[tagname] = info for tagname in HTML_FORBIDDEN_END: info = table.get(tagname, list(g_defaultInfo)) info[FORBIDDEN_END] = 1 table[tagname] = info # PCDATA containing elements for tagname in ['APPLET', 'IMG', 'OBJECT']: info = table.get(tagname, list(g_defaultInfo)) info[PCDATA_ELEMENT] = 1 table[tagname] = info # CDATA containing elements for tagname in ['SCRIPT', 'STYLE']: info = table.get(tagname, list(g_defaultInfo)) info[CDATA_CONTENT] = 1 table[tagname] = info # Elements to not strip whitespace from for tagname in ['SCRIPT', 'STYLE', 'PRE', 'TEXTAREA']: info = table.get(tagname, list(g_defaultInfo)) info[NO_STRIP] = 1 table[tagname] = info tagname = 'HEAD' info = table.get(tagname, list(g_defaultInfo)) info[HEAD_ELEMENT] = 1 table[tagname] = info for (tagname, value) in table.items(): g_elementTable[string.upper(tagname)] = tuple(value) for name in HTML_BOOLEAN_ATTRS: g_attributeTable[string.upper(name)] = 1 InitTables() class HtmlWriter(NullWriter.NullWriter): def __init__(self, outputParams, stream=None, restrictElements=None): NullWriter.NullWriter.__init__(self, outputParams, stream) # Defaults self._outputParams.indent = outputParams.indent in [None, 'yes'] self._outputParams.encoding = outputParams.encoding or 'iso-8859-1' self._outputParams.mediaType = outputParams.mediaType or 'text/html' # Process flags self._indentLevel = 0 self._inUnescapedElement = 0 self._inNoStrip = 0 self._isInline = [0] self._inPCdata = 1 self._inElement = 0 self._inHead = 0 self._first_element = 1 self._elementRestrictions = restrictElements return def _tryNewLine(self): if not self._inPCdata: self._stream.write('\n') self._stream.write(INDENT*self._indentLevel) return def _doctype(self, docElem): external_id = '' if self._outputParams.doctypePublic: external_id = ' PUBLIC "' + self._outputParams.doctypePublic + '"' if self._outputParams.doctypeSystem: external_id = external_id + ' "' + self._outputParams.doctypeSystem + '"' elif self._outputParams.doctypeSystem: external_id = external_id + ' SYSTEM "' + self._outputParams.doctypeSystem + '"' if external_id: self._stream.write('\n' % (docElem, external_id)) self._first_element = 0 return def _closeElement(self): if self._inElement: self._stream.write('>') self._inElement = 0 if self._inHead and self._outputParams.encoding: self._inHead = 0 self.startElement('meta') self.attribute('http-equiv', 'Content-Type') self.attribute('content', '%s; charset=%s' % (self.getMediaType(), self._outputParams.encoding)) self.endElement('meta') return def endDocument(self): self._closeElement() self._stream.flush() return def text(self, text, escapeOutput=1): if (self._outputParams.indent and not self._inPCdata and not self._inNoStrip): text = string.strip(text) and text or '' if text: self._closeElement() if not self._inUnescapedElement and escapeOutput: if text and text[0] == '>': self._stream.seek(-2, 2) last_chars = self._stream.read() else: last_chars = '' text = TranslateHtmlCdata( text, self._outputParams.encoding, last_chars ) self._stream.write(text) self._inPCdata = 1 return def attribute(self, name, value, namespace=EMPTY_NAMESPACE): self._stream.write(' %s' % name) # Output boolean attributes in minimized form name = string.upper(name) if not (g_attributeTable.get(name) and name == string.upper(value)): value = TranslateCdata(value, self._outputParams.encoding) value, delimiter = TranslateCdataAttr(value) self._stream.write('=%s%s%s' % (delimiter, value, delimiter)) return def processingInstruction(self, target, data): self._closeElement() self._outputParams.indent and self._tryNewLine() target = TranslateCdata(target, self._outputParams.encoding, '') data = TranslateCdata(data, self._outputParams.encoding, '') self._stream.write('' % (target, data)) return def comment(self, body): self._closeElement() body = TranslateCdata(body, self._outputParams.encoding, '') self._outputParams.indent and self._tryNewLine() self._stream.write('' % body) return def startElement(self, name, namespace=EMPTY_NAMESPACE, extraNss=None): if self._elementRestrictions is not None: if name not in self._elementRestrictions: raise XsltException(Error.RESTRICTED_OUTPUT_VIOLATION, name) # Close previous element, if any self._closeElement() self._inElement = 1 info = g_elementTable.get(string.upper(name), g_defaultInfo) if self._outputParams.indent: if not self._isInline[-1] and not self._first_element: self._tryNewLine() self._indentLevel = self._indentLevel + 1 if self._first_element: self._doctype(name) self._stream.write('<' + name) self._inPCdata = 0 self._isInline.append(info[INLINE_ELEMENT]) self._inUnescapedElement = info[CDATA_CONTENT] self._inHead = info[HEAD_ELEMENT] self._inNoStrip = info[NO_STRIP] return def endElement(self, name): # Close previous element, if any empty = self._inElement self._closeElement() info = g_elementTable.get(string.upper(name), g_defaultInfo) indent = self._outputParams.indent if indent: self._indentLevel = self._indentLevel - 1 if not info[FORBIDDEN_END]: if (indent and not empty and not self._inPCdata and (not self._isInline[-1] or not info[INLINE_ELEMENT])): self._tryNewLine() self._isInline.pop() self._stream.write('' % name) self._inPCdata = info[PCDATA_ELEMENT] self._inUnescapedElement = 0 return PyXML-0.8.2/xml/xslt/IfElement.py0100644000076400001440000000527507377133277015755 0ustar martinusers######################################################################## # # File Name: IfElement.py # # Documentation: http://docs.4suite.com/4XSLT/IfElement.py.html # """ Implementation of the XSLT Spec if instruction WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element import xml.xslt from xml.xslt import XsltElement, XSL_NAMESPACE from xml.xpath import CoreFunctions, Conversions from xml.xpath import XPathParser class IfElement(XsltElement): legalAttrs = ('test',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='if', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): parser = XPathParser.XPathParser() self.__dict__['_test'] = self.getAttributeNS(EMPTY_NAMESPACE, 'test') self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) self.__dict__['_expr'] = parser.parseExpression(self._test) self.__dict__['_elements'] = [] for child in self.childNodes: if (child.namespaceURI == XSL_NAMESPACE and child.localName in ['call-template', 'if', 'choose']): self.__dict__['_elements'].append((1,child)) else: self.__dict__['_elements'].append((0,child)) return def instantiate(self, context, processor, new_level=1): origState = context.copy() context.setNamespaces(self._nss) rec_tpl_params = None result = self._expr.evaluate(context) test = Conversions.BooleanValue(result) if test: for (recurse,child) in self._elements: if recurse: context, rec_tpl_params = child.instantiate(context, processor, new_level) else: context = child.instantiate(context, processor)[0] context.set(origState) return (context, rec_tpl_params) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._test, self._expr, self._elements) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._test = state[2] self._expr = state[3] self._elements = state[4] return PyXML-0.8.2/xml/xslt/LiteralElement.py0100644000076400001440000001201707277470665017007 0ustar martinusers######################################################################## # # File Name: LiteralElement.py # # Documentation: http://docs.4suite.com/4XSLT/LiteralElement.py.html # """ Implementation of the XSLT Spec import stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string import xml.dom.Element import xml.dom.ext from xml.xslt import XsltElement, AttributeValueTemplate from xml.xslt import XSL_NAMESPACE, XsltException, Error from xml.xpath import Util from xml.dom import XML_NAMESPACE class LiteralElement(XsltElement): def __init__(self, doc, uri, localName, prefix, baseUri): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self._useAttributeSets = string.splitfields(self.getAttributeNS(XSL_NAMESPACE, 'use-attribute-sets')) self._nss = xml.dom.ext.GetAllNs(self) self._outputNss = {} self.__attrs = [] self.excludedNss = [] sheet = self.ownerDocument.documentElement sheet._lres.append(self) excluded_prefixes = self.getAttributeNS(XSL_NAMESPACE, 'exclude-result-prefixes') if excluded_prefixes: excluded_prefixes = string.splitfields(excluded_prefixes) for prefix in excluded_prefixes: if prefix == '#default': prefix = '' self.excludedNss.append(self._nss[prefix]) node = self.parentNode while node: if hasattr(node, 'excludedNss'): self.excludedNss = self.excludedNss + node.excludedNss break node = node.parentNode for attr in self.attributes.values(): if attr.name == 'xmlns' or attr.name[:6] == 'xmlns:' or attr.namespaceURI == XSL_NAMESPACE: continue name = attr.name local_name = attr.localName prefix = attr.prefix uri = attr.namespaceURI if sheet.namespaceAliases[1].has_key(uri): name = sheet.namespaceAliases[0][prefix] + ':' + local_name uri = sheet.namespaceAliases[1][uri] self.__attrs.append((name, uri, AttributeValueTemplate.AttributeValueTemplate(attr.value))) self.fixupAliases() return def fixupAliases(self): sheet = self.ownerDocument.documentElement self._aliasUri = self.namespaceURI self._aliasNodeName = self.nodeName if sheet.namespaceAliases[1].has_key(self.namespaceURI): self._aliasNodeName = sheet.namespaceAliases[0][self.prefix] + ':' + self.localName self._aliasUri = sheet.namespaceAliases[1][self.namespaceURI] output_nss = self._nss.items() for ons in output_nss: prefix = ons[0] ns = ons[1] if ns in sheet.extensionNss + self.excludedNss + [XSL_NAMESPACE , XML_NAMESPACE]: continue if sheet.namespaceAliases[1].has_key(ns): if sheet.namespaceAliases[0].has_key(prefix): prefix = sheet.namespaceAliases[0][prefix] ns = sheet.namespaceAliases[1][ns] self._outputNss[prefix] = ns return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) processor.writers[-1].startElement(self._aliasNodeName, self._aliasUri, self._outputNss) for (name, uri, avt) in self.__attrs: value = avt.evaluate(context) processor.writers[-1].attribute(name, value, uri) for attr_set_name in self._useAttributeSets: split_name = Util.ExpandQName(attr_set_name, namespaces=context.processorNss) try: attr_set = processor.attributeSets[split_name] except KeyError: raise XsltException(Error.UNDEFINED_ATTRIBUTE_SET, attr_set_name) attr_set.use(context, processor) for child in self.childNodes: context = child.instantiate(context, processor)[0] processor.writers[-1].endElement(self._aliasNodeName) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._useAttributeSets, self._outputNss, self._aliasUri, self._aliasNodeName, self.__attrs, self.excludedNss) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._useAttributeSets = state[2] self._outputNss = state[3] self._aliasUri = state[4] self._aliasNodeName = state[5] self.__attrs = state[6] self.excludedNss = state[7] return PyXML-0.8.2/xml/xslt/LiteralText.py0100644000076400001440000000212407255677344016337 0ustar martinusers######################################################################## # # File Name: LiteralText.py # # Documentation: http://docs.4suite.com/4XSLT/LiteralText.py.html # """ Implementation of the XSLT Spec import stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string try: from Ft.Lib import pDomlette _Base = pDomlette.Text def _base_init(self, doc, data): _Base.__init__(self, doc) except ImportError: from xml.dom import minidom _Base = minidom.Text def _base_init(self, doc, data): _Base.__init__(self, data) class LiteralText(_Base): def __init__(self, doc, data): _base_init(self, doc, data) self.data = data def setup(self): return def instantiate(self, context, processor): processor.writers[-1].text(self.data) return (context,) def __getinitargs__(self): return (None, self.data) PyXML-0.8.2/xml/xslt/MessageElement.py0100644000076400001440000000434107377133277016774 0ustar martinusers######################################################################## # # File Name: MessageElement.py # # Documentation: http://docs.4suite.com/4XSLT/MessageElement.py.html # """ Implementation of the XSLT Spec import stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import cStringIO from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element import xml.xslt from xml.xslt import XsltElement, XsltException, Error from xml.xpath import Conversions class MessageElement(XsltElement): legalAttrs = ('terminate',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='message', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_terminate'] = self.getAttributeNS(EMPTY_NAMESPACE, 'terminate') if not self._terminate: self.__dict__['_terminate'] = 'no' self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) processor.pushResult() for child in self.childNodes: context = child.instantiate(context, processor)[0] result = processor.popResult() msg = Conversions.StringValue(result) processor.releaseRtf(result) if self._terminate == 'yes': raise XsltException(Error.STYLESHEET_REQUESTED_TERMINATION, msg) else: processor.xslMessage(msg) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._terminate) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._terminate = state[2] return PyXML-0.8.2/xml/xslt/MessageSource.py0100644000076400001440000001524307277470665016652 0ustar martinusersfrom xml.xslt import Error try: import os, gettext locale_dir = os.path.split(__file__)[0] gettext.install('4Suite', locale_dir) #except ImportError, IOError: #Note, 1.5.2 has gettext, but no install except (ImportError,AttributeError,IOError): def _(msg): return msg g_errorMessages = { Error.INTERNAL_ERROR: _('There is an internal bug in 4XSLT. Please report this error code to support@4suite.org: %s'), Error.PATTERN_SYNTAX: _('Syntax error in pattern at location %s (XPattern production number: %d).'), Error.PATTERN_SEMANTIC: _('Parse tree error in pattern at location %s (XPattern production number: %d, error type: %s, error value: %s, traceback:\n%s'), Error.APPLYIMPORTS_WITH_NULL_CURR_TPL: _('apply-imports used where there is no current template. (see XSLT Spec)'), Error.ILLEGAL_IMPORT: _('import is not allowed here. '), Error.STYLESHEET_PARSE_ERROR: _('Stylesheet (%s): XML parse error at line %d, column %d: %s'), Error.CIRCULAR_VAR: _('Circular variable reference error (see XSLT Spec: 11.4) for variable or parameter: (%s, %s)'), Error.SOURCE_PARSE_ERROR: _('Source document (%s): %s'), # Error.STYLESHEET_PARSE_ERROR: _('Stylesheet(XML) parse exception at line %d, column %d: %s'), # Error.SOURCE_PARSE_ERROR: _('Source document XML parse exception at line %d, column %d: %s'), Error.ILLEGAL_CALLTEMPLATE_CHILD: _('call-templates child must be with-param., (see XSLT Spec: 6)'), Error.ILLEGAL_APPLYTEMPLATE_CHILD: _('apply-templates child must be with-param or sort., (see XSLT Spec: 5.4)'), Error.WHEN_AFTER_OTHERWISE: _('when cannot succeed otherwise.'), Error.MULTIPLE_OTHERWISE: _('there cannot be more than one otherwise within a choose.'), Error.ILLEGAL_CHOOSE_CHILD: _('choose child must be "when" or "otherwise"., (see XSLT Spec: 9.2)'), Error.CHOOSE_WHEN_AFTER_OTHERWISE: _('choose cannot have "when" child after "otherwise" child., (see XSLT Spec: 9.2)'), Error.CHOOSE_MULTIPLE_OTHERWISE: _('choose only allowed one "otherwise" child., (see XSLT Spec: 9.2)'), Error.CHOOSE_REQUIRES_WHEN_CHILD: _('choose must have atleast one "when" child., (see XSLT Spec: 9.2)'), Error.ILLEGAL_TEXT_CHILD: _('xsl:text cannot have any child elements"., (see XSLT Spec: 7.2)'), Error.ILLEGAL_ATTRIBUTESET_CHILD: _('attribute-set child must be "attribute"., (see XSLT Spec: 7.1.4)'), Error.ATTRIBUTESET_REQUIRES_NAME: _('missing attribute-set required attribute name., (see XSLT Spec: 7.1.4)'), Error.INVALID_FOREACH_SELECT: _('for-each select attribute must evaluate to a node set (see XSLT Spec: 8)'), Error.VALUEOF_MISSING_SELECT: _('missing value-of requried attribute select (see XSLT Spec: 7.6.1)'), Error.COPYOF_MISSING_SELECT: _('missing copy-of requried attribute select (see XSLT Spec: 11.3)'), Error.WHEN_MISSING_TEST: _('missing when requried attribute test (see XSLT Spec: 9.2)'), Error.TOP_LEVEL_ELEM_WITH_NULL_NS: _(''), Error.XSLT_ILLEGAL_ATTR: _('Illegal attribute "%s" with null namespace in XSLT element "%s" (see XSLT Spec: 2.1).'), Error.XSLT_ILLEGAL_ELEMENT: _('Illegal Element "%s" in XSLT Namespace (see XSLT Spec: 2.1).'), Error.STYLESHEET_ILLEGAL_ROOT: _('Illegal Document Root Element "%s" (see XSLT Spec: 2.2).'), Error.ILLEGAL_SORT_DATA_TYPE_VALUE: _('The "data-type" attribute of sort must be either "text" or "number" (see XSLT Spec: 10).'), Error.ILLEGAL_SORT_CASE_ORDER_VALUE: _('The "case-order" attribute of sort must be either "upper-first" or "lower-first" (see XSLT Spec: 10)'), Error.ILLEGAL_SORT_ORDER_VALUE: _('The "order" attribute of sort must be either "ascending" or "descending". (see XSLT Spec: 10)'), Error.AVT_SYNTAX: _('Syntax error in attribute-value template. (see XSLT Spec: 7.6.2)'), Error.NO_STYLESHEET: _('No stylesheets to process.'), Error.STYLESHEET_MISSING_VERSION: _('Style-sheet document root element must have a version attribute. (see XSLT Spec: 2.2 - 2.3)'), Error.STYLESHEET_MISSING_VERSION_NOTE1: _('Style-sheet document root element must have a version attribute. (see XSLT Spec: 2.2 - 2.3). Note that you do not have the http://www.w3.org/1999/XSL/Transform namespace declared in your top element.'), Error.ILLEGAL_TEMPLATE_PRIORITY: _('Invalid priority value for template. (see XSLT Spec: 5.5)'), Error.ILLEGAL_NUMBER_GROUPING_SIZE_VALUE: _('The "grouping-size" attribute of number must be an integer. (see XSLT Spec: 7.7.1)'), Error.ILLEGAL_NUMBER_LEVEL_VALUE: _('The "level" attribute of number must be "single", "multiple" or "any". (see XSLT Spec: 7.7)'), Error.ILLEGAL_NUMBER_FORMAT_VALUE: _('Invalid value for "format" attribute of number. (see XSLT Spec: 7.7)'), Error.ILLEGAL_NUMBER_LETTER_VALUE_VALUE: _('The "letter-value" attribute of number must be "alphabetic" or "traditional". (see XSLT Spec: 7.7.1)'), Error.INVALID_NAMESPACE_ALIAS: _('Invalid arguments to the namespace-alias instruction. (see XSLT Spec: 7.1.1)'), Error.WRONG_NUMBER_OF_ARGUMENTS: _('A built-in or extension function was called with the wrong number of arguments.'), Error.WRONG_ARGUMENT_TYPE: _('A built-in or extension function was called with the wrong number of arguments.'), Error.FEATURE_NOT_SUPPORTED: _('4XSLT does not yet support this feature.'), Error.INVALID_PATTERN: _('Invalid pattern (%s).'), Error.INVALID_OPERAND_IN_PATTERN: _('Invalid operand (%s) in pattern.'), Error.INVALID_OPERAND_ID: _('Invalid operand (%s) for "id".'), Error.INVALID_OPERAND_IDREL: _('Invalid operand (%s) for "id" with relative path.'), Error.INVALID_OPERAND_SREL: _('Invalid operand (%s) in absolute location path.'), Error.INVALID_OPERAND_REL: _('Invalid operand (%s) in relative location path.'), Error.INVALID_LEFT_OR_RIGHT_OPERAND_S: _('Invalid left or right operand (%s or %s) to "/".'), Error.INVALID_LEFT_OR_RIGHT_OPERAND_RELP: _('Invalid left or right operand (%s or %s) in relative path.'), Error.INVALID_AXIS_SPEC: _('Invalid axis specifier'), Error.INVALID_NODE_TEST: _('Invalid node test'), Error.INVALID_PREDICATE_LIST: _('Invalid predicate list'), Error.ATTRIBUTE_ADDED_AFTER_ELEMENT: _('xsl:attribute instantiated within an element instantiation after a child element has been added. (see XSLT Spec: 7.1.3)'), Error.ATTRIBUTE_MISSING_NAME: _('xsl:attribute missing required name attribute. (see XSLT Spec: 7.1.3)'), Error.UNDEFINED_ATTRIBUTE_SET: _('Undefined attribute set (%s)'), Error.RESTRICTED_OUTPUT_VIOLATION: _('The requested output of element "%s" is forbidden accirding to output restrictions'), #Error.: _(''), Error.STYLESHEET_REQUESTED_TERMINATION: _('A message instruction in the Stylesheet requested termination of processing:\n%s'), } PyXML-0.8.2/xml/xslt/NullWriter.py0100644000076400001440000000266507377133277016214 0ustar martinusers######################################################################## # # File Name: NullWriter.py # # Documentation: http://docs.4suite.com/4XSLT/NullWriter.py.html # """ Implements an empty writer for XSLT processor output WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc., USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import sys, cStringIO from xml.dom import EMPTY_NAMESPACE from xml.xslt import OutputParameters class NullWriter: def __init__(self, outputParams=None, stream=None): self._outputParams = outputParams or OutputParameters() self._stream = stream or cStringIO.StringIO() self._savedResult = stream is None def getMediaType(self): return self._outputParams.mediaType def getResult(self): if self._savedResult: return self._stream.getvalue() return '' def startDocument(self): return def endDocument(self): return def text(self, text, escapeOutput=1): return def attribute(self, name, value, namespace=EMPTY_NAMESPACE): return def processingInstruction(self, target, data): return def comment(self, body): return def startElement(self, name, namespace=EMPTY_NAMESPACE, extraNss=None): return def endElement(self, name): return PyXML-0.8.2/xml/xslt/NumberElement.py0100644000076400001440000003656207377133277016652 0ustar martinusers######################################################################## # # File Name: NumberElement.py # # Documentation: http://docs.4suite.com/4XSLT/NumberElement.py.html # """ Implementation of the XSLT Spec number stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import re, string from xml.dom import EMPTY_NAMESPACE from xml.xslt import Roman import xml.xslt import xml.dom.ext from xml.dom import Node from xml.xslt import XsltElement, XsltException, Error, AttributeValueTemplate from xml.xslt import XPatternParser from xml.xpath import XPathParser, Conversions #Pattern for format tokens (see spec 7.7.1) g_formatToken = re.compile(r"([^a-zA-Z0-9]*)([a-zA-Z0-9]+)([^a-zA-Z0-9]*)") class NumberElement(XsltElement): legalAttrs = ('level', 'count', 'from', 'value', 'format', 'lang', 'letter-value', 'grouping-separator', 'grouping-size',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='number', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self._nss = {} self._level = None self._count = None self._from = None self._value = None self._format = None self._lang = None self._letter_value = None self._grouping_separator = None self._grouping_size = None self._value_expr = None self._sibling_expr = None self._count_prior_doc_order_expr = None self._count_pattern = None self._ancorself_expr = None path_parser = XPathParser.XPathParser() pattern_parser = XPatternParser.XPatternParser() self.__dict__['_level'] = self.getAttributeNS(EMPTY_NAMESPACE, 'level') or 'single' if self._level not in ['single', 'multiple', 'any']: raise XsltException(Error.ILLEGAL_NUMBER_LEVEL_VALUE) self.__dict__['_count'] = self.getAttributeNS(EMPTY_NAMESPACE, 'count') self.__dict__['_from'] = self.getAttributeNS(EMPTY_NAMESPACE, 'from') self.__dict__['_value'] = self.getAttributeNS(EMPTY_NAMESPACE, 'value') format = self.getAttributeNS(EMPTY_NAMESPACE, 'format') self.__dict__['_format'] = format and AttributeValueTemplate.AttributeValueTemplate(format) or None lang = self.getAttributeNS(EMPTY_NAMESPACE, 'lang') self.__dict__['_lang'] = lang and AttributeValueTemplate.AttributeValueTemplate(lang) or None letter_value = self.getAttributeNS(EMPTY_NAMESPACE, 'letter-value') self.__dict__['_letter_value'] = letter_value and AttributeValueTemplate.AttributeValueTemplate(letter_value) or None grouping_separator = self.getAttributeNS(EMPTY_NAMESPACE, 'grouping-separator') self.__dict__['_grouping_separator'] = grouping_separator and AttributeValueTemplate.AttributeValueTemplate(grouping_separator) or None grouping_size = self.getAttributeNS(EMPTY_NAMESPACE, 'grouping-size') self.__dict__['_grouping_size'] = grouping_size and AttributeValueTemplate.AttributeValueTemplate(grouping_size) or None self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) #Prep computations if not self._count: #FIXME: Handle other node types???? self._count = '*[name()=name(current())]' self._count_pattern = pattern_parser.parsePattern(self._count) ancestor_or_self = "ancestor-or-self::node()" if self._from: ancestor_or_self = ancestor_or_self + '[ancestor::%s]'%(self._from) self._ancorself_expr = path_parser.parseExpression(ancestor_or_self) if self._value: self._value_expr = path_parser.parseExpression(self._value) self._sibling_expr = None self._count_prior_doc_order_expr = None else: self._sibling_expr = path_parser.parseExpression('preceding-sibling::node()') patterns = pattern_parser.parsePattern(self._count)._patterns count_prior_doc_order = '' if self._from: froms = pattern_parser.parsePattern(self._from)._patterns pred = "[" for fro in froms: pred = pred + 'ancestor::' + repr(fro) if fro != froms[-1]: pred = pred + '|' pred = pred + ']' for count in patterns: if self._from: count_prior_doc_order = count_prior_doc_order + 'ancestor-or-self::' + repr(count) + pred + '|preceding::' +repr(count) + pred else: count_prior_doc_order = count_prior_doc_order + 'ancestor-or-self::' + repr(count) + '|preceding::' + repr(count) if count != patterns[-1]: count_prior_doc_order = count_prior_doc_order + '|' self._count_prior_doc_order_expr = path_parser.parseExpression(count_prior_doc_order) return def instantiate(self, context, processor, nodeList=None, specList=None): if nodeList is None: nodeList = [] if specList is None: specList = [] origState = context.copy() context.setNamespaces(self._nss) if self._format: format = self._format.evaluate(context) else: format = '1' if self._grouping_separator: grouping_separator = self._grouping_separator.evaluate(context) else: grouping_separator = ',' if self._grouping_size: grouping_size = self._grouping_size.evaluate(context) else: grouping_size = '3' if grouping_separator and grouping_size: try: grouping_size = string.atoi(grouping_size) except ValueError: raise XsltException(Error.ILLEGAL_NUMBER_GROUPING_SIZE_VALUE) else: grouping_separator = None grouping_size = None if self._letter_value: letter_value = self._letter_value.evaluate(context) if letter_value not in ['alphabetic', 'traditional']: raise XsltException(Error.ILLEGAL_NUMBER_LETTER_VALUE_VALUE) value = [] tempState = context.copyNodePosSize() if self._value: result = self._value_expr.evaluate(context) value = [Conversions.NumberValue(result)] elif self._level == 'single': ancorself_result = self._ancorself_expr.evaluate(context) ancorself_result.reverse() for node in ancorself_result: context.node = node if self._count_pattern.match(context, context.node): break sibling_result = self._sibling_expr.evaluate(context) value = 1 for node in sibling_result: context.node = node if self._count_pattern.match(context, context.node): value = value + 1 value = [value] elif self._level == 'multiple': ancorself_result = self._ancorself_expr.evaluate(context) ancorself_result.reverse() count_result = [] for node in ancorself_result: context.node = node if self._count_pattern.match(context, context.node): count_result.append(node) context.setNodePosSize(tempState) value = [] for node in count_result: context.node = node sibling_result = self._sibling_expr.evaluate(context) lvalue = 1 for node in sibling_result: context.node = node if self._count_pattern.match(context, context.node): lvalue = lvalue + 1 value.insert(0, lvalue) elif self._level == 'any': count_result = self._count_prior_doc_order_expr.evaluate(context) value = [len(count_result)] context.setNodePosSize(tempState) format_tokens = [] format_separators = [] re_groups = g_formatToken.findall(format) if not re_groups: raise XsltException(Error.ILLEGAL_NUMBER_FORMAT_VALUE) pre_string = re_groups[0][0] post_string = re_groups[-1][2] for group in re_groups: format_tokens.append(group[1]) format_separators.append(group[2]) format_separators = ['.'] + format_separators[:-1] result = pre_string curr_index = 0 lft = len(format_tokens) lfs = len(format_separators) for number in value: if curr_index: result = result + curr_sep if curr_index < lft: curr_ft = format_tokens[curr_index] curr_sep = format_separators[curr_index] curr_index = curr_index + 1 else: curr_ft = format_tokens[-1] curr_sep = format_separators[-1] numstr = str(number) if curr_ft[-1] == '1': subresult = Group( '0'*(len(curr_ft)-len(numstr))+numstr, grouping_size, grouping_separator ) result = result + subresult elif curr_ft == 'A': digits = Base26(number) #FIXME: faster with reduce for dig in digits: result = result + chr(ord('A') + dig - 1) elif curr_ft == 'a': digits = Base26(number) for dig in digits: result = result + chr(ord('a') + dig - 1) elif curr_ft == 'I': result = result + Roman.IToRoman(number) elif curr_ft == 'i': result = result + string.lower(Roman.IToRoman(number)) else: raise XsltException(Error.ILLEGAL_NUMBER_FORMAT_VALUE) processor.writers[-1].text(result + post_string) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._level, self._count, self._from, self._value, self._format, self._lang, self._letter_value, self._grouping_separator, self._grouping_size, self._value_expr, self._sibling_expr, self._count_prior_doc_order_expr, self._count_pattern, self._ancorself_expr) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._level = state[2] self._count = state[3] self._from = state[4] self._value = state[5] self._format = state[6] self._lang = state[7] self._letter_value = state[8] self._grouping_separator = state[9] self._grouping_size = state[10] self._value_expr = state[11] self._sibling_expr = state[12] self._count_prior_doc_order_expr = state[13] self._count_pattern = state[14] self._ancorself_expr = state[15] return def Base26(n): #FIXME: There must be an easier/faster way in Python n = int(n) result = [] factor = 1 while factor < n: factor = factor * 26 factor = factor / 26 while n >= 26: digit = n / factor result.append(digit) n = n - factor * digit factor = factor / 26 result.append(n) return result def Group(numstr, size, sep): if not sep: return numstr result = '' start_seg = 0 end_seg = len(numstr) % size while end_seg <= len(numstr): if end_seg: if end_seg == len(numstr): result = result + numstr[start_seg:end_seg] else: result = result + numstr[start_seg:end_seg] + sep start_seg = end_seg end_seg = end_seg + size return result ##Note: emacs can uncomment the ff automatically. ##To: xsl-list@mulberrytech.com ##Subject: Re: number format test ##From: MURAKAMI Shinyu ##Date: Thu, 3 Aug 2025 01:18:10 +0900 (Wed 10:18 MDT) ##Kay Michael wrote: ##>> 5. Saxon ##>> - Fullwidth 1 (#xff11) are supported. ##>> - Hiragana/Katakana/Kanji format generates incorrect result. ##>> (Unicode codepoint order, such as #x3042, #x3043, #x3044,...) ##>> useless and trouble with Non-European style processing. ##>> fix it please!! ##> ##>If you could tell me what the correct sequence is, I'll be happy to include ##>it. Help me please! ##XSLT 1.0 spec says: ## 7.7.1 Number to String Conversion Attributes ## ... ## - Any other format token indicates a numbering sequence that starts ## with that token. If an implementation does not support a numbering ## sequence that starts with that token, it must use a format token of 1. ##The last sentence is important. ...it must use a format token of 1. ##If Saxon will support... the following are Japanese Hiragana/Katakana sequences ##-- modern(A...) and traditional(I...) -- and Kanji(CJK ideographs) numbers. ##format="あ" (Hiragana A) ##あいうえおかきくけこ ##さしすせそたちつてと ##なにぬねのはひふへほ ##まみむめもやゆよらり ##るれろわをん ##format="ア" (Katakana A) ##アイウエオカキクケコ ##サシスセソタチツテト ##ナニヌネノハヒフヘホ ##マミムメモヤユヨラリ ##ルレロワヲン ##format="い" (Hiragana I) ##いろはにほへとちりぬ ##るをわかよたれそつね ##ならむうゐのおくやま ##けふこえてあさきゆめ ##みしゑひもせす ##format="イ" (Katakana I) ##イロハニホヘトチリヌ ##ルヲワカヨタレソツネ ##ナラムウヰノオクヤマ ##ケフコエテアサキユメ ##ミシヱヒモセス ##format="一" (Kanji 1) (decimal notation) ##一(=1) 二(=2) 三(=3) 四(=4) 五(=5) ##六(=6) 七(=7) 八(=8) 九(=9) 〇(=0) ##e.g. 一〇(=10) 二五六(=256) ##There are more ideographic(kanji)-number formats, but the above will be sufficient. ##Thanks, ##MURAKAMI Shinyu ##murakami@nadita.com PyXML-0.8.2/xml/xslt/OtherXslElement.py0100644000076400001440000001605407377133277017164 0ustar martinusers######################################################################## # # File Name: OtherXslElement.py # # Documentation: http://docs.4suite.com/4XSLT/OtherXslElement.py.html # """ Non-template instructions from the XSLT spec WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.xslt from xml.xslt import XsltElement, XsltException, Error, XSL_NAMESPACE class DecimalFormatElement(XsltElement): legalAttrs = ('name', 'decimal-separator', 'grouping-separator', 'infinity', 'minus-sign', 'NaN', 'percent', 'per-mille', 'zero-digit', 'digit', 'pattern-separator') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='decimal-format', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): return def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return class IncludeElement(XsltElement): legalAttrs = ('href',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='include', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_href'] = self.getAttributeNS(EMPTY_NAMESPACE, 'href') return def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._href, ) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._href = state[1] return class FallbackElement(XsltElement): legalAttrs = () def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='fallback', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def setup(self): return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) for child in self.childNodes: context = child.instantiate(context, processor)[0] context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return class ImportElement(XsltElement): legalAttrs = ('href',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='import', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) self.stylesheet = None def setup(self): self.href = self.getAttributeNS(EMPTY_NAMESPACE, 'href') def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return class KeyElement(XsltElement): legalAttrs = ('name', 'match', 'use') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='key', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): pass def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return class NamespaceAliasElement(XsltElement): legalAttrs = ('stylesheet-prefix', 'result-prefix') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='namespace-alias', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): pass def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return class OutputElement(XsltElement): legalAttrs = ('method', 'version', 'encoding', 'omit-xml-declaration', 'standalone', 'doctype-public', 'doctype-system', 'cdata-section-elements', 'indent', 'media-type') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='output', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): pass def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return class PreserveSpaceElement(XsltElement): legalAttrs = ('elements',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='preserve-space', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): pass def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return class StripSpaceElement(XsltElement): legalAttrs = ('elements',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='strip-space', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): pass def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) return base_state def __setstate__(self, state): XsltElement.__setstate__(self, state) return import urlparse from xml.xslt import XsltException, Error import xml.xslt.StylesheetReader PyXML-0.8.2/xml/xslt/OtherwiseElement.py0100644000076400001440000000364307255676734017372 0ustar martinusers######################################################################## # # File Name: OtherwiseElement.py # # Documentation: http://docs.4suite.com/4XSLT/OtherwiseElement.py.html # """ Implementation of the XSLT Spec otherwise instruction WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import xml.dom.ext import xml.dom.Element import xml.xslt from xml.xslt import XsltElement, XsltException, Error from xml.xpath import CoreFunctions class OtherwiseElement(XsltElement): legalAttrs = () def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='otherwise', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor, new_level=1): origState = context.copy() context.setNamespaces(self._nss) rec_tpl_params = None for child in self.childNodes: if child.namespaceURI == xml.xslt.XSL_NAMESPACE and child.localName in ['call-template', 'if', 'choose']: context, rec_tpl_params = child.instantiate(context, processor, new_level) else: context = child.instantiate(context, processor)[0] context.set(origState) return (context, 1, rec_tpl_params) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, ) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] return PyXML-0.8.2/xml/xslt/OutputHandler.py0100644000076400001440000000350207277470665016676 0ustar martinusersimport string from xml.xslt import NullWriter, PlainTextWriter from xml.xslt import HtmlWriter, XmlWriter class OutputHandler(NullWriter.NullWriter): def __init__(self, outputParams, stream, notifyFunc): self._outputParams = outputParams self._stream = stream self._notify = notifyFunc self._stack = [] def _finalize(self, writerClass): writer = writerClass(self._outputParams, self._stream) self._notify(writer) writer.startDocument() newline = 0 for (cmd, args, kw) in self._stack: if newline: writer.text('\n') else: newline = 1 apply(getattr(writer, cmd), args, kw) self._outputParams = None self._stream = None self._notify = None self._stack = [] def getResult(self): return '' def startDocument(self): if self._outputParams.method == 'html': self._finalize(HtmlWriter.HtmlWriter) elif self._outputParams.method == 'xml': self._finalize(XmlWriter.XmlWriter) elif self._outputParams.method == 'text': self._finalize(PlainTextWriter.PlainTextWriter) def text(self, *args, **kw): self._stack.append(('text', args, kw)) if string.strip(args[0]): self._finalize(XmlWriter.XmlWriter) def processingInstruction(self, *args, **kw): self._stack.append(('processingInstruction', args, kw)) def comment(self, *args, **kw): self._stack.append(('comment', args, kw)) def startElement(self, *args, **kw): self._stack.append(('startElement', args, kw)) tagName = args[0] if string.upper(tagName) == 'HTML': self._finalize(HtmlWriter.HtmlWriter) else: self._finalize(XmlWriter.XmlWriter) PyXML-0.8.2/xml/xslt/ParamElement.py0100644000076400001440000000477007377133277016456 0ustar martinusers######################################################################## # # File Name: ParamElement.py # # Documentation: http://docs.4suite.com/4XSLT/ParamElement.py.html # """ Implementation of the XSLT Spec param stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element import xml.xslt from xml.xslt import XsltElement, XsltException, Error from xml.xpath import CoreFunctions, Util from xml.xpath import XPathParser class ParamElement(XsltElement): legalAttrs = ('name', 'select') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='param', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self._nss = xml.dom.ext.GetAllNs(self) name_attr = self.getAttributeNS(EMPTY_NAMESPACE, 'name') split_name = Util.ExpandQName( name_attr, namespaces=self._nss ) self._name = split_name self._select = self.getAttributeNS(EMPTY_NAMESPACE, 'select') if self._select: parser = XPathParser.XPathParser() self._expr = parser.parseExpression(self._select) else: self._expr = None return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) if self._select: result = self._expr.evaluate(context) else: processor.pushResult() for child in self.childNodes: context = child.instantiate(context, processor)[0] result = processor.popResult() context.rtfs.append(result) context.set(origState) context.varBindings[self._name] = result return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name, self._select, self._expr) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._name = state[2] self._select = state[3] self._expr = state[4] return PyXML-0.8.2/xml/xslt/ParsedLocationPathPattern.py0100644000076400001440000000574207357127430021156 0ustar martinusers######################################################################## # # File Name: ParsedLocationPathPattern.py # # Documentation: http://docs.4suite.com/4XSLT/ParsedLocationPathPattern.py.html # """ Parse class to handle XSLT LocationPathPattern patterns WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node class RootPattern: """LocationPathPattern: '/'""" def __init__(self): self.priority = 0.5 def getShortcut(self): return (self, None) def match(self, context, node, axisType): # In some DOM implementations, ownerDocument of the root document # is the document itself if node.ownerDocument == node: return 1 # According to the DOM spec, ownerDocument is None for the root return node.ownerDocument is None def pprint(self, indent=''): print indent + '<%s at %x: %s>' % ( self.__class__.__name__, id(self), repr(self)) def __repr__(self): return '/' class IdKeyPattern: """LocationPathPattern: IdKeyPattern""" def __init__(self, idKey, nodeTest=None, axisType=None): self._idKey = idKey self._nodeTest = nodeTest self._axisType = axisType self.priority = nodeTest and nodeTest.priority or 0.5 def getShortcut(self): return (self, None) def match(self, context, node, axisType): return (node in self._idKey.evaluate(context)) def pprint(self, indent=''): print indent + '<%s at %x: %s>' % ( self.__class__.__name__, id(self), repr(self)) self._nodeTest and self._nodeTest.pprint(indent + ' ') self._idKey.pprint(indent + ' ') def __repr__(self): return repr(self._idKey) class IdKeyParentPattern(IdKeyPattern): """LocationPathPattern: IdKeyPattern '/' RelativePathPattern""" def match(self, context, node, axisType): if self._nodeTest.match(context, node, self._axisType): return (node.parentNode in self._idKey.evaluate(contenxt)) return 0 def __repr__(self): st = '/' + (self._axisType == Node.ATTRIBUTE_NODE and '@' or '') return repr(self._idKey) + st + repr(self._nodeTest) class IdKeyAncestorPattern(IdKeyPattern): """LocationPathPattern: IdKeyPattern '//' RelativePathPattern""" def match(self, context, node, axisType): if self._nodeTest.match(context, node, self._axisType): nodeset = self._idKey.evaluate(context) while node: if node.parentNode in nodeset: return 1 node = node.parentNode return 0 def __repr__(self): st = '//' + (self._axisType == Node.ATTRIBUTE_NODE and '@' or '') return repr(self._idKey) + st + repr(self._nodeTest) PyXML-0.8.2/xml/xslt/ParsedPattern.py0100644000076400001440000000305107357127430016637 0ustar martinusers######################################################################## # # File Name: ParsedPattern.py # # Documentation: http://docs.4suite.com/4XSLT/ParsedPattern.py.html # """ Parse class to handle base XSLT patterns WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import sys from xml.xpath import ParsedToken from xml.xslt import XsltException, Error class ParsedPattern(ParsedToken.ParsedToken): def __init__(self, pattern): ParsedToken.ParsedToken.__init__(self, 'PATTERN') self._patterns = [pattern] self._shortcuts = [pattern.getShortcut()] def append(self,pattern): self._patterns.append(pattern) self._shortcuts.append(pattern.getShortcut()) def match(self, context, node): for pattern,axis_type in self._shortcuts: if pattern.match(context, node, axis_type): return 1 return 0 def getMatchShortcuts(self): return map(lambda a, b: (a, b), self._patterns, self._shortcuts) def pprint(self, indent=''): print indent + str(self) for pattern in self._patterns: pattern.pprint(indent + ' ') def __str__(self): return '' % (id(self), repr(self)) def __repr__(self): rt = repr(self._patterns[0]) for pattern in self._patterns[1:]: rt = rt + ' | ' + repr(pattern) return rt PyXML-0.8.2/xml/xslt/ParsedRelativePathPattern.py0100644000076400001440000000472007357127430021154 0ustar martinusers######################################################################## # # File Name: ParsedRelativePathPattern.py # # Documentation: http://docs.4suite.com/4XSLT/ParsedRelativePathPattern.py.html # """ Parse class to handle XSLT RelativePathPattern patterns WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from xml.xpath import ParsedToken from xml.xslt import XsltException, Error, XPattern class RelativePathPattern(ParsedToken.ParsedToken): def __init__(self, op, parent, step): ParsedToken.ParsedToken.__init__(self, 'RELATIVE_PATH_PATTERN') self._op = op self._parent = parent self._step = step self.priority = self._step.priority def getShortcut(self): return (self, None) def pprint(self, indent=''): print indent + str(self) self._parent.pprint(indent + ' ') self._step.pprint(indent + ' ') def __str__(self): return '<%s(RelativePathPattern) at %x: %s>' % ( self.__class__.__name__, id(self), repr(self)) def __repr__(self): return repr(self._parent) + self._op + repr(self._step) class RelativeParentPattern(RelativePathPattern): """RelativePathPattern: RelativePathPattern '/' StepPattern""" def __init__(self, parent, step): RelativePathPattern.__init__(self, '/', parent, step) def match(self, context, node): if self._step.match(context, node): if node.nodeType == Node.ATTRIBUTE_NODE: node = node.ownerElement else: node = node.parentNode if node: return self._parent.match(context, node) return 0 class RelativeAncestorPattern(RelativePathPattern): """RelativePathPattern: RelativePathPattern '//' StepPattern""" def __init__(self, parent, step): RelativePathPattern.__init__(self, '//', parent, step) def match(self, context, node): if self._step.match(context, node): if node.nodeType == Node.ATTRIBUTE_NODE: node = node.ownerElement else: node = node.parentNode while node: if self._parent.match(context, node): return 1 node = node.parentNode return 0 PyXML-0.8.2/xml/xslt/ParsedStepPattern.py0100644000076400001440000001177407357127430017506 0ustar martinusers######################################################################## # # File Name: ParsedStepPattern.py # # Documentation: http://docs.4suite.com/4XSLT/ParsedStepPattern.py.html # """ Parse class to handle XSLT StepPatterns WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import Node from xml.xpath import ParsedToken from xml.xslt import XsltException, Error class StepPattern: def __init__(self, nodeTest, axisType, parent=None, parentAxis=None): self.nodeTest = nodeTest self.axisType = axisType self.priority = nodeTest.priority self.parent = parent self.parentAxis = parentAxis def getShortcut(self): return (self.nodeTest, self.axisType) def match(self, context, node, nodeType): raise Exception('subclass should override') def pprint(self, indent=''): print indent + str(self) self.nodeTest.pprint(indent + ' ') self.parent and self.parent.pprint(indent + ' ') def __str__(self): return '<%s at %x: %s>' % ( self.__class__.__name__, id(self), repr(self)) def __repr__(self): st = (self.axisType == Node.ATTRIBUTE_NODE and '@' or '') return st + repr(self.nodeTest) class ParentStepPattern(StepPattern): def getShortcut(self): return (self, self.axisType) def match(self, context, node, axisType): # Called when there is another step following if self.nodeTest.match(context, node, self.axisType): if node.parentNode: node = node.parentNode elif node.nodeType == Node.ATTRIBUTE_NODE: node = node.ownerElement return self.parent.match(context, node, self.parentAxis) return 0 def __repr__(self): st = '/' + (self.axisType == Node.ATTRIBUTE_NODE and '@' or '') return repr(self.parent) + st + repr(self.nodeTest) class RootParentStepPattern(StepPattern): def getShortcut(self): return (self, self.axisType) def match(self, context, node, axisType): if self.nodeTest.match(context, node, axisType): return node.parentNode == node.ownerDocument return 0 def __repr__(self): prefix = '/' + (self.axisType == Node.ATTRIBUTE_NODE and '@' or '') suffix = self.parent and repr(self.parent) or '' return prefix + repr(self.nodeTest) + suffix class AncestorStepPattern(StepPattern): def getShortcut(self): return (self, self.axisType) def match(self, context, node, axisType): # Called when there is another step following if self.nodeTest.match(context, node, self.axisType): if node.parentNode: node = node.parentNode elif node.nodeType == Node.ATTRIBUTE_NODE: node = node.ownerElement while node: if self.parent.match(context, node, self.parentAxis): return 1 node = node.parentNode return 0 def __repr__(self): st = '//' + (self.axisType == Node.ATTRIBUTE_NODE and '@' or '') return repr(self.parent) + st + repr(self.nodeTest) class PredicateStepPattern: def __init__(self, nodeTest, axisType, predicates): self.nodeTest = nodeTest self.axisType = axisType self.predicates = predicates self.priority = 0.5 def getShortcut(self): return (self, None) def match(self, context, node, axisType): if node.parentNode: parent = node.parentNode node_set = parent.childNodes elif node.nodeType == Node.ATTRIBUTE_NODE == self.axisType: parent = node.ownerElement node_set = parent.attributes.values() else: # Must be a document, it only matches '/' return 0 # Pass through the NodeTest node_set = filter(lambda node, match=self.nodeTest.match, context=context, principalType=self.axisType: match(context, node, principalType), node_set) # Our axes are forward only if node_set: original = context.node context.node = parent node_set = self.predicates.filter(node_set, context, 0) context.node = original return node in node_set def pprint(self, indent=''): print indent + '<%s at %x: %s>' % ( self.__class__.__name__, id(self), repr(self)) self.nodeTest.pprint(indent + ' ') self.predicates.pprint(indent + ' ') def __repr__(self): prefix = self.axisType == Node.ATTRIBUTE_NODE and '@' or '' return prefix + repr(self.nodeTest) + repr(self.predicates) PyXML-0.8.2/xml/xslt/PlainTextWriter.py0100644000076400001440000000305507377133277017204 0ustar martinusers######################################################################## # # File Name: PlainTextWriter.py # # Documentation: http://docs.4suite.com/4XSLT/PlainTextWriter.py.html # """ Implements a text output writer for XSLT processor output WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc., USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.xslt import NullWriter from xml.dom import EMPTY_NAMESPACE from xml.dom.ext.Printer import utf8_to_code class PlainTextWriter(NullWriter.NullWriter): def __init__(self, outputParams, stream=None): NullWriter.NullWriter.__init__(self, outputParams, stream) self._mediaType = outputParams.mediaType or 'text/plain' self._encoding = outputParams.encoding def getMediaType(self): return self._mediaType def startDocument(self): return def endDocument(self): return def text(self, text, escapeOutput=1): if self._encoding: self._stream.write(utf8_to_code(text, self._encoding)) else: # Defaults to UTF-8 self._stream.write(text) def attribute(self, name, value, namespace=EMPTY_NAMESPACE): return def processingInstruction(self, target, data): return def comment(self, body): return def startElement(self, name, namespace=EMPTY_NAMESPACE, extraNss=None): return def endElement(self, name): return PyXML-0.8.2/xml/xslt/ProcessingInstructionElement.py0100644000076400001440000000432007377133277021763 0ustar martinusers######################################################################## # # File Name: ProcessingInstructionElement.py # # Documentation: http://docs.4suite.com/4XSLT/ProcessingInstructionElement.py.html # """ Implementation of the XSLT Spec processing-instruction stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element from xml.xslt import XsltElement, XsltException, Error, AttributeValueTemplate from xml.xpath import Conversions class ProcessingInstructionElement(XsltElement): legalAttrs = ('name',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='processing-instructions', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_target'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS(EMPTY_NAMESPACE, 'name')) self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): origState = context.copy() context.setNamespaces(self._nss) target = self._target.evaluate(context) #FIXME: Add error checking of child nodes processor.pushResult() for child in self.childNodes: context = child.instantiate(context, processor)[0] result = processor.popResult() processor.writers[-1].processingInstruction(target, Conversions.StringValue(result)) processor.releaseRtf(result) context.set(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._target) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._target = state[2] return PyXML-0.8.2/xml/xslt/Processor.py0100644000076400001440000003676007377133277016067 0ustar martinusers######################################################################## # # File Name: Processor.py # # Documentation: http://docs.4suite.com/4XSLT/Processor.py.html # """ Implement the XSLT processor engine WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string, os, sys import traceback import xml.dom.ext from xml.dom import XML_NAMESPACE,EMPTY_NAMESPACE from xml.dom.ext import reader from xml.dom import Node from xml.xpath import Util from xml.xslt import XSL_NAMESPACE, XsltContext from xml.xslt import RtfWriter, OutputHandler, OutputParameters, Error, XsltException from xml.xslt import StylesheetReader, ReleaseNode try: from Ft.Lib import pDomlette import Ft.Lib have_pDomlette = 1 except ImportError: from xml.dom import minidom have_pDomlette = 0 from xml import xpath, xslt import os BETA_DOMLETTE = os.environ.get("BETA_DOMLETTE") if BETA_DOMLETTE: from Ft.Lib import cDomlette g_readerClass = cDomlette.RawExpatReader g_domModule = cDomlette else: if have_pDomlette: g_readerClass = pDomlette.PyExpatReader g_domModule = pDomlette else: import minisupport g_readerClass = minisupport.MinidomReader g_domModule = minidom XSLT_IMT = ['text/xml', 'application/xml'] class Processor: def __init__(self, reader=None): self._stylesheets = [] self.writers = [] self._reset() self._dummyDoc = g_domModule.Document() #Can be overridden self._styReader = StylesheetReader.StylesheetReader() self._docReader = reader or g_readerClass() self._lastOutputParams = None if not xslt.g_registered: xslt.Register() return def _reset(self): self.attributeSets = {} for sty in self._stylesheets: sty.reset() self.sheetWithCurrTemplate = [None] #A stack of writers, to support result-tree fragments self.writers = [] #self.extensionParams = {} return def _getWsStripElements(self): space_rules = {} for a_sheet in self._stylesheets: space_rules.update(a_sheet.spaceRules) strip_elements = map(lambda x: (x[0][0], x[0][1], x[1] == 'strip'), space_rules.items()) strip_elements.append((XSL_NAMESPACE,'text',0)) return strip_elements def registerExtensionModules(self, moduleList): return xslt.RegisterExtensionModules(moduleList) def setStylesheetReader(self, readInst): self._styReader = readInst def setDocumentReader(self, readInst): self._docReader = readInst def appendStylesheetUri(self, styleSheetUri, baseUri=''): sty = self._styReader.fromUri(styleSheetUri, baseUri) self._stylesheets.append(sty) return appendStylesheetFile = appendStylesheetUri def appendStylesheetNode(self, styleSheetNode, baseUri=''): """Accepts a DOM node that must be a document containing the stylesheet""" sty = StylesheetReader.FromDocument(styleSheetNode, baseUri) self._stylesheets.append(sty) return def appendStylesheetString(self, text, baseUri=''): sty = self._styReader.fromString(text, baseUri) self._stylesheets.append(sty) return def appendStylesheetStream(self, stream, baseUri=''): sty = self._styReader.fromStream(stream, baseUri) self._stylesheets.append(sty) return def appendInstantStylesheet(self, sty): """Accepts a valid StyleDOM node""" self._stylesheets.append(sty) return def runString(self, xmlString, ignorePis=0, topLevelParams=None, writer=None, baseUri='', outputStream=None): try: src = self._docReader.fromString(xmlString,stripElements=self._getWsStripElements()) except Exception, e: raise XsltException(Error.SOURCE_PARSE_ERROR, '', e) if not ignorePis and self.checkStylesheetPis(src, baseUri): #FIXME: should we leave this to GC in Python 2.0? self._docReader.releaseNode(src) #Do it again with updates WS strip lists try: src = self._docReader.fromString(xmlString,stripElements=self._getWsStripElements()) except Exception, e: raise XsltException(Error.SOURCE_PARSE_ERROR, '', e) result = self.execute(src, ignorePis, topLevelParams, writer, baseUri, outputStream) #FIXME: should we leave this to GC in Python 2.0? self._docReader.releaseNode(src) return result def runUri(self, uri, ignorePis=0, topLevelParams=None, writer=None, outputStream=None): try: src = self._docReader.fromUri(uri, stripElements=self._getWsStripElements()) except Exception, e: import traceback traceback.print_exc() raise XsltException(Error.SOURCE_PARSE_ERROR, uri, e) if not ignorePis and self.checkStylesheetPis(src, uri): self._docReader.releaseNode(src) #Do it again with updates WS strip lists try: src = self._docReader.fromUri(uri,stripElements=self._getWsStripElements()) except Exception, e: raise XsltException(Error.SOURCE_PARSE_ERROR, uri, e) result = self.execute(src, ignorePis, topLevelParams, writer, uri, outputStream) self._docReader.releaseNode(src) return result def runStream(self, stream, ignorePis=0, topLevelParams=None, writer=None, baseUri='', outputStream=None): try: src = self._docReader.fromStream( stream, stripElements=self._getWsStripElements() ) except Exception, e: raise XsltException(Error.SOURCE_PARSE_ERROR, '', e) if not ignorePis and self.checkStylesheetPis(src, baseUri): #FIXME: Will this work with tty streams? stream.seek(0,0) self._docReader.releaseNode(src) #Do it again with updated WS strip lists try: src = self._docReader.fromStream( stream, stripElements=self._getWsStripElements() ) except Exception, e: raise XsltException(Error.SOURCE_PARSE_ERROR, '', e) result = self.execute(src, ignorePis, topLevelParams, writer, baseUri, outputStream) self._docReader.releaseNode(src) return result def runNode(self, node, ignorePis=0, topLevelParams=None, writer=None, baseUri='', outputStream=None, forceStripElements = 0): 'Note: this method could mutate the node' node.normalize() if not ignorePis and self.checkStylesheetPis(node, baseUri): #FIXME: should re-strip white-space pass if forceStripElements: #WARNING: This will mutate the source self._stripElements(node) result = self.execute(node, ignorePis, topLevelParams, writer, baseUri, outputStream) return result def checkStylesheetPis(self, node, baseUri): pis_found = 0 #Note: A Stylesheet PI can only be in the prolog, acc to the NOTE #http://www.w3.org/TR/xml-stylesheet/ if node.nodeType == Node.DOCUMENT_NODE: ownerDoc = node else: ownerDoc = node.ownerDoc for child in ownerDoc.childNodes: if child.nodeType == Node.PROCESSING_INSTRUCTION_NODE: if child.target == 'xml-stylesheet': data = child.data data = string.splitfields(data,' ') sty_info = {} for d in data: seg = string.splitfields(d, '=') if len(seg) == 2: sty_info[seg[0]] = seg[1][1:-1] if sty_info.has_key('href'): if not sty_info.has_key('type') \ or sty_info['type'] in XSLT_IMT: self.appendStylesheetUri(sty_info['href'], baseUri) pis_found = 1 return pis_found def execute(self, node, ignorePis=0, topLevelParams=None, writer=None, baseUri='', outputStream=None): """ Run the stylesheet processor against the given XML DOM node with the stylesheets that have been registered. Does not mutate the DOM If writer is None, use the XmlWriter, otherwise, use the supplied writer """ #FIXME: What about ws stripping? topLevelParams = topLevelParams or {} if len(self._stylesheets) == 0: raise XsltException(Error.NO_STYLESHEET) self._outputParams = self._stylesheets[0].outputParams if writer: self.writers = [writer] else: self.addHandler(self._outputParams, outputStream, 0) self._namedTemplates = {} tlp = topLevelParams.copy() for sty in self._stylesheets: sty.processImports(node, self, tlp) named = sty.getNamedTemplates() for name,template_info in named.items(): if not self._namedTemplates.has_key(name): self._namedTemplates[name] = template_info for sty in self._stylesheets: tlp = sty.prime(node, self, tlp) #Run the document through the style sheets self.writers[-1].startDocument() context = XsltContext.XsltContext(node, 1, 1, None, processor=self) try: self.applyTemplates(context, None) self.writers[-1].endDocument() Util.FreeDocumentIndex(node) result = self.writers[-1].getResult() finally: self._reset() context.release() return result def applyTemplates(self, context, mode, params=None): params = params or {} for sty in self._stylesheets: self.sheetWithCurrTemplate.append(sty) found = sty.applyTemplates(context, mode, self, params) del self.sheetWithCurrTemplate[-1] if found: break else: self.applyBuiltins(context, mode) return def applyBuiltins(self, context, mode): if context.node.nodeType == Node.TEXT_NODE: self.writers[-1].text(context.node.data) elif context.node.nodeType in [Node.ELEMENT_NODE, Node.DOCUMENT_NODE]: origState = context.copyNodePosSize() node_set = context.node.childNodes size = len(node_set) pos = 1 for node in node_set: context.setNodePosSize((node,pos,size)) self.applyTemplates(context, mode) pos = pos + 1 context.setNodePosSize(origState) elif context.node.nodeType == Node.ATTRIBUTE_NODE: self.writers[-1].text(context.node.value) return def applyImports(self, context, mode, params=None): params = params or {} if not self.sheetWithCurrTemplate[-1]: raise XsltException(Error.APPLYIMPORTS_WITH_NULL_CURRENT_TEMPLATE) self.sheetWithCurrTemplate[-1].applyImports(context, mode, self) return def xslMessage(self, msg): sys.stderr.write("STYLESHEET MESSAGE:\n") sys.stderr.write(msg+'\n') sys.stderr.write("END STYLESHEET MESSAGE:\n") return def callTemplate(self, name, context, params, new_level=1): tpl_info = self._namedTemplates.get(name) if tpl_info: (stylesheet, template) = tpl_info variables = stylesheet.getTopLevelVariables() variables.update(params) origState = context.copyStylesheet() context.setStylesheet((variables, stylesheet.namespaces, stylesheet)) rec_tpl_params = template.instantiate(context, self, params, new_level)[1] context.setStylesheet(origState) else: rec_tpl_params = None return rec_tpl_params def _writerChanged(self, newWriter): self.writers[-1] = newWriter def addHandler(self, outputParams, stream=None, start=1): handler = OutputHandler.OutputHandler(outputParams, stream, self._writerChanged) self.writers.append(handler) start and self.writers[-1].startDocument() def removeHandler(self): self.writers[-1].endDocument() del self.writers[-1] def pushResult(self, handler=None, ownerDoc=None): """ Start processing all content into a separate result-tree (either an rtf, or for ft:write-file) """ #FIXME: Should actually use a doc fragment for the SAX handler doc #Q: Should the output parameters discovered at run-time (e.g html root element) be propagated back to RTFs? handler = handler or RtfWriter.RtfWriter(self._outputParams, ownerDoc or self._dummyDoc) self.writers.append(handler) return def popResult(self): """End sub-result-tree and return any result""" result = self.writers[-1].getResult() del self.writers[-1] return result def releaseRtf(self, rtfRoot): ReleaseNode(rtfRoot) return def _stripElements(self,node): stripElements = self._getWsStripElements() self.__stripNode(node,stripElements,0) return def __stripNode(self,node,stripElements,stripState): if node.nodeType == Node.DOCUMENT_NODE: for c in node.childNodes: self.__stripNode(c,stripElements,stripState) elif node.nodeType == Node.ELEMENT_NODE: #See if we need to change the strip state if node.getAttributeNodeNS(XML_NAMESPACE,'space') == 'preserve': #Force the state to preserve stripState = 0 elif node.getAttributeNodeNS(XML_NAMESPACE,'space'): #Force to strip stripState = 1 elif (node.namespaceURI, node.localName) == (XSL_NAMESPACE,'text'): #xsl:text never get striped stripState = 0 else: #See if it is a perserve or strip element for (uri, local, strip) in stripElements: if (uri, local) in [(node.namespaceURI, node.localName), (EMPTY_NAMESPACE, '*'), (node.namespaceURI, '*')]: stripState = strip break for c in node.childNodes: self.__stripNode(c,stripElements,stripState) elif node.nodeType == Node.TEXT_NODE: if stripState and not string.strip(node.data): #Kill'em all node.parentNode.removeChild(node) def reclaim(self): try: ReleaseNode(self._dummyDoc) except: pass self._dummyDoc = None try: for sheet in self._stylesheets: sheet.reclaim() self._styReader.releaseNode(sheet.ownerDocument) except: pass self._stylesheets = [] #Python 2.0 has GC, but it doesn't try to auto-reclaim classes with __del__ if sys.version[0] != '2': __del__ = reclaim PyXML-0.8.2/xml/xslt/Roman.py0100644000076400001440000000172607255676734015163 0ustar martinusers""" Light-weight functions to convert from Roman-Numerals to ints, and vice-versa. """ import string factor_list = [1000, 500, 100, 50, 10, 5, 1] roman_equiv = {1000: 'M', 500: 'D', 100: 'C', 50: 'L', 10: 'X', 5: 'V', 1: 'I'} def IToRoman(num): roman = "" remainder = num factor_index = 0 for f in factor_list: factor_up = (f != 1000 and factor_list[factor_index - 1]) or None factor_down = (f != 1 and factor_list[factor_index + 1]) or None dividend = remainder / f remainder = remainder % f if factor_up and dividend == 4: roman = roman + roman_equiv[f] + roman_equiv[factor_up] elif factor_down and dividend == 1 and remainder / factor_down == 4: roman = roman + roman_equiv[factor_down] + roman_equiv[factor_up] remainder = remainder % factor_down else: roman = roman + roman_equiv[f]*dividend factor_index = factor_index + 1 return roman PyXML-0.8.2/xml/xslt/RtfWriter.py0100644000076400001440000000556707377133277016041 0ustar martinusers######################################################################## # # File Name: RtfWriter.py # # Documentation: http://docs.4suite.com/4XSLT/RtfWriter.py.html # """ A special, simple writer for capturing result-tree fragments WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2001 Fourthought Inc., USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string, os import NullWriter from xml.dom import EMPTY_NAMESPACE from xml.xslt import XSL_NAMESPACE from xml.xpath import Util from xml.dom.ext import SplitQName from xml.dom import XMLNS_NAMESPACE, Node class RtfWriter(NullWriter.NullWriter): def __init__(self, outputParams, ownerDoc): self._ownerDoc = ownerDoc self._root = ownerDoc.createDocumentFragment() self._root.stringValue = "" self._nodeStack = [self._root] self._currElement = None self._outputParams = outputParams def getResult(self): return self._root def startElement(self, name, namespace=EMPTY_NAMESPACE, extraNss=None): extraNss = extraNss or {} prefix, localName = SplitQName(name) new_element = self._ownerDoc.createElementNS(namespace, name) self._nodeStack.append(new_element) for prefix in extraNss.keys(): if prefix: new_element.setAttributeNS(XMLNS_NAMESPACE, 'xmlns:'+prefix, extraNss[prefix]) else: new_element.setAttributeNS(XMLNS_NAMESPACE, 'xmlns', extraNss[prefix]) new_element.stringValue = "" return def endElement(self, name): new_element = self._nodeStack[-1] del self._nodeStack[-1] self._nodeStack[-1].appendChild(new_element) return def text(self, text, escapeOutput=1): new_text = self._ownerDoc.createTextNode(text) top_node = self._nodeStack[-1] top_node.appendChild(new_text) top_node.stringValue = top_node.stringValue + text return def attribute(self, name, value, namespace=EMPTY_NAMESPACE): prefix, localName = SplitQName(name) attr = self._ownerDoc.createAttributeNS(namespace, name) attr.value = value if self._nodeStack[-1].nodeType == Node.ELEMENT_NODE: self._nodeStack[-1].attributes[(namespace, localName)] = attr else: #Document-fragment parent self._nodeStack[-1].appendChild(attr) return def processingInstruction(self, target, data): pi = self._ownerDoc.createProcessingInstruction(target, data) self._nodeStack[-1].appendChild(pi) return def comment(self, data): comment = self._ownerDoc.createComment(data) self._nodeStack[-1].appendChild(comment) return PyXML-0.8.2/xml/xslt/SortElement.py0100644000076400001440000001151307377133277016336 0ustar martinusers######################################################################## # # File Name: SortElement.py # # Documentation: http://docs.4suite.com/4XSLT/SortElement.py.html # """ Implementation of the XSLT Spec sort stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element import xml.xslt from xml.xslt import XsltElement, XsltException, Error, AttributeValueTemplate from xml.xpath import XPathParser from xml.xpath import Conversions class SortElement(XsltElement): legalAttrs = ('select', 'lang', 'data-type', 'case-order', 'order') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='sort', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_select'] = self.getAttributeNS(EMPTY_NAMESPACE, 'select') or '.' data_type = self.getAttributeNS(EMPTY_NAMESPACE, 'data-type') self.__dict__['_data_type'] = data_type and AttributeValueTemplate.AttributeValueTemplate(data_type) or None case_order = self.getAttributeNS(EMPTY_NAMESPACE, 'case-order') self.__dict__['_case_order'] = case_order and AttributeValueTemplate.AttributeValueTemplate(case_order) or None order = self.getAttributeNS(EMPTY_NAMESPACE, 'order') self.__dict__['_order'] = order and AttributeValueTemplate.AttributeValueTemplate(order) or None self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) parser = XPathParser.XPathParser() self.__dict__['_expr'] = parser.parseExpression(self._select) return def instantiate(self, context, processor, nodeList=None, specList=None): if nodeList is None: nodeList = [] if specList is None: specList = [] origState = context.copy() context.setNamespaces(self._nss) if self._data_type: data_type = self._data_type.evaluate(context) if data_type not in ['text', 'number']: raise XsltException(Error.ILLEGAL_SORT_DATA_TYPE_VALUE) else: data_type = 'text' if self._case_order: case_order = self._case_order.evaluate(context) if case_order not in ['upper-first', 'lower-first']: raise XsltException(Error.ILLEGAL_SORT_CASE_ORDER_VALUE) else: case_order = 'lower-first' if self._order: order = self._order.evaluate(context) if order not in ['ascending', 'descending']: raise XsltException(Error.ILLEGAL_SORT_ORDER_VALUE) else: order = 'ascending' keys = [] node_dict = {} pos = 1 size = len(nodeList) tempState = context.copyNodePosSize() for node in nodeList: context.setNodePosSize((node,pos,size)) result = self._expr.evaluate(context) key = Conversions.StringValue(result) if not key in keys: keys.append(key) if node_dict.has_key(key): node_dict[key].append(node) else: node_dict[key] = [node] pos = pos + 1 context.setNodePosSize(tempState) keys.sort(lambda x, y, o=order, d=data_type, c=case_order: Cmp(x, y, o, d, c)) sorted_list = [] for key in keys: sub_list = node_dict[key] if len(sub_list) > 1 and specList: sub_list = specList[0].instantiate(context, processor, sub_list, specList[1:])[1] sorted_list = sorted_list + sub_list context.set(origState) return (context, sorted_list) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._select, self._data_type, self._case_order, self._order, self._expr) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._select = state[2] self._data_type = state[3] self._case_order = state[4] self._order = state[5] self._expr = state[6] return def Cmp(a, b, order, dataType, caseOrder): if dataType == 'number': a = float(a or 0) b = float(b or 0) elif caseOrder == 'lower-first': if a: a = string.swapcase(a[0])+a[1:] if b: b = string.swapcase(b[0])+b[1:] if order == 'ascending': return cmp(a,b) else: return cmp(b,a) PyXML-0.8.2/xml/xslt/Stylesheet.py0100644000076400001440000005376707534565153016244 0ustar martinusers######################################################################## # # File Name: Stylesheet.py # # Documentation: http://docs.4suite.com/4XSLT/Stylesheet.py.py.html # """ Implement all the stylesheet internals WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import string, types from xml.dom import EMPTY_NAMESPACE import xml.dom.ext from xml import xpath, xslt from xml.dom import Node from xml.dom.NodeFilter import NodeFilter from xml.xslt import XsltElement, XsltException, InternalException, Error from xml.xslt import XPatternParser, XsltContext from xml.xslt import XSL_NAMESPACE, OutputParameters, ReleaseNode from xml.xpath import CoreFunctions, Util, XPathParser, Conversions class PatternInfo: """Indexes into the tuple for pattern information""" PATTERN = 0 AXIS_TYPE = 1 PRIORITY = 2 MODE = 3 NSS = 4 TEMPLATE = 5 SPECIAL_RE_CHARS = ['.', '^', '$', '*', '+', '?'] def MatchTree(patterns, context): '''Select all nodes from node on down that match the pattern''' matched = map(lambda x, c=context, n=context.node: [n]*x.match(c,n), patterns) counter = 1 size = len(context.node.childNodes) origState = context.copyNodePosSize() for child in context.node.childNodes: context.setNodePosSize((child, counter, size)) map(lambda x, y: x.extend(y), matched, MatchTree(patterns, context)) context.setNodePosSize(origState) counter = counter + 1 if context.node.nodeType == Node.ELEMENT_NODE: counter = 1 size = len(context.node.attributes) for attr in context.node.attributes.values(): context.setNodePosSize((attr, counter, size)) map(lambda x, y: x.extend(y), matched, MatchTree(patterns, context)) context.setNodePosSize(origState) counter = counter + 1 return matched class StylesheetElement(XsltElement): legalAttrs = ('id', 'extension-element-prefixes', 'exclude-result-prefixes', 'version') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='stylesheet', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) self._imports = [] self.extensionNss = [] self._primedContext = None self._lres = [] return def _updateKeys(self, doc, processor): context = XsltContext.XsltContext(doc, 1, 1, processorNss=self.namespaces, processor=processor) patterns = map(lambda x: x[1], self._kelems) if not patterns: return match_lists = MatchTree(patterns, context) ctr = 0 for (name, match_pattern, use_expr) in self._kelems: match_list = match_lists[ctr] if not self.keys.has_key(name): self.keys[name] = {} for node in match_list: context.stylesheet = self origState = context.copy() context.node = node key_value_list = use_expr.evaluate(context) #NOTE: use attrs can't contain var refs, so result can't #be RTF So use CoreFunc StringValue, not ExtFunc version if type(key_value_list) != type([]): key_value_list = [key_value_list] for obj in key_value_list: keystr = Conversions.StringValue(obj) if not self.keys[name].has_key(keystr): self.keys[name][keystr] = [] self.keys[name][keystr].append(node) context.set(origState) ctr = ctr + 1 context.release() return def setup(self): ''' Called only once, at the first initialization ''' self.namespaces = xml.dom.ext.GetAllNs(self) self.spaceRules = {} self._topLevelVarNodes = {} self.namespaceAliases = ({}, {}) self.decimalFormats = {'': ('.', ',', 'Infinity', '-', 'NaN', '%', '?', '0', '#', ';')} self.keys = {} self.outputParams = OutputParameters() excluded_prefixes = self.getAttributeNS(EMPTY_NAMESPACE, 'exclude-result-prefixes') self.excludedNss = [] if excluded_prefixes: excluded_prefixes = string.splitfields(excluded_prefixes) for prefix in excluded_prefixes: if prefix == '#default': prefix = '' self.excludedNss.append(self.namespaces[prefix]) self._setupNamespaceAliases() self._setupChildNodes() self._setupDecimalFormats() self._setupWhitespaceRules() self._setupOutput() self._setupTemplates() self._setupKeys() self._setupTopLevelVarParams() return def _setupNamespaceAliases(self): #Namespace aliases ns_aliases = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'namespace-alias'), self.childNodes) for nsa in ns_aliases: stylesheet_prefix = nsa.getAttributeNS(EMPTY_NAMESPACE, 'stylesheet-prefix') result_prefix = nsa.getAttributeNS(EMPTY_NAMESPACE, 'result-prefix') if not (stylesheet_prefix and result_prefix): raise XsltException(Error.INVALID_NAMESPACE_ALIAS) if stylesheet_prefix == '#default': stylesheet_prefix == '' if result_prefix == '#default': result_prefix == '' sty_ns = self.namespaces[stylesheet_prefix] res_ns = self.namespaces[result_prefix] self.namespaceAliases[0][stylesheet_prefix] = result_prefix self.namespaceAliases[1][sty_ns] = res_ns return def _setupChildNodes(self): snit = self.ownerDocument.createNodeIterator(self, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, None,0) curr_node = snit.nextNode() curr_node = snit.nextNode() while curr_node: try: curr_node.setup() except (xpath.SyntaxException, xpath.InternalException, xslt.SyntaxException, xslt.InternalException), e: #import traceback #traceback.print_exc(1000) if not hasattr(e, 'stylesheetUri'): e.stylesheetUri = curr_node.baseUri raise e curr_node = snit.nextNode() return def _setupDecimalFormats(self): dec_formats = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'decimal-format'), self.childNodes) for dc in dec_formats: format_settings = ( (dc.getAttributeNS(EMPTY_NAMESPACE, 'decimal-separator') or '.'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'grouping-separator') or ','), (dc.getAttributeNS(EMPTY_NAMESPACE, 'infinity') or 'Infinity'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'minus-sign') or '-'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'NaN') or 'NaN'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'percent') or '%'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'per-mille') or '?'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'zero-digit') or '0'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'digit') or '#'), (dc.getAttributeNS(EMPTY_NAMESPACE, 'pattern-separator') or ';') ) nfs = [] for fc in format_settings: if fc in SPECIAL_RE_CHARS: nfs.append('\\'+fc) else: nfs.append(fc) name = dc.getAttributeNS(EMPTY_NAMESPACE, 'name') name = name and Util.ExpandQName(name, dc) self.decimalFormats[name] = tuple(nfs) return def _setupWhitespaceRules(self): #Whitespace rules space_rules = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) in [(XSL_NAMESPACE, 'preserve-space'), (XSL_NAMESPACE, 'strip-space')], self.childNodes) for sr in space_rules: args = string.splitfields(sr.getAttributeNS(EMPTY_NAMESPACE, 'elements')) for an_arg in args: #FIXME: watch out! ExpandQName doesn't handle ns defaulting split_name = Util.ExpandQName(an_arg, sr) self.spaceRules[split_name] = string.splitfields(sr.localName, '-')[0] return def _setupOutput(self): #Output output = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'output'), self.childNodes) for out in output: method = out.getAttributeNS(EMPTY_NAMESPACE, 'method') if method: self.outputParams.method = method version = out.getAttributeNS(EMPTY_NAMESPACE, 'version') if version: self.outputParams.version = version encoding = out.getAttributeNS(EMPTY_NAMESPACE, 'encoding') if encoding: self.outputParams.encoding = encoding omit_xml_decl = out.getAttributeNS(EMPTY_NAMESPACE, 'omit-xml-declaration') if omit_xml_decl: self.outputParams.omitXmlDeclaration = omit_xml_decl standalone = out.getAttributeNS(EMPTY_NAMESPACE, 'standalone') if standalone: self.outputParams.standalone = standalone doctype_system = out.getAttributeNS(EMPTY_NAMESPACE, 'doctype-system') if doctype_system: self.outputParams.doctypeSystem = doctype_system doctype_public = out.getAttributeNS(EMPTY_NAMESPACE, 'doctype-public') if doctype_public: self.outputParams.doctypePublic = doctype_public media_type = out.getAttributeNS(EMPTY_NAMESPACE, 'media-type') if media_type: self.outputParams.mediaType = media_type #cdata_sec_elem = out.getAttributeNS(EMPTY_NAMESPACE, 'cdata-section-elements') self.outputParams.cdataSectionElements = [] qnames = string.splitfields(out.getAttributeNS(EMPTY_NAMESPACE, 'cdata-section-elements')) for qname in qnames: self.outputParams.cdataSectionElements.append(Util.ExpandQName(qname, namespaces=self.namespaces)) indent = out.getAttributeNS(EMPTY_NAMESPACE, 'indent') if indent: self.outputParams.indent = indent return def _setupTemplates(self): templates = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'template'), self.childNodes) #Preprocess all of the templates with names match_tpls = filter(lambda x: x._name != '', templates) self._call_templates = {} for m in match_tpls: if not self._call_templates.has_key(m._name): self._call_templates[m._name] = m #Preprocess the patterns from all templates patterns = [] for tpl in templates: (patternInfo, mode, nss) = tpl.getMatchInfo() for pi in patternInfo: patterns.append(pi+(mode, nss, tpl)) patterns.reverse() patterns.sort(lambda x, y: cmp(y[PatternInfo.PRIORITY], x[PatternInfo.PRIORITY])) patternDict = {} for p in patterns: m = p[PatternInfo.MODE] if not patternDict.has_key(m): patternDict[m] = [] patternDict[m].append(p) self._patterns = patternDict return def _setupKeys(self): self._kelems = [] pattern_parser = XPatternParser.XPatternParser() path_parser = XPathParser.XPathParser() kelems = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'key'), self.childNodes) for kelem in kelems: name = Util.ExpandQName(kelem.getAttributeNS(EMPTY_NAMESPACE, 'name'), kelem) match = kelem.getAttributeNS(EMPTY_NAMESPACE, 'match') match_pattern = pattern_parser.parsePattern(match) use = kelem.getAttributeNS(EMPTY_NAMESPACE, 'use') use_expr = path_parser.parseExpression(use) self._kelems.append((name, match_pattern, use_expr)) self.reset() return def _setupTopLevelVarParams(self): #Is there a more efficient way to zip two sequences into a dict? vars = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and x.namespaceURI == XSL_NAMESPACE and x.localName == 'variable', self.childNodes) self._topVariables = {} for var in vars: #FIXME: First check multiple variable errors self._topVariables[var._name] = var params = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and x.namespaceURI == XSL_NAMESPACE and x.localName == 'param', self.childNodes) for param in params: #FIXME: First check multiple variable errors self._topVariables[param._name] = param return def newSource(self, doc, processor): """ Called whenever there's a new source document registed to the processor """ self._updateKeys(doc, processor) return def reset(self): """ Called whenever the processor is reset, i.e. after each run """ self.keys = {} if self._primedContext: self._primedContext.release() self._primedContext = None return def _fixupAliases(self): for lre in self._lres: lre.fixupAliases() return def processImports(self, contextNode, processor, topLevelParams): #Import precedence rules can be taken care of by having parent self._imports = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'import'), self.childNodes) #Style-sheet dictionaries override imported values for imp in self._imports: imp.setup() #FIXME: Extension elements? imp.stylesheet = processor._styReader.fromUri(imp.href, baseUri=imp.baseUri) sheet = imp.stylesheet sheet.processImports(contextNode, processor, topLevelParams) sheet.prime(contextNode, processor, topLevelParams) self.spaceRules.update(sheet.spaceRules) self.namespaceAliases[0].update(sheet.namespaceAliases[0]) self.namespaceAliases[1].update(sheet.namespaceAliases[1]) self._fixupAliases() return def _computeVar(self, vname, context, processed, deferred, overriddenParams, topLevelParams, processor): vnode = self._topVariables[vname] if vnode in deferred: raise XsltException(Error.CIRCULAR_VAR, vname[0], vname[1]) if vnode in processed: return if vnode.localName[0] == 'p': if overriddenParams.has_key(vname): context.varBindings[vname] = overriddenParams[vname] else: try: context = vnode.instantiate(context, processor)[0] except xpath.RuntimeException, e: deferred.append(vnode) self._computeVar((e.args[0], e.args[1]), context, processed, deferred, overriddenParams, topLevelParams, processor) deferred.remove(vnode) context = vnode.instantiate(context, processor)[0] #Set up so that later stylesheets will get overridden by #parameter values set in higher-priority stylesheets topLevelParams[vname] = context.varBindings[vname] else: try: context = vnode.instantiate(context, processor)[0] except xpath.RuntimeException, e: deferred.append(vnode) self._computeVar((e.args[0], e.args[1]), context, processed, deferred, overriddenParams, topLevelParams, processor) deferred.remove(vnode) context = vnode.instantiate(context, processor)[0] processed.append(vnode) return def prime(self, contextNode, processor, topLevelParams): self._primedContext = context = XsltContext.XsltContext(contextNode.ownerDocument, 1, 1, processorNss=self.namespaces, stylesheet=self, processor=processor) self._docReader = processor._docReader #Attribute sets attribute_sets = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'attribute-set'), self.childNodes) for as in attribute_sets: as.instantiate(context, processor) overridden_params = {} for k in topLevelParams.keys(): if type(k) != types.TupleType: try: split_name = Util.ExpandQName(k, namespaces=context.processorNss) except KeyError: continue else: split_name = k overridden_params[split_name] = topLevelParams[k] for vname in self._topVariables.keys(): self._computeVar(vname, context, [], [], overridden_params, topLevelParams, processor) self._primedContext = context #Note: key expressions can't have var refs, so we needn't worry about imports self._updateKeys(contextNode, processor) for imp in self._imports: self._primedContext.varBindings.update(imp.stylesheet._primedContext.varBindings) return topLevelParams ########################## Run-time methods ######################## def getNamedTemplates(self): templates = {} for name,tpl in self._call_templates.items(): templates[name] = (self, tpl) for imported in self._imports: imp_tpl = imported.stylesheet.getNamedTemplates() for name, (sty, tpl) in imp_tpl.items(): if not templates.has_key(name): templates[name] = (sty, tpl) return templates def getTopLevelVariables(self): return self._primedContext.varBindings.copy() def applyTemplates(self, context, mode, processor, params=None): params = params or {} origState = context.copyStylesheet() context.setStylesheet((self._primedContext.varBindings,self.namespaces, self)) #Set the current node for this template application context.currentNode = context.node matched = 1 for patternInfo in self._patterns.get(mode,[]): context.processorNss = patternInfo[PatternInfo.NSS] pattern = patternInfo[PatternInfo.PATTERN] if pattern.match(context, context.node, patternInfo[PatternInfo.AXIS_TYPE]): patternInfo[PatternInfo.TEMPLATE].instantiate(context, processor, params) break else: for imported in self._imports: if imported.stylesheet.applyTemplates(context, mode, processor, params): break else: matched = 0 context.setStylesheet(origState) return matched def applyImports(self, context, mode, processor, params=None): params = params or {} for imp in self._imports: matched = imp.stylesheet.applyTemplates(context, mode, processor, params) if matched: return 1 return 0 def callTemplate(self, processor, name, context, params, new_level=1): vars = self._primedContext.varBindings.copy() vars.update(params) origState = context.copyStylesheet() context.setStylesheet((vars, self.namespaces, self)) matched = 0 rec_tpl_params = None tpl = self._call_templates.get(name) if tpl: rec_tpl_params = tpl.instantiate(context, processor, params, new_level)[1] else: for child in self._imports: (matched, rec_tpl_params) = child.stylesheet.callTemplate(processor, name, context, params, new_level) if matched: break context.setStylesheet(origState) return (matched, rec_tpl_params) def reclaim(self): self.__dict__['_primedContext'] = None for imp in self._imports: imp.stylesheet.reclaim() ReleaseNode(imp.stylesheet.ownerDocument) self.namespaces = xml.dom.ext.GetAllNs(self) self.spaceRules = {} self.namespaceAliases = ({}, {}) self.decimalFormats = {'': ('.', ',', 'Infinity', '-', 'NaN', '%', '?', '0', '#', ';')} self.keys = {} self.outputParams = OutputParameters() excluded_prefixes = self.getAttributeNS(EMPTY_NAMESPACE, 'exclude-result-prefixes') self.excludedNss = [] self._lres = [] return def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self.namespaces, self.spaceRules, self.namespaceAliases, self.decimalFormats, self.keys, self.outputParams, self.excludedNss, self._patterns, self._call_templates, self._kelems, self.extensionNss, self._topVariables) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self.namespaces = state[1] self.spaceRules = state[2] self.namespaceAliases = state[3] self.decimalFormats = state[4] self.keys = state[5] self.outputParams = state[6] self.excludedNss = state[7] self._patterns = state[8] self._call_templates = state[9] self._kelems = state[10] self.extensionNss = state[11] self._topVariables = state[12] return PyXML-0.8.2/xml/xslt/StylesheetReader.py0100644000076400001440000006124607534565154017357 0ustar martinusers######################################################################## # # File Name: StylesheetReader.py # # Documentation: http://docs.4suite.com/4XSLT/StylesheetReader.py.html # """ Create a stylesheet object WWW: http://4suite.org/4XSLT e-mail: support@4suite.org Copyright (c) 1999-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import string, os, urllib, cStringIO try: from Ft.Lib.ReaderBase import DomletteReader _ReaderBase = DomletteReader except ImportError: from minisupport import MinidomReader _ReaderBase = MinidomReader #FIXME: we might want to do some meta-magic to __import__ element modules on demand from xml.xslt.ApplyTemplatesElement import ApplyTemplatesElement from xml.xslt.AttributeElement import AttributeElement from xml.xslt.AttributeSetElement import AttributeSetElement from xml.xslt.CallTemplateElement import CallTemplateElement from xml.xslt.ChooseElement import ChooseElement from xml.xslt.CopyElement import CopyElement from xml.xslt.CopyOfElement import CopyOfElement from xml.xslt.CommentElement import CommentElement from xml.xslt.ElementElement import ElementElement from xml.xslt.ForEachElement import ForEachElement from xml.xslt.IfElement import IfElement from xml.xslt.LiteralElement import LiteralElement from xml.xslt.LiteralText import LiteralText from xml.xslt.MessageElement import MessageElement from xml.xslt.NumberElement import NumberElement from xml.xslt.OtherwiseElement import OtherwiseElement from xml.xslt.ParamElement import ParamElement from xml.xslt.ProcessingInstructionElement import ProcessingInstructionElement from xml.xslt.SortElement import SortElement from xml.xslt.TemplateElement import TemplateElement from xml.xslt.TextElement import TextElement from xml.xslt.VariableElement import VariableElement from xml.xslt.ValueOfElement import ValueOfElement from xml.xslt.WhenElement import WhenElement from xml.xslt.WithParamElement import WithParamElement from xml.xslt.OtherXslElement import ImportElement, IncludeElement, DecimalFormatElement, KeyElement, NamespaceAliasElement, OutputElement, PreserveSpaceElement, StripSpaceElement, FallbackElement from xml.xslt.Stylesheet import StylesheetElement from xml.xslt import XSL_NAMESPACE, XsltElement from xml.xslt import XsltException, Error, ReleaseNode, RegisterExtensionModules from xml import xslt from xml.dom import Node from xml.dom.ext import StripXml, GetAllNs, SplitQName from xml.dom import implementation, ext, XML_NAMESPACE, XMLNS_NAMESPACE, EMPTY_NAMESPACE try: from Ft.Lib import FtException import Ft.Lib XML_PARSE_ERROR = Ft.Lib.Error.XML_PARSE_ERROR except ImportError: XML_PARSE_ERROR = "XML_PARSE_ERROR" # XXX need better definition class FtException(Exception): pass import cPickle try: from Ft.Lib import pDomlette createDocument = pDomlette.Document def CreateInstantStylesheet(sheet): return pDomlette.PickleDocument(sheet.ownerDocument) def FromInstant(dump, forceBaseUri=None): return UnpickleDocument(dump, forceBaseUri).documentElement except ImportError: from xml.dom import minitraversal import pickle createDocument = minitraversal.Document def CreateInstantStylesheet(sheet): return pickle.dumps(sheet, 1) def FromInstant(dump, forceBaseUri=None): assert not forceBaseUri return pickle.loads(dump) g_mappings = {XSL_NAMESPACE: { 'apply-templates': ApplyTemplatesElement , 'attribute': AttributeElement , 'attribute-set': AttributeSetElement , 'call-template': CallTemplateElement , 'choose': ChooseElement , 'copy': CopyElement , 'copy-of': CopyOfElement , 'comment': CommentElement , 'element': ElementElement , 'for-each': ForEachElement , 'if': IfElement , 'message': MessageElement , 'number': NumberElement , 'otherwise': OtherwiseElement , 'param': ParamElement , 'processing-instruction': ProcessingInstructionElement , 'sort': SortElement , 'stylesheet': StylesheetElement , 'transform': StylesheetElement , 'template': TemplateElement , 'text': TextElement , 'variable': VariableElement , 'value-of': ValueOfElement , 'when': WhenElement , 'fallback': FallbackElement , 'with-param': WithParamElement , 'import': ImportElement , 'include': IncludeElement , 'key': KeyElement , 'namespace-alias': NamespaceAliasElement , 'output': OutputElement , 'preserve-space': PreserveSpaceElement , 'strip-space': StripSpaceElement }} def FromDocument(oldDoc, baseUri='',stylesheetReader = None): #FIXME: We really shouldn't mutate the given doc, but this is the easiest way to strip whitespace if baseUri and baseUri[-1] == '/': modBaseUri = baseUri else: modBaseUri = baseUri + '/' oldDoc.normalize() extElements = xslt.g_extElements source_root = oldDoc.documentElement #Set up a new document for the stylesheet nodes if source_root.namespaceURI == XSL_NAMESPACE: if source_root.localName not in ['stylesheet', 'transform']: raise XsltException(Error.STYLESHEET_ILLEGAL_ROOT, source_root.nodeName) result_elem_root = 0 else: result_elem_root = 1 xsl_doc = createDocument() ext_uris = [] if result_elem_root: vattr = source_root.getAttributeNodeNS(XSL_NAMESPACE, 'version') if not vattr: root_nss = GetAllNs(source_root) if filter(lambda x, n=root_nss: n[x] == XSL_NAMESPACE, root_nss.keys()): raise XsltException(Error.STYLESHEET_MISSING_VERSION) else: raise XsltException(Error.STYLESHEET_MISSING_VERSION_NOTE1) sheet = StylesheetElement(xsl_doc, XSL_NAMESPACE, 'transform', vattr.prefix, baseUri) sheet.setAttributeNS(EMPTY_NAMESPACE, 'version', vattr.value) tpl = TemplateElement(xsl_doc, XSL_NAMESPACE, 'template', vattr.prefix, baseUri) tpl.setAttributeNS(EMPTY_NAMESPACE, 'match', '/') sheet.appendChild(tpl) sheet.__dict__['extensionNss'] = [] xsl_doc.appendChild(sheet) DomConvert(source_root, tpl, xsl_doc, [], extElements, 0) else: sheet = StylesheetElement(xsl_doc, source_root.prefix, source_root.localName, baseUri=baseUri) sty_nss = GetAllNs(source_root) for attr in source_root.attributes.values(): if (attr.namespaceURI, attr.localName) == ('', 'extension-element-prefixes'): ext_prefixes = string.splitfields(attr.value) for prefix in ext_prefixes: if prefix == '#default': prefix = '' ext_uris.append(sty_nss[prefix]) sheet.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) sheet.__dict__['extensionNss'] = ext_uris if not sheet.getAttributeNS(EMPTY_NAMESPACE, 'version'): raise XsltException(Error.STYLESHEET_MISSING_VERSION) xsl_doc.appendChild(sheet) for child in source_root.childNodes: DomConvert(child, sheet, xsl_doc, ext_uris, extElements, 0) #Handle includes includes = filter(lambda x: x.nodeType == Node.ELEMENT_NODE and (x.namespaceURI, x.localName) == (XSL_NAMESPACE, 'include'), sheet.childNodes) for inc in includes: href = inc.getAttributeNS(EMPTY_NAMESPACE,'href') if stylesheetReader is None: stylesheetReader = StylesheetReader() docfrag = stylesheetReader.fromUri(href,baseUri = baseUri, ownerDoc=xsl_doc) sty = docfrag.firstChild included_nss = GetAllNs(sty) for child in sty.childNodes[:]: if child.nodeType != Node.ELEMENT_NODE: continue sheet.insertBefore(child, inc) #migrate old nss from stylesheet directly to new child for prefix in included_nss.keys(): if prefix: child.setAttributeNS(XMLNS_NAMESPACE, 'xmlns:'+prefix, included_nss[prefix]) else: child.setAttributeNS(XMLNS_NAMESPACE, 'xmlns', included_nss[prefix]) sheet.removeChild(inc) ReleaseNode(inc) #sty.reclaim() try: sheet.setup() except: ReleaseNode(sheet.ownerDocument) raise return sheet def DomConvert(node, xslParent, xslDoc, extUris, extElements, preserveSpace): if node.nodeType == Node.ELEMENT_NODE: mapping = g_mappings.get(node.namespaceURI, None) if mapping: if not mapping.has_key(node.localName): raise XsltException(Error.XSLT_ILLEGAL_ELEMENT, node.localName) xsl_class = mapping[node.localName] xsl_instance = xsl_class(xslDoc, baseUri=xslParent.baseUri) for attr in node.attributes.values(): if not attr.namespaceURI and attr.localName not in xsl_instance.__class__.legalAttrs: raise XsltException(Error.XSLT_ILLEGAL_ATTR, attr.nodeName, xsl_instance.nodeName) xsl_instance.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) xslParent.appendChild(xsl_instance) elif node.namespaceURI in extUris: name = (node.namespaceURI, node.localName) if name in extElements.keys(): ext_class = extElements[name] else: #Default XsltElement behavior effects fallback ext_class = XsltElement xsl_instance = ext_class(xslDoc, node.namespaceURI, node.localName, node.prefix, xslParent.baseUri) for attr in node.attributes.values(): if (attr.namespaceURI, attr.localName) == (XSL_NAMESPACE, 'extension-element-prefixes'): ext_prefixes = string.splitfields(attr.value) for prefix in ext_prefixes: if prefix == '#default': prefix = '' extUris.append(node_nss[prefix]) xsl_instance.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) xslParent.appendChild(xsl_instance) else: xsl_instance = LiteralElement(xslDoc, node.namespaceURI, node.localName, node.prefix, xslParent.baseUri) node_nss = GetAllNs(node) for attr in node.attributes.values(): if (attr.namespaceURI, attr.localName) == (XSL_NAMESPACE, 'extension-element-prefixes'): ext_prefixes = string.splitfields(attr.value) for prefix in ext_prefixes: if prefix == '#default': prefix = '' extUris.append(node_nss[prefix]) xsl_instance.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value ) xslParent.appendChild(xsl_instance) ps = (xsl_instance.namespaceURI, xsl_instance.localName) == (XSL_NAMESPACE, 'text') or xsl_instance.getAttributeNS(XML_NAMESPACE,'space') == 'preserve' #ps = (xsl_instance.namespaceURI, xsl_instance.localName) == (XSL_NAMESPACE, 'text') for child in node.childNodes: DomConvert(child, xsl_instance, xslDoc, extUris, extElements, ps) elif node.nodeType == Node.TEXT_NODE: if string.strip(node.data) or preserveSpace: xsl_instance = LiteralText(xslDoc, node.data) xslParent.appendChild(xsl_instance) return ### Domlette Parser Interface ### from xml.parsers import expat class StylesheetReader(_ReaderBase): def __init__(self, force8Bit=0): _ReaderBase.__init__(self) self.force8Bit = force8Bit self._ssheetUri = '' return def fromUri(self, uri, baseUri='', ownerDoc=None, stripElements=None): self._ssheetUri = urllib.basejoin(baseUri, uri) result = _ReaderBase.fromUri(self, uri, baseUri, ownerDoc, stripElements) return result def fromStream(self, stream, baseUri='', ownerDoc=None, stripElements=None): if not xslt.g_registered: xslt.Register() self.initParser() self.initState(ownerDoc, baseUri) p = self.parser try: success = self.parser.ParseFile(stream) except XsltException: raise except Exception, e: for s in self._nodeStack: self.releaseNode(s) if p.ErrorCode: raise FtException(XML_PARSE_ERROR, p.ErrorLineNumber, p.ErrorColumnNumber, expat.ErrorString(p.ErrorCode)) else: raise self._ssheetUri = '' self.killParser() if not success: self.releaseNode(self._rootNode) self.releaseNode(self._ownerDoc) raise XsltException(Error.STYLESHEET_PARSE_ERROR, baseUri, p.ErrorLineNumber, p.ErrorColumnNumber, expat.ErrorString(p.ErrorCode)) self._completeTextNode() root = self._rootNode or self._ownerDoc if root.nodeType == Node.DOCUMENT_NODE: sheet = root.documentElement try: sheet.setup() except: sheet.reclaim() self.releaseNode(root) raise else: sheet = None rt = sheet or root return rt def initParser(self): if self.force8Bit: self.handler = Utf8OnlyHandler(self) else: self.handler = self self.parser=expat.ParserCreate() self.parser.StartElementHandler = self.handler.startElement self.parser.EndElementHandler = self.handler.endElement self.parser.CharacterDataHandler = self.handler.characters self.parser.ProcessingInstructionHandler = self.handler.processingInstruction self.parser.CommentHandler = self.handler.comment self.parser.ExternalEntityRefHandler = self.handler.entityRef return def initState(self, ownerDoc, refUri): pDomlette.Handler.initState(self, ownerDoc) self._preserveStateStack = [0] self._extUris = [] self._extUriStack = [] self._firstElement = 1 if not self._ssheetUri: self._ssheetUri = refUri return def _completeTextNode(self): #Note some parsers don't report ignorable white space properly if self._currText and len(self._nodeStack) and self._nodeStack[-1].nodeType != Node.DOCUMENT_NODE: if self._preserveStateStack[-1] or string.strip(self._currText): new_text = LiteralText(self._ownerDoc, self._currText) self._nodeStack[-1].appendChild(new_text) self._currText = '' return def _initializeSheet(self, rootNode): if rootNode.namespaceURI == XSL_NAMESPACE: if rootNode.localName in ['stylesheet', 'transform']: if not rootNode.getAttributeNS(EMPTY_NAMESPACE, 'version'): raise XsltException(Error.STYLESHEET_MISSING_VERSION) #rootNode.__dict__['extensionNss'] = [] else: raise XsltException(Error.STYLESHEET_ILLEGAL_ROOT, rootNode.nodeName) else: vattr = rootNode.getAttributeNodeNS(XSL_NAMESPACE, 'version') if not vattr: root_nss = GetAllNs(rootNode) if filter(lambda x, n=root_nss: n[x] == XSL_NAMESPACE, root_nss.keys()): raise XsltException(Error.STYLESHEET_MISSING_VERSION) else: raise XsltException(Error.STYLESHEET_MISSING_VERSION_NOTE1) sheet = StylesheetElement(self._ownerDoc, XSL_NAMESPACE, 'transform', vattr.prefix, self._ssheetUri) sheet.setAttributeNS(EMPTY_NAMESPACE, 'version', vattr.value) tpl = TemplateElement(self._ownerDoc, XSL_NAMESPACE, 'template', vattr.prefix, self._ssheetUri) tpl.setAttributeNS(EMPTY_NAMESPACE, 'match', '/') sheet.appendChild(tpl) sheet.__dict__['extensionNss'] = [] self._nodeStack[-1].appendChild(sheet) # Ensure the literal element is a child of the template # endElement appends to the end of the nodeStack self._nodeStack.append(tpl) self._firstElement = 0 return def _handleExtUris(self, ns, local, value, extUri, delExtu, sheet): if (ns, local) == (extUri, 'extension-element-prefixes'): ext_prefixes = string.splitfields(value) for prefix in ext_prefixes: if prefix == '#default': prefix = '' uri = self._namespaces[-1].get(prefix, '') if uri not in self._extUris: delExtu.append(uri) self._extUris.append(uri) if sheet and not uri in sheet.extensionNss: sheet.extensionNss.append(uri) return def processingInstruction(self, target, data): self._completeTextNode() return def comment(self, data): self._completeTextNode() return def startElement(self, name, attribs): self._completeTextNode() (name, qname, nsattribs) = self._handleStartElementNss(name, attribs) nsuri = name[0] local = name[1] prefix = SplitQName(qname)[0] mapping = g_mappings.get(nsuri, None) del_extu = [] if mapping: if not mapping.has_key(local): if self._firstElement: raise XsltException(Error.STYLESHEET_ILLEGAL_ROOT, name) else: raise XsltException(Error.XSLT_ILLEGAL_ELEMENT, local) xsl_class = mapping[local] if xsl_class == IncludeElement: #Can the included sheet have literal result element as root? inc = self.clone().fromUri(nsattribs[('', 'href')], baseUri=self._ssheetUri, ownerDoc=self._ownerDoc) sty = inc.firstChild included_nss = GetAllNs(sty) for child in sty.childNodes[:]: self._nodeStack[-1].appendChild(child) #migrate old nss from stylesheet directly to new child for prefix in included_nss.keys(): if prefix: child.setAttributeNS(XMLNS_NAMESPACE, 'xmlns:'+prefix, included_nss[prefix]) else: child.setAttributeNS(XMLNS_NAMESPACE, 'xmlns', included_nss[prefix]) self._nodeStack.append(None) pDomlette.ReleaseNode(inc) return else: xsl_instance = xsl_class(self._ownerDoc, baseUri=self._ssheetUri) for aqname in nsattribs.getQNames(): (ansuri, alocal) = nsattribs.getNameByQName(aqname) value = nsattribs.getValueByQName(aqname) if ansuri != XMLNS_NAMESPACE and xsl_class == StylesheetElement: self._handleExtUris(ansuri, alocal, value, '', del_extu,xsl_instance) elif not ansuri and alocal not in xsl_instance.__class__.legalAttrs: raise XsltException(Error.XSLT_ILLEGAL_ATTR, aqname, xsl_instance.nodeName) xsl_instance.setAttributeNS(ansuri, aqname, value) else: if nsuri in self._extUris and self._extElements: #Default XsltElement behavior effects fallback ext_class = self._extElements.get((nsuri, local), XsltElement) xsl_instance = ext_class(self._ownerDoc, nsuri, local, prefix, self._ssheetUri) else: xsl_instance = LiteralElement(self._ownerDoc, nsuri, local, prefix, self._ssheetUri) for aqname in nsattribs.getQNames(): (ansuri, alocal) = nsattribs.getNameByQName(aqname) value = nsattribs.getValueByQName(aqname) if ansuri != XMLNS_NAMESPACE: self._handleExtUris(ansuri, alocal, value, '', del_extu, xsl_instance) if hasattr(xsl_instance.__class__, 'legalAttrs'): if not ansuri and alocal not in xsl_instance.__class__.legalAttrs: raise XsltException(Error.XSLT_ILLEGAL_ATTR, alocal, xsl_instance.nodeName) xsl_instance.setAttributeNS(ansuri, aqname, value) self._extUriStack.append(del_extu) if (xsl_instance.namespaceURI, xsl_instance.localName) == (XSL_NAMESPACE, 'text') or xsl_instance.getAttributeNS(XML_NAMESPACE, 'space') == 'preserve': self._preserveStateStack.append(1) elif xsl_instance.getAttributeNS(XML_NAMESPACE, 'space') == 'default': self._preserveStateStack.append(0) else: self._preserveStateStack.append(self._preserveStateStack[-1]) if self._firstElement: self._initializeSheet(xsl_instance) self._nodeStack.append(xsl_instance) return def endElement(self, name): if not self._nodeStack[-1]: del self._nodeStack[-1] return self._completeTextNode() del self._preserveStateStack[-1] new_element = self._nodeStack[-1] del self._nodeStack[-1] del self._namespaces[-1] self._nodeStack[-1].appendChild(new_element) del_extu = self._extUriStack[-1] del self._extUriStack[-1] for uri in del_extu: self._extUris.remove(uri) return def characters(self, data): self._currText = self._currText + data return def CreateInstantStylesheet(sheet): return pDomlette.PickleDocument(sheet.ownerDocument) def FromInstant(dump, forceBaseUri=None): return UnpickleDocument(dump, forceBaseUri).documentElement ##FIXME ##This unpickling code is Basically a transplant from pDomlette ##with the addition of baseUri overriding in unpickling. It is ##somewhat experimental and not intended to diverge from the pDomlette ##code, and if it ever does so, it should be nixed, and some ##genericity found between this the pDomlette code import threading, cPickle g_lock = threading.Lock() def UnpickleDocument(pickledXml, forceBaseUri=None): g_lock.acquire() try: doc = pDomlette.Document() stream = cStringIO.StringIO(pickledXml) unpickler = cPickle.Unpickler(stream) _UnpickleChildren(unpickler, doc, forceBaseUri) return doc finally: g_lock.release() def UnpickleNode(pickledXml, doc=None, forceBaseUri=None): g_lock.acquire() try: doc = doc or Document() stream = cStringIO.StringIO(pickledXml) unpickler = cPickle.Unpickler(stream) topLevelNode = unpickler.load() if forceBaseUri is None and hasattr(topLevelNode, 'baseUri'): topLevelNode.baseUri = forceBaseUri doc.appendChild(topLevelNode) if topLevelNode.attributes: for attr in topLevelNode.attributes.values(): attr.ownerDocument = topLevelNode.ownerDocument _UnpickleChildren(unpickler, topLevelNode, forceBaseUri) return topLevelNode finally: g_lock.release() ## Helper function for unpickling ## def _UnpickleChildren(unpickler, node, forceBaseUri=None): children = unpickler.load() while children: child = unpickler.load() if forceBaseUri is None and hasattr(child, 'baseUri'): child.baseUri = forceBaseUri node.appendChild(child) if child.nodeType == Node.ELEMENT_NODE: for attr in child.attributes: attr.ownerDocument = child.ownerDocument _UnpickleChildren(unpickler, child, forceBaseUri) children = children - 1 PyXML-0.8.2/xml/xslt/TemplateElement.py0100644000076400001440000001274407377133277017171 0ustar martinusers######################################################################## # # File Name: TemplateElement.py # # Docs: http://docs.4suite.com/4XSLT/TemplateElement.py.html # """ Implementation of the XSLT Spec template stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import re, string from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element import xml.xslt from xml.xpath.Util import ExpandQName from xml.xslt import XsltElement, XsltException, XPatternParser, Error, XSL_NAMESPACE from xml.xpath import Util #FIXME: We don't handle the priority rules rightly for templates with matches of the form a|b|c. see spec 5.5 class TemplateElement(XsltElement): legalAttrs = ('match', 'mode', 'priority', 'name') def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='template', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) def setup(self): self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) self.__dict__['_match'] = self.getAttributeNS(EMPTY_NAMESPACE, 'match') mode_attr = self.getAttributeNS(EMPTY_NAMESPACE, 'mode') if not mode_attr: self.__dict__['_mode'] = None else: split_name = Util.ExpandQName( mode_attr, namespaces=self._nss ) self.__dict__['_mode'] = split_name name_attr = self.getAttributeNS(EMPTY_NAMESPACE, 'name') split_name = Util.ExpandQName( name_attr, namespaces=self._nss ) self.__dict__['_name'] = split_name self.__dict__['_params'] = [] self.__dict__['_elements'] = [] for child in self.childNodes: if child.namespaceURI == XSL_NAMESPACE: if child.localName == 'param': self.__dict__['_params'].append(child) elif child.localName in ['choose', 'if']: self.__dict__['_elements'].append((1, child)) else: self.__dict__['_elements'].append((0, child)) else: self.__dict__['_elements'].append((0, child)) #A list of tuples #(pattern,qmatch,priority) #either pattern or qmatch will be present but not both self.__dict__['_patternInfo'] = [] if self._match: priority = self.getAttributeNS(EMPTY_NAMESPACE, 'priority') or None if priority is not None: try: priority = float(priority) except: raise XsltException(Error.ILLEGAL_TEMPLATE_PRIORITY) parser = XPatternParser.XPatternParser() shortcuts = parser.parsePattern(self._match).getMatchShortcuts() for pattern, (shortcut, extra_arg) in shortcuts: if priority is None: tpl_priority = pattern.priority else: tpl_priority = priority self.__dict__['_patternInfo'].append((shortcut, extra_arg, tpl_priority)) def getMatchInfo(self): return (self._patternInfo,self._mode,self._nss) def instantiate(self, context, processor, params=None, new_level=1): params = params or {} #NOTE Don't reset the context context.setNamespaces(self._nss) origVars = context.varBindings.copy() # Set the parameter list for param in self._params: value = params.get(param._name) if value is not None: context.varBindings[param._name] = value else: context = param.instantiate(context, processor)[0] rec_tpl_params = None for (recurse,child) in self._elements: if recurse: context, rec_tpl_params = child.instantiate(context, processor, new_level) else: context = child.instantiate(context, processor)[0] context.varBindings = origVars return (context, rec_tpl_params) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._name, self._mode, self._patternInfo, self._match, self._params, self._elements) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._name = state[2] self._mode = state[3] self._patternInfo = state[4] self._match = state[5] self._params = state[6] self._elements = state[7] return def mergeUnbalancedPipes(self, patterns): ctr = 0 while ctr < len(patterns)-1: if string.count(patterns[ctr],'[') != string.count(patterns[ctr], ']'): patterns[ctr] = patterns[ctr] + '|' +patterns[ctr+1] else: ctr = ctr + 1 patterns = map(lambda x:string.strip(x), patterns) return patterns PyXML-0.8.2/xml/xslt/TextElement.py0100644000076400001440000000457607377133277016346 0ustar martinusers######################################################################## # # File Name: TextElement.py # # Documentation: http://docs.4suite.com/4XSLT/TextElement.py.html # """ Implementation of the XSLT Spec text stylesheet element. WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ from xml.dom import EMPTY_NAMESPACE import xml.dom.ext import xml.dom.Element from xml.xpath import CoreFunctions from xml.xslt import XsltElement, XsltException, Error from xml.dom import Node class TextElement(XsltElement): legalAttrs = ('disable-output-escaping',) def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='text', prefix='xsl', baseUri=''): XsltElement.__init__(self, doc, uri, localName, prefix, baseUri) return def setup(self): self.__dict__['_disable_output_escaping'] = self.getAttributeNS(EMPTY_NAMESPACE, 'disable-output-escaping') == 'yes' self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self) for child in self.childNodes: if child.nodeType == Node.ELEMENT_NODE: raise XsltException(Error.ILLEGAL_TEXT_CHILD) self.normalize() return def instantiate(self, context, processor): if not self.firstChild: return (context,) if context.processorNss != self._nss: origState = context.copyNamespaces() context.setNamespaces(self._nss) else: origState = None value = self.firstChild and self.firstChild.data or '' if self._disable_output_escaping: processor.writers[-1].text(value, escapeOutput=0) else: processor.writers[-1].text(value) origState and context.setNamespaces(origState) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = XsltElement.__getstate__(self) new_state = (base_state, self._nss, self._disable_output_escaping) return new_state def __setstate__(self, state): XsltElement.__setstate__(self, state[0]) self._nss = state[1] self._disable_output_escaping = state[2] return PyXML-0.8.2/xml/xslt/TextSax.py0100644000076400001440000000334707255676734015510 0ustar martinusers######################################################################## # # File Name: TextSax.py # # Documentation: http://docs.4suite.com/4XSLT/TextSax.py.html # # """ Components for reading Text files from a SAX-like producer. WWW: http://4suite.com/4DOM e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import sys, string, cStringIO class TextGenerator: def __init__(self, keepAllWs=0): self.__currText = '' def getRootNode(self): return self.__currText def startElement(self, name, attribs): st = "<" + name for attr in attribs.keys(): st = st + " %s = %s " % (attr,attribs[attr]) st = st + '>\n' self.__currText = self.__currText + st def endElement(self, name): st = "" % name self.__currText = self.__currText + st def ignorableWhitespace(self, ch, start, length): """ If 'keepAllWs' permits, add ignorable white-space as a text node. Remember that a Document node cannot contain text nodes directly. If the white-space occurs outside the root element, there is no place for it in the DOM and it must be discarded. """ if self.__keepAllWs: self.__currText = self.__currText + ch[start:start+length] def characters(self, ch, start, length): self.__currText = self.__currText + ch[start:start+length] #Overridden ErrorHandler methods #def warning(self, exception): # raise exception def error(self, exception): raise exception def fatalError(self, exception): raise exception PyXML-0.8.2/xml/xslt/TextWriter.py0100644000076400001440000002313107377133277016215 0ustar martinusers######################################################################## # # File Name: TextWriter.py # # Documentation: http://docs.4suite.com/4XSLT/TextWriter.py.html # """ Implement the core Writer for XSLT processor output WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc., USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import os, re, string, cStringIO from xml.dom import EMPTY_NAMESPACE import xml.dom.ext from xml.dom.ext.Printer import TranslateCdata, TranslateCdataAttr from xml.dom.html import TranslateHtmlCdata from xml.xslt import XSL_NAMESPACE, TextSax from xml.dom.html import HTML_4_TRANSITIONAL_INLINE, HTML_4_STRICT_INLINE from xml.dom import XML_NAMESPACE from xml.dom.html import HTML_FORBIDDEN_END class ElementData: def __init__(self, name, cdataElement, attrs, extraNss=None): self.name = name self.cdataElement = cdataElement self.attrs = attrs self.extraNss = extraNss or {} return class TextWriter: def __init__(self, outputParams): self._currElement = None self._namespaces = [{'': EMPTY_NAMESPACE, 'xml': XML_NAMESPACE}] self._result = cStringIO.StringIO() self._outputParams = outputParams self._outputParams.mediaType = outputParams.mediaType or 'text/plain' self._indent = '' self._nextNewLine = 0 self._cdataSectionElement = 0 self._first_element = 1 self._strict_inline = [0] self._cachedPis = [] return def _prolog(self, docElem): if self._outputParams.method == 'html' and self._outputParams.indent is None: self._outputParams.indent = 'yes' if self._outputParams.method in [None, 'xml']: #FIXME: Case-sensitivity? if self._outputParams.omitXmlDeclaration in [None,'no']: self._result.write("\n") if self._outputParams.doctypeSystem: self._result.write('\n') for target,data in self._cachedPis: self._writePiOrXmlDecl(target,data) self._result.write('\n' + self._indent) self._nextNewLine = 0 return def getResult(self): self._completeLastElement(0) return self._result.getvalue() def text(self, text, escapeOutput=1): self._completeLastElement(0) if escapeOutput: if text and text[0] == '>': self._result.seek(-2, 2) last_chars = self._result.read() else: last_chars = '' new_text = text if self._outputParams.method == 'html': new_text = TranslateHtmlCdata( new_text, self._outputParams.encoding or 'UTF-8', last_chars ) else: new_text = TranslateCdata( new_text, self._outputParams.encoding or 'UTF-8', last_chars, markupSafe=self._cdataSectionElement ) self._result.write(new_text) else: self._result.write(text) self._nextNewLine = 0 return def attribute(self, name, value, namespace=EMPTY_NAMESPACE): self._currElement.attrs[name] = value (prefix, local) = xml.dom.ext.SplitQName(name) if self._outputParams.method == 'xml': self._namespaces[-1][prefix] = namespace return def processingInstruction(self, target, data): if self._first_element: self._cachedPis.append((target,data)) return self._completeLastElement(0) self._writePiOrXmlDecl(target,data) return def _writePiOrXmlDecl(self, target, data): pi = '' % (target, data) if self._outputParams.indent == 'yes': self._result.write("%s%s\n" % (self._indent, pi)) else: self._result.write(pi) self._nextNewLine = 1 return def comment(self, body): self._completeLastElement(0) if self._outputParams.indent == 'yes': self._result.write(self._indent + "\n"%(body)) else: self._result.write(""%(body)) self._nextNewLine = 1 return def startElement(self, name, namespace=EMPTY_NAMESPACE, extraNss=None): extraNss = extraNss or {} self._strict_inline.append(string.upper(name) in HTML_4_STRICT_INLINE) if self._first_element: if not self._outputParams.method: if string.upper(name) == 'HTML': self._outputParams.method = 'html' else: self._outputParams.method = 'xml' self._first_element = 0 self._prolog(name) self._completeLastElement(0) (prefix, local) = xml.dom.ext.SplitQName(name) cdatas_flag = 0 if self._outputParams.method == 'xml': cdatas_flag = (namespace, local) in self._outputParams.cdataSectionElements self._currElement = ElementData(name, cdatas_flag, {}, extraNss) self._namespaces.append(self._namespaces[-1].copy()) if self._outputParams.method == 'xml': self._namespaces[-1][prefix] = namespace return def endElement(self, name): if self._currElement: elementIsEmpty = 1 endElementHandled = self._completeLastElement(1) else: elementIsEmpty = endElementHandled = 0 if self._outputParams.indent == 'yes': self._indent = self._indent[:-2] if self._outputParams.method == 'xml' and self._cdataSectionElement: self._result.write(']]>') self._cdataSectionElement = 0 if self._outputParams.method == 'html': if (string.upper(name) not in HTML_FORBIDDEN_END): if self._outputParams.indent == 'yes' and not self._strict_inline[-1]: if self._nextNewLine and not elementIsEmpty: self._result.write('\n' + self._indent) self._result.write((not endElementHandled) and ('' % name) or '') else: self._result.write((not endElementHandled) and ('' % name) or '') else: if self._outputParams.indent == 'yes' and self._nextNewLine and not elementIsEmpty: self._result.write('\n' + self._indent) self._result.write((not endElementHandled) and ('' % name) or '') self._nextNewLine = 1 del self._namespaces[-1] self._strict_inline.pop() return def _completeLastElement(self, elementIsEmpty): endElementHandled = 1 if self._currElement: elem = self._currElement if self._outputParams.indent == 'yes' and self._nextNewLine and not self._strict_inline[-1]: self._result.write('\n' + self._indent) self._result.write('<' + elem.name) encoding = self._outputParams.encoding or 'UTF-8' for name,value in elem.attrs.items(): value = TranslateCdata(value, encoding) value, delimiter = TranslateCdataAttr(value) self._result.write(' %s=%s%s%s' % (name,delimiter,value,delimiter)) if self._outputParams.method == 'xml': #Handle namespaces nss = elem.extraNss nss.update(self._namespaces[-1]) for prefix in nss.keys(): ns = nss[prefix] prev_ns = self._namespaces[-2].get(prefix, None) if ns and not prev_ns: if prefix: self._result.write(" xmlns:%s='%s'" % (prefix, ns)) else: self._result.write(" xmlns='%s'" % ns) self._namespaces[-1] = nss if elementIsEmpty: if self._outputParams.method != 'html': self._result.write('/>') else: self._result.write('>') endElementHandled = 0 else: self._result.write('>') if self._currElement.cdataElement: self._result.write('>> ") parser = XPatternParser() try: result = parser.parsePattern(st) result.pprint() except XPatternParserBase.InternalException, e: XPatternParserBase.PrintInternalException(e) except XPatternParserBase.SyntaxException, e: XPatternParserBase.PrintSyntaxException(e) PyXML-0.8.2/xml/xslt/XPatternParserBase.py0100644000076400001440000000740707377133422017611 0ustar martinusersimport XPattern try: import os, gettext locale_dir = os.path.split(__file__)[0] gettext.install('4Suite', locale_dir) except (ImportError,AttributeError,IOError): def _(msg): return msg SYNTAX_ERR_MSG = _("Error parsing pattern:\n'%s'\nSyntax error at or near '%s' Line: %d, Production Number: %s") INTERNAL_ERR_MSG = _("Error parsing pattern:\n'%s'\nInternal error in processing at or near '%s', Line: %d, Production Number: %s, Exception: %s") class SyntaxException(Exception): def __init__(self, source, lineNum, location, prodNum): Exception.__init__(self, SYNTAX_ERR_MSG%(source, location, lineNum, prodNum)) self.source = source self.lineNum = lineNum self.loc = location self.prodNum = prodNum class InternalException(Exception): def __init__(self, source, lineNum, location, prodNum, exc, val, tb): Exception.__init__(self, INTERNAL_ERR_MSG%(source, location, lineNum, prodNum, exc)) self.source = source self.lineNum = lineNum self.loc = location self.prodNum = prodNum self.errorType = exc self.errorValue = val self.errorTraceback = tb import threading g_parseLock = threading.RLock() class XPatternParserBase: def __init__(self): self.initialize() def initialize(self): self.results = None self.__stack = [] XPattern.cvar.g_prodNum = "-1" XPattern.cvar.g_errorOccured = 0 def parse(self,st): g_parseLock.acquire() try: self.initialize() XPattern.my_XPatternparse(self,st) if XPattern.cvar.g_errorOccured == 1: raise SyntaxException( st, XPattern.cvar.lineNum, XPattern.cvar.g_errorLocation, XPattern.cvar.g_prodNum) if XPattern.cvar.g_errorOccured == 2: raise InternalException( st, XPattern.cvar.lineNum, XPattern.cvar.g_errorLocation, XPattern.cvar.g_prodNum, XPattern.cvar.g_errorType, XPattern.cvar.g_errorValue, XPattern.cvar.g_errorTraceback) return self.__stack finally: g_parseLock.release() def pop(self): if len(self.__stack): rt = self.__stack[-1] del self.__stack[-1] return rt self.raiseException("Pop with 0 stack length") def push(self,item): self.__stack.append(item) def empty(self): return len(self.__stack) == 0 def size(self): return len(self.__stack) def raiseException(self, message): raise Exception(message + "\n" + "EBNF ProductionNumber: " + str(XPattern.cvar.g_prodNum) ) ### Callback methods ### def PrintSyntaxException(e): print "********** Syntax Exception **********" print "Exception at or near '%s'" % e.loc print " Line: %d, Production Number: %s" % (e.lineNum, str(e.prodNum)) def PrintInternalException(e): print "********** Internal Exception **********" print "Exception at or near '%s'" % e.loc print " Line: %d, Production Number: %s" % (e.lineNum, e.prodNum) print " Exception: %s" % e.errorType print "Original traceback:" import traceback traceback.print_tb(e.errorTraceback) if __name__ == "__main__": import sys p = XPatternParserBase() if len(sys.argv) == 2: l = open(sys.argv[1],"r").read() else: l = raw_input(">>>") try: p.parse(l) except InternalException, e: PrintInternalException(e) except SyntaxException, e: PrintSyntaxException(e) PyXML-0.8.2/xml/xslt/XmlWriter.py0100644000076400001440000001616007406041742016021 0ustar martinusers######################################################################## # # File Name: XmlWriter.py # # Documentation: http://docs.4suite.com/4XSLT/XmlWriter.py.html # """ Implements the XML output writer for XSLT processor output WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999-2000 Fourthought Inc., USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import os, re, string import xml.dom.ext from xml.dom.ext.Printer import TranslateCdata, TranslateCdataAttr from xml.dom.html import TranslateHtmlCdata from xml.xslt import XSL_NAMESPACE, NullWriter, XsltException, Error from xml.dom.html import HTML_4_TRANSITIONAL_INLINE, HTML_4_STRICT_INLINE from xml.dom import XML_NAMESPACE, EMPTY_NAMESPACE from xml.dom.html import HTML_FORBIDDEN_END class ElementData: def __init__(self, name, cdataElement, attrs, extraNss=None): self.name = name self.cdataElement = cdataElement self.attrs = attrs self.extraNss = extraNss or {} return class XmlWriter(NullWriter.NullWriter): def __init__(self, outputParams, stream=None): NullWriter.NullWriter.__init__(self, outputParams, stream) self._outputParams.encoding = outputParams.encoding or 'UTF-8' self._outputParams.indent = outputParams.indent == 'yes' self._outputParams.mediaType = outputParams.mediaType or 'text/xml' self._currElement = None self._namespaces = [{'': EMPTY_NAMESPACE, 'xml': XML_NAMESPACE}] self._indent = '' self._nextNewLine = 0 self._cdataSectionElement = 0 self._first_element = 1 self._cached = [] return def _doctype(self, docElem): external_id = '' if self._outputParams.doctypePublic and self._outputParams.doctypeSystem: external_id = ' PUBLIC "' + self._outputParams.doctypePublic + '" "' + self._outputParams.doctypeSystem + '"' elif self._outputParams.doctypeSystem: external_id = ' SYSTEM "' + self._outputParams.doctypeSystem + '"' if external_id: self._stream.write('\n' % (docElem, external_id)) self._first_element = 0 def startDocument(self): if self._outputParams.omitXmlDeclaration in [None,'no']: self._stream.write("\n") return def endDocument(self): self._completeLastElement(0) return def text(self, text, escapeOutput=1): self._completeLastElement(0) if escapeOutput: if text and text[0] == '>': self._stream.seek(-2, 2) last_chars = self._stream.read() else: last_chars = '' text = TranslateCdata( text, self._outputParams.encoding, last_chars, markupSafe=self._cdataSectionElement ) self._stream.write(text) self._nextNewLine = 0 return def attribute(self, name, value, namespace=EMPTY_NAMESPACE): if not self._currElement: raise XsltException(Error.ATTRIBUTE_ADDED_AFTER_ELEMENT) value = TranslateCdata(value, self._outputParams.encoding) self._currElement.attrs[name] = TranslateCdataAttr(value) (prefix, local) = xml.dom.ext.SplitQName(name) self._namespaces[-1][prefix] = namespace return def processingInstruction(self, target, data): self._completeLastElement(0) target = string.strip(TranslateCdata(target, self._outputParams.encoding, '')) data = string.strip(TranslateCdata(data, self._outputParams.encoding, '')) pi = '' % (target, data) if self._outputParams.indent: self._stream.write("%s%s\n" % (self._indent, pi)) else: self._stream.write(pi) self._nextNewLine = 1 return def comment(self, body): self._completeLastElement(0) body = TranslateCdata(body, self._outputParams.encoding, '') comment = "" % body if self._outputParams.indent: self._stream.write("%s%s\n" % (self._indent, comment)) else: self._stream.write(comment) self._nextNewLine = 1 return def startElement(self, name, namespace=EMPTY_NAMESPACE, extraNss=None): extraNss = extraNss or {} self._completeLastElement(0) if self._first_element: self._doctype(name) (prefix, local) = xml.dom.ext.SplitQName(name) cdatas_flag = (namespace, local) in self._outputParams.cdataSectionElements self._currElement = ElementData(name, cdatas_flag, {}, extraNss) self._namespaces.append(self._namespaces[-1].copy()) self._namespaces[-1][prefix] = namespace return def endElement(self, name): if self._currElement: elementIsEmpty = 1 self._completeLastElement(1) else: elementIsEmpty = 0 if self._outputParams.indent: self._indent = self._indent[:-2] if self._cdataSectionElement: self._stream.write(']]>') self._cdataSectionElement = 0 if self._outputParams.indent and self._nextNewLine and not elementIsEmpty: self._stream.write('\n' + self._indent) self._stream.write((not elementIsEmpty) and ('' % name) or '') self._nextNewLine = 1 del self._namespaces[-1] return def _completeLastElement(self, elementIsEmpty): if self._currElement: elem = self._currElement if self._outputParams.indent and self._nextNewLine: self._stream.write('\n' + self._indent) self._stream.write('<' + elem.name) for (name, (value, delimiter)) in elem.attrs.items(): self._stream.write(' %s=%s%s%s' % (name,delimiter,value,delimiter)) #Handle namespaces nss = elem.extraNss nss.update(self._namespaces[-1]) for prefix in nss.keys(): ns = nss[prefix] prev_ns = self._namespaces[-2].get(prefix, None) if ns and not prev_ns: if prefix: self._stream.write(" xmlns:%s='%s'" % (prefix, ns)) else: self._stream.write(" xmlns='%s'" % ns) self._namespaces[-1] = nss if elementIsEmpty: self._stream.write('/>') else: self._stream.write('>') if self._currElement.cdataElement: self._stream.write('' % ( id(self), repr(self.node), self.position, self.size ) PyXML-0.8.2/xml/xslt/XsltFunctions.py0100644000076400001440000002007707377133277016725 0ustar martinusers######################################################################## # # File Name: XsltFunctions.py # # Docs: http://docs.4suite.com/XSLT/XsltFunctions.py.html # """ WWW: http://4suite.org/XSLT e-mail: support@4suite.org Copyright (c) 1999-2000 FourThought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """ import cStringIO, os, re, urlparse, urllib from xml.dom import EMPTY_NAMESPACE import xml.dom.ext from xml.dom import Node from xml.dom.DocumentFragment import DocumentFragment from xml.xpath import CoreFunctions, Conversions, Util, g_extFunctions from xml.xslt import XsltException, Error, XSL_NAMESPACE from xml.xslt import g_extElements # from Ft.Lib import Uri # import os # BETA_DOMLETTE = os.environ.get("BETA_DOMLETTE") # if BETA_DOMLETTE: # from Ft.Lib import cDomlette # g_readerClass = cDomlette.RawExpatReader # g_domModule = cDomlette # else: # from Ft.Lib import pDomlette # g_readerClass = pDomlette.PyExpatReader # g_domModule = pDomlette def Document(context, object, nodeSet=None): result = [] baseUri = getattr(context.stylesheet, 'baseUri', '') #if baseUri: baseUri= baseUri + '/' if nodeSet: baseUri = getattr(nodeSet[0], 'baseUri', baseUri) if nodeSet is None: if type(object) == type([]): for curr_node in object: result = result + Document( context, Conversions.StringValue(curr_node), [curr_node] ) elif object == '': result = [context.stylesheet.ownerDocument] context.stylesheet.newSource(context.stylesheet.ownerDocument, context.processor) #Util.IndexDocument(context.stylesheet.ownerDocument) else: try: #FIXME: Discard fragments before checking for dupes uri = Conversions.StringValue(object) if context.documents.has_key(uri): result = context.documents[uri] else: try: doc = context.stylesheet._docReader.fromUri(uri, baseUri=baseUri) except: raise #Util.IndexDocument(doc) context.stylesheet.newSource(doc, context.processor) result = [doc] except IOError: pass elif type(nodeSet) == type([]): if type(object) == type([]): for curr_node in object: result = result + Document( context, Conversions.StringValue(curr_node), nodeSet ) else: try: uri = Conversions.StringValue(object) #FIXME: Discard fragments before checking for dupes if context.documents.has_key(uri): result = context.documents[uri] else: doc = context.stylesheet._docReader.fromUri(uri, baseUri=baseUri) #Util.IndexDocument(doc) context.stylesheet.newSource(doc, context.processor) result = [doc] except IOError: pass return result def Key(context, qname, keyList): result = [] name = Util.ExpandQName(Conversions.StringValue(qname), namespaces=context.processorNss) if context.stylesheet.keys.has_key(name): a_dict = context.stylesheet.keys[name] if type(keyList) != type([]): keyList = [keyList] for key in keyList: key = Conversions.StringValue(key) result = result + a_dict.get(key, []) return result def Current(context): return [context.currentNode] def UnparsedEntityUri(context, name): if hasattr(context.node.ownerDoc, '_unparsedEntities') and context.node.ownerDoc._unparsedEntities.has_key(name): return context.node.ownerDoc._unparsedEntities[name] return '' def GenerateId(context, nodeSet=None): if nodeSet is not None and type(nodeSet) != type([]): raise XsltException(Error.WRONG_ARGUMENT_TYPE) if not nodeSet: return 'id' + `id(context.node)` else: node = Util.SortDocOrder(nodeSet)[0] return 'id' + `id(node)` def SystemProperty(context, qname): uri, lname = Util.ExpandQName(Conversions.StringValue(qname), namespaces=context.processorNss) if uri == XSL_NAMESPACE: if lname == 'version': return 1.0 if lname == 'vendor': return "Fourthought Inc." if lname == 'vendor-url': return "http://4Suite.org" elif uri == 'http://xmlns.4suite.org/xslt/env-system-property': return os.environ.get(lname, '') elif uri == 'http://xmlns.4suite.org': if lname == 'version': return __version__ return '' def FunctionAvailable(context, qname): split_name = Util.ExpandQName(Conversions.StringValue(qname), namespaces=context.processorNss) if g_extFunctions.has_key(split_name) or CoreFunctions.CoreFunctions.has_key(split_name): return CoreFunctions.True(context) else: return CoreFunctions.False(context) def ElementAvailable(context, qname): split_name = Util.ExpandQName(Conversions.StringValue(qname), namespaces=context.processorNss) if g_extElements.has_key(split_name) or CoreFunctions.CoreFunctions.has_key(split_name): return CoreFunctions.True(context) else: return CoreFunctions.False(context) def XsltStringValue(object): #def XsltStringValue(object, cache=None): #print "XsltStringValue cache", cache #if cache and cache.has_key(object): #print "found:", cache[object] #return cache[object] if hasattr(object, 'stringValue'): return 1, object.stringValue if hasattr(object, 'nodeType') and object.nodeType == Node.DOCUMENT_FRAGMENT_NODE: result = '' for node in object.childNodes: result = result + Conversions.CoreStringValue(node)[1] #if cache is not None: cache[object] = result return 1, result return 0, None def XsltNumberValue(object): handled, value = XsltStringValue(object) if handled: return 1, Conversions.NumberValue(value) return 0, None def XsltBooleanValue(object): handled, value = XsltStringValue(object) if handled: return 1, Conversions.BooleanValue(value) return 0, None ##0 decimal-separator ##1 grouping-separator ##2 infinity ##3 minus-sign ##4 NaN ##5 percent ##6 per-mille ##7 zero-digit ##8 digit ##9 pattern-separator def FormatNumber(context, number, formatString, decimalFormatName=None): decimal_format = '' num = Conversions.NumberValue(number) format_string = Conversions.StringValue(formatString) if decimalFormatName is not None: split_name = Util.ExpandQName(decimalFormatName, namespaces=context.processorNss) decimal_format = context.stylesheet.decimalFormats[split_name] else: decimal_format = context.stylesheet.decimalFormats[''] from Ft.Lib import routines result = routines.FormatNumber(num, format_string) return result Conversions.g_stringConversions.insert(0, XsltStringValue) Conversions.g_numberConversions.insert(0, XsltNumberValue) Conversions.g_booleanConversions.insert(0, XsltBooleanValue) ExtFunctions = { (EMPTY_NAMESPACE, 'document'): Document, (EMPTY_NAMESPACE, 'key'): Key, (EMPTY_NAMESPACE, 'current'): Current, (EMPTY_NAMESPACE, 'generate-id'): GenerateId, (EMPTY_NAMESPACE, 'system-property'): SystemProperty, (EMPTY_NAMESPACE, 'function-available'): FunctionAvailable, (EMPTY_NAMESPACE, 'element-available'): ElementAvailable, (EMPTY_NAMESPACE, 'string-value'): XsltStringValue, (EMPTY_NAMESPACE, 'format-number'): FormatNumber, (EMPTY_NAMESPACE, 'unparsed-entity-uri'): UnparsedEntityUri } PyXML-0.8.2/xml/xslt/_4xslt.py0100644000076400001440000001071607277470665015322 0ustar martinusers#!/usr/bin/env python ######################################################################## # # File Name: 4xslt.py # # Documentation: http://docs.4suite.com/4XSLT/4xslt.py.html # """ Command-line invokation of the 4XSLT processor WWW: http://4suite.com/4XSLT e-mail: support@4suite.com Copyright (c) 1999 FourThought LLC, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ import re, string, os, sys, getopt, cStringIO, traceback import xml.dom.ext from xml import xpath, xslt from xml.xslt import XsltException from xml.xslt.Processor import Processor MAX_PYTHON_RECURSION_DEPTH=10000 g_paramBindingPattern = re.compile(r"([\d\D_\.\-]*:?[\d\D_\.\-]+)=(.*)") g_usage = """ 4XSLT version %s Usage: %s [options] []... Options: -i Ignore stylesheet processing instructions in the input file. -v Validate the input file as it is being parsed. -D= Bind a top-level parameter, overriding any binding in the stylesheet. -o Specify a filename for the output. This file will be overwritten if present. Note: if you use "-" as the name of the source document, the source will instead be read from standard input. """ if sys.hexversion >= 0x2000000: sys.setrecursionlimit(MAX_PYTHON_RECURSION_DEPTH) def ParseCommandLine(argv): validate_flag = 0 out_file = None ignore_pis = 0 top_level_params = {} command_line_error = 0 trace_on_error = 0 stylesheets = [] source = "" try: optlist, args = getopt.getopt(argv[1:], 'ivD:o:', ['trace-on-error']) source = args[0] for k, v in optlist: if k == "-v": validate_flag = 1 elif k == "-i": ignore_pis = 1 elif k == "-o": out_file = v elif k == "-D": match = g_paramBindingPattern.match(v) top_level_params[match.group(1)] = match.group(2) elif k == "--trace-on-error": trace_on_error = 1 else: command_line_error = 1 if len(args) > 1: stylesheets = args[1:] except: command_line_error = 1 if command_line_error: import Ft print g_usage % (Ft.__version__, os.path.basename(argv[0])) sys.exit(1) return (validate_flag,out_file,ignore_pis,top_level_params,stylesheets,source,trace_on_error,command_line_error) def Run(argv): (validate_flag, out_file, ignore_pis, top_level_params, stylesheets, source, trace_on_error, command_line_error) = ParseCommandLine(argv) out_file = out_file and open(out_file, 'w') or sys.stdout processor = Processor() import os try: from Ft.Lib import pDomlette BETA_DOMLETTE = os.environ.get("BETA_DOMLETTE") if BETA_DOMLETTE and not validate_flag: from Ft.Lib import cDomlette g_readerClass = cDomlette.RawExpatReader reader = cDomlette.RawExpatReader() elif validate_flag: reader = pDomlette.SaxReader(validate=1) else: reader = pDomlette.PyExpatReader() except ImportError: import minisupport reader = minisupport.MinidomReader(validate_flag) try: processor.setDocumentReader(reader) for sty in stylesheets: processor.appendStylesheetUri(sty) if source == '-': result = processor.runStream(sys.stdin, ignore_pis, topLevelParams=top_level_params) else: result = processor.runUri(source, ignore_pis, topLevelParams=top_level_params) except XsltException, e: s = cStringIO.StringIO() traceback.print_exc(1000, s) sys.stderr.write(s.getvalue()) sys.stderr.write(str(e) + '\n') sys.exit(-1) except (xpath.SyntaxException, xpath.InternalException, xslt.SyntaxException, xslt.InternalException), e: s = cStringIO.StringIO() traceback.print_exc(1000, s) sys.stderr.write(s.getvalue()) if hasattr(e, 'stylesheetUri'): sys.stderr.write("While processing %s\n"%e.stylesheetUri) sys.stderr.write(str(e) + '\n') sys.exit(-1) out_file.write(result + '\n') out_file.close() if __name__ == '__main__': import sys Run(sys.argv) PyXML-0.8.2/xml/xslt/__init__.py0100644000076400001440000001412007277470665015635 0ustar martinusers######################################################################## # # File Name: __init__.py # # Documentation: http://docs.4suite.com/4XSLT/__init__.py.html # """ WWW: http://4suite.org/4XSLT e-mail: support@4suite.org Copyright (c) 2000, 2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.com/COPYRIGHT for license and copyright information """ XSL_NAMESPACE='http://www.w3.org/1999/XSL/Transform' import xml.dom from xml import xpath from xml.xpath import g_xpathRecognizedNodes SyntaxException = xpath.SyntaxException InternalException = SyntaxException # not used g_extElements = {} g_xsltRecognizedNodes = g_xpathRecognizedNodes + [xml.dom.Node.DOCUMENT_FRAGMENT_NODE] # Define ReleaseNode in a DOM-independent way import xml.dom.ext import xml.dom.minidom def _releasenode(n): if isinstance(n, xml.dom.minidom.Node): n.unlink() else: xml.dom.ext.ReleaseNode(n) try: from Ft.Lib import pDomlette def ReleaseNode(n): if isinstance(n, pDomlette.Node): pDomlette.ReleaseNode(n) else: _releasenode(n) _XsltElementBase = pDomlette.Element except ImportError: ReleaseNode = _releasenode from minisupport import _XsltElementBase def RegisterExtensionModules(moduleNames, moduleList=g_extElements): mod_names = moduleNames[:] mods = [] for mod_name in mod_names: module_used = 0 if mod_name: mod = __import__(mod_name, {}, {}, ['ExtElements', 'ExtFunctions']) if hasattr(mod, 'ExtFunctions'): xpath.g_extFunctions.update(mod.ExtFunctions) module_used = 1 if hasattr(mod, 'ExtElements'): moduleList.update(mod.ExtElements) module_used = 1 module_used and mods.append(mod) return mods class XsltException(Exception): def __init__(self, errorCode, *args): self.args = args self.errorCode = errorCode Exception.__init__(self, MessageSource.g_errorMessages[errorCode]%args) class XsltElement(_XsltElementBase): def __init__(self, doc, uri, localName, prefix, baseUri): _XsltElementBase.__init__(self, doc, uri, localName, prefix) self.baseUri = baseUri def setup(self): self._nss = xml.dom.ext.GetAllNs(self) return def instantiate(self, context, processor): for child in self.childNodes: if (child.namespaceURI, child.localName) == (XSL_NAMESPACE, 'fallback'): child.instantiate(context, processor) return (context,) def __getinitargs__(self): return (None, self.namespaceURI, self.localName, self.prefix, self.baseUri) def __getstate__(self): base_state = _XsltElementBase.__getstate__(self) new_state = (base_state, self.baseUri,) return new_state return base_state def __setstate__(self, state): _XsltElementBase.__setstate__(self, state[0]) self.baseUri = state[1] return class Error: INTERNAL_ERROR = 1 PATTERN_SYNTAX = 2 PATTERN_SEMANTIC = 3 NO_STYLESHEET = 4 AVT_SYNTAX = 5 STYLESHEET_MISSING_VERSION = 6 STYLESHEET_MISSING_VERSION_NOTE1 = 7 STYLESHEET_PARSE_ERROR = 8 SOURCE_PARSE_ERROR = 9 TOP_LEVEL_ELEM_WITH_NULL_NS = 10 XSLT_ILLEGAL_ATTR = 11 XSLT_ILLEGAL_ELEMENT = 12 STYLESHEET_ILLEGAL_ROOT = 13 CIRCULAR_VAR = 14 WHEN_AFTER_OTHERWISE = 111 MULTIPLE_OTHERWISE = 112 APPLYIMPORTS_WITH_NULL_CURR_TPL = 120 #xsl:import ILLEGAL_IMPORT = 130 #xsl:choose ILLEGAL_CHOOSE_CHILD = 140 CHOOSE_REQUIRES_WHEN_CHILD = 141 CHOOSE_WHEN_AFTER_OTHERWISE = 142 CHOOSE_MULTIPLE_OTHERWISE = 143 #xsl:call-template ILLEGAL_CALLTEMPLATE_CHILD = 150 #xsl:template ILLEGAL_TEMPLATE_PRIORITY = 160 #xsl:attribute ATTRIBUTE_ADDED_AFTER_ELEMENT = 170 ATTRIBUTE_MISSING_NAME = 171 #xsl:element UNDEFINED_ATTRIBUTE_SET = 180 #xsl:for-each INVALID_FOREACH_SELECT = 190 #xsl:value-of VALUEOF_MISSING_SELECT = 200 #xsl:copy-of COPYOF_MISSING_SELECT = 210 #xsl:text ILLEGAL_TEXT_CHILD = 220 #xsl:apply-template ILLEGAL_APPLYTEMPLATE_CHILD = 230 #xsl:when WHEN_MISSING_TEST = 240 #xsl:attribute-set ILLEGAL_ATTRIBUTESET_CHILD = 250 ATTRIBUTESET_REQUIRES_NAME = 251 INVALID_PATTERN = 1000 INVALID_OPERAND_IN_PATTERN = 1001 INVALID_OPERAND_ID = 1002 INVALID_OPERAND_SREL = 1003 INVALID_OPERAND_REL = 1004 INVALID_OPERAND_IDREL = 1005 INVALID_LEFT_OR_RIGHT_OPERAND_S = 1006 INVALID_LEFT_OR_RIGHT_OPERAND_RELP = 1007 INVALID_AXIS_SPEC = 1008 INVALID_NODE_TEST = 1009 INVALID_PREDICATE_LIST = 1010 ILLEGAL_SORT_DATA_TYPE_VALUE = 2010 ILLEGAL_SORT_CASE_ORDER_VALUE = 2011 ILLEGAL_SORT_ORDER_VALUE = 2012 ILLEGAL_NUMBER_GROUPING_SIZE_VALUE = 2020 ILLEGAL_NUMBER_LEVEL_VALUE = 2021 ILLEGAL_NUMBER_LETTER_VALUE_VALUE = 2022 ILLEGAL_NUMBER_FORMAT_VALUE = 2023 INVALID_NAMESPACE_ALIAS = 2030 WRONG_NUMBER_OF_ARGUMENTS = 5000 WRONG_ARGUMENT_TYPE = 5001 RESTRICTED_OUTPUT_VIOLATION = 7000 FEATURE_NOT_SUPPORTED = 9999 STYLESHEET_REQUESTED_TERMINATION = 10000 class OutputParameters: def __init__(self): #Initialize with defaults according to spec self.method = None self.version = "1.0" self.encoding = "" self.omitXmlDeclaration = 'no' self.standalone = None self.doctypeSystem = '' self.doctypePublic = '' self.mediaType = None self.cdataSectionElements = [] self.indent = None g_registered = 0 def Register(): import os,string from xml.xslt import XsltFunctions, BuiltInExtElements xpath.g_extFunctions.update(XsltFunctions.ExtFunctions) if os.environ.has_key('EXTMODULES'): RegisterExtensionModules( string.split(os.environ["EXTMODULES"], ':') ) g_extElements.update(BuiltInExtElements.ExtElements) global g_registered g_registered = 1 def Init(): pass Init() import MessageSource PyXML-0.8.2/xml/xslt/minisupport.py0100644000076400001440000001240107534565154016461 0ustar martinusersimport string, urllib, urllib2, StringIO, xml.sax.sax2exts, xml.sax.handler from xml.dom import minidom,pulldom, EMPTY_NAMESPACE # _XsltElementBase is used when Ft.Lib.pDomlette.Element is not available class _XsltElementBase(minidom.Element): def __init__(self, ownerDocument, namespaceURI=EMPTY_NAMESPACE, localName='', prefix=''): if prefix: tagName = prefix+':'+localName else: tagName = localName minidom.Element.__init__(self, tagName, namespaceURI, prefix, localName) self.ownerDocument = ownerDocument def __getstate__(self): return (self.childNodes, self.parentNode, self.ownerDocument, self.tagName, self.nodeName, self.prefix, self.namespaceURI, self.nodeValue, self._attrs, self._attrsNS) def __setstate__(self, st): (self.childNodes, self.parentNode, self.ownerDocument, self.tagName, self.nodeName, self.prefix, self.namespaceURI, self.nodeValue, self._attrs, self._attrsNS) = st # _ReaderBase is used in StylesheetReader if # Ft.Lib.ReaderBase.DomletteReader is not available import StringIO class _ReaderBase: def __init__(self, force8Bit = 0): self.force8Bit = force8Bit def clone(self): if hasattr(self,'__getinitargs__'): return apply(self.__class__,self.__getinitargs__()) else: return self.__class__() def initState(self, ownerDoc=None, stripElements=None): self._preserveStateStack = [1] self._stripElements = stripElements or [] if ownerDoc: self._ownerDoc = ownerDoc #Create a docfrag to hold all the generated nodes. self._rootNode = doc.createDocumentFragment() else: self._rootNode = self._ownerDoc = minidom.Document() #Set up the stack which keeps track of the nesting of DOM nodes. self._nodeStack = [self._rootNode] self._namespaces = [{'xml': XML_NAMESPACE}] self._currText = '' def fromUri(self, uri, baseUri = '', ownerDoc=None, stripElements=None): url = urllib.basejoin(baseUri, uri) stream = urllib2.urlopen(url) return self.fromStream(stream, baseUri, ownerDoc, stripElements) def fromString(self, st, baseUri='', ownerDoc=None, stripElements=None): st = StringIO.StringIO(st) return self.fromStream(st, baseUri, ownerDoc, stripElements) # g_readerClass is used in Processor if Ft.Lib.pDomlette.PyExpatReader # is not available class StrippingPullDOM(pulldom.PullDOM): def __init__(self, stripElements): pulldom.PullDOM.__init__(self) self.stripElements = stripElements or [] self.stripState = [1] self._currText = '' def startElementNS(self, name, tagName , attrs): self._completeTextNode() pulldom.PullDOM.startElementNS(self, name, tagName, attrs) new_element = self.elementStack[-1] new_pstate = self.stripState[-1] for (uri, local, strip) in self.stripElements: if (uri, local) in [(new_element.namespaceURI, new_element.localName), (EMPTY_NAMESPACE, '*'), (new_element.namespaceURI, '*')]: new_pstate = not strip break self.stripState.append(new_pstate) def endElementNS(self, name, tagName): self._completeTextNode() pulldom.PullDOM.endElementNS(self, name, tagName) del self.stripState[-1] def startElement(self, name, attrs): raise NotImplemented def endElement(self, name): raise NotImplemented def _completeTextNode(self): if self._currText and self.document: if self.stripState[-1] or string.strip(self._currText): pulldom.PullDOM.characters(self, self._currText) self._currText = '' def characters(self, data): self._currText = self._currText + data def ignorableWhitespace(self, data): self._currText = self._currText + data def processingInstruction(self, target, data): self._completeTextNode() return pulldom.PullDOM.processingInstruction(self, target, data) def comment(self, data): self._completeTextNode() return pulldom.PullDOM.comment(self, data) class StrippingStream(pulldom.DOMEventStream): def __init__(self, stream, parser, bufsize, stripElements): self.stream = stream self.parser = parser self.bufsize = bufsize self.pulldom = StrippingPullDOM(stripElements) # This content handler relies on namespace support self.parser.setFeature(xml.sax.handler.feature_namespaces, 1) self.parser.setContentHandler(self.pulldom) class MinidomReader(_ReaderBase): def __init__(self, validate = 0): self.validate = validate def fromStream(self, stream, baseUri='',ownerDoc=None, stripElements=None): if self.validate: parser = xml.sax.sax2exts.XMLValParserFactory.make_parser() else: parser = xml.sax.sax2exts.XMLParserFactory.make_parser() events = StrippingStream(stream, parser, pulldom.default_bufsize, stripElements) toktype, rootNode = events.getEvent() events.expandNode(rootNode) events.clear() return rootNode def releaseNode(self, n): n.unlink() PyXML-0.8.2/xml/FtCore.py0100644000076400001440000000100107413602560014237 0ustar martinusers""" Contains various definitions common to modules acquired from 4Suite """ class FtException(Exception): def __init__(self, errorCode, messages, args): # By defining __str__, args will be available. Otherwise # the __init__ of Exception sets it to the passed in arguments. self.params = args self.errorCode = errorCode self.message = messages[errorCode] % args Exception.__init__(self, self.message, args) def __str__(self): return self.message PyXML-0.8.2/xml/__init__.py0100644000076400001440000000207307550506776014644 0ustar martinusers"""Extended XML support for Python The full PyXML package, available from http://pyxml.sf.net, is installed. This package contains seven sub-packages: dom -- The W3C Document Object Model. This supports DOM Level 1 + Namespaces. marshal -- Converts Python objects to XML and back again. ns -- Contains namespace URIs for various standards. parsers -- Python wrappers for XML parsers. sax -- The Simple API for XML, developed by XML-Dev, led by David Megginson and ported to Python by Lars Marius Garshol. This supports the SAX 2 API. schema -- Support for XML schema languages. Currently TREX is the only supported language. utils -- Various small utility modules. xpath -- XPath parsing and evaluation. Implemented by Fourthought, Inc. """ # xml.unicode is not listed because it is for internal use and backwards # compatibility only. __all__ = ['dom', 'marshal', 'parsers', 'sax', 'schema', 'utils', 'xpath', 'xslt'] # Needs to synchronize with setup.py # Never drop digits from the end. version_info = (0,8,2) __version__ = "0.8.2" PyXML-0.8.2/xml/ns.py0100644000076400001440000001703207461630226013513 0ustar martinusers"""NS module -- XML Namespace constants This module contains the definitions of namespaces (and sometimes other URI's) used by a variety of XML standards. Each class has a short all-uppercase name, which should follow any (emerging) convention for how that standard is commonly used. For example, ds is almost always used as the namespace prefixes for items in XML Signature, so DS is the class name. Attributes within that class, all uppercase, define symbolic names (hopefully evocative) for "constants" used in that standard. """ class XMLNS: """XMLNS, Namespaces in XML XMLNS (14-Jan-1999) is a W3C Recommendation. It is specified in http://www.w3.org/TR/REC-xml-names BASE -- the basic namespace defined by the specification XML -- the namespace for XML 1.0 HTML -- the namespace for HTML4.0 """ BASE = "http://www.w3.org/2000/xmlns/" XML = "http://www.w3.org/XML/1998/namespace" HTML = "http://www.w3.org/TR/REC-html40" class XLINK: """XLINK, XML Linking Language XLink (v1.0, 27-Jun-2001) is a W3C Recommendation. It is specified in http://www.w3.org/TR/xlink/ """ BASE = "http://www.w3.org/1999/xlink" class SOAP: """SOAP, the Simple Object Access Protocol SOAP (v1.1, 8-May-2000) is a W3C note. It is specified in http://www.w3.org/TR/SOAP ENV -- namespace for the SOAP envelope ENC -- namespace for the SOAP encoding in section 5 ACTOR_NEXT -- the URI for the "next" actor (Note that no BASE is defined.) """ ENV = "http://schemas.xmlsoap.org/soap/envelope/" ENC = "http://schemas.xmlsoap.org/soap/encoding/" ACTOR_NEXT = "http://schemas.xmlsoap.org/soap/actor/next" class DSIG: """DSIG, XML-Signature Syntax and Processing DSIG (19-Apr-2001) is a W3C Candidate Recommendation. It is specified in http://www.w3.org/TR/xmldsig-core/ BASE -- the basic namespace defined by the specification DIGEST_SHA1 -- The SHA-1 digest method DIGEST_MD2 -- The MD2 digest method DIGEST_MD5 -- The MD5 digest method SIG_DSA_SHA1 -- The DSA/DHA-1 signature method SIG_RSA_SHA1 -- The RSA/DHA-1 signature method HMAC_SHA1 -- The SHA-1 HMAC method ENC_BASE64 -- The Base64 encoding method ENVELOPED -- an enveloped XML signature C14N -- XML canonicalization C14N_COMM -- XML canonicalization, retaining comments C14N_EXCL -- XML exclusive canonicalization XPATH -- The identifier for an XPATH transform XSLT -- The identifier for an XSLT transform """ BASE = "http://www.w3.org/2000/09/xmldsig#" DIGEST_SHA1 = BASE + "sha1" DIGEST_MD2 = BASE + "md2" DIGEST_MD5 = BASE + "md5" SIG_DSA_SHA1= BASE + "dsa-sha1" SIG_RSA_SHA1= BASE + "rsa-sha1" HMAC_SHA1 = BASE + "hmac-sha1" ENC_BASE64 = BASE + "base64" ENVELOPED = BASE + "enveloped-signature" C14N = "http://www.w3.org/TR/2000/CR-xml-c14n-20010315" C14N_COMM = C14N + "#WithComments" C14N_EXCL = "http://www.w3.org/2001/10/xml-exc-c14n#" XPATH = "http://www.w3.org/TR/1999/REC-xpath-19991116" XSLT = "http://www.w3.org/TR/1999/REC-xslt-19991116" class ENCRYPTION: """ENCRYPTION, XML-Encryption Syntax and Processing ENCRYPTION (26-Jun-2001) is a W3C Working Draft. It is specified in http://www.w3.org/TR/xmlenc-core/ BASE -- the basic namespace defined by the specification BLOCK_3DES -- The triple-DES symmetric encryption method BLOCK_AES128 -- The 128-bit AES symmetric encryption method BLOCK_AES256 -- The 256-bit AES symmetric encryption method BLOCK_AES192 -- The 192-bit AES symmetric encryption method STREAM_ARCFOUR -- The ARCFOUR symmetric encryption method KT_RSA_1_5 -- The RSA v1.5 key transport method KT_RSA_OAEP -- The RSA OAEP key transport method KA_DH -- The Diffie-Hellman key agreement method WRAP_3DES -- The triple-DES symmetric key wrap method WRAP_AES128 -- The 128-bit AES symmetric key wrap method WRAP_AES256 -- The 256-bit AES symmetric key wrap method WRAP_AES192 -- The 192-bit AES symmetric key wrap method DIGEST_SHA256 -- The SHA-256 digest method DIGEST_SHA512 -- The SHA-512 digest method DIGEST_RIPEMD160 -- The RIPEMD-160 digest method """ BASE = "http://www.w3.org/2001/04/xmlenc#" BLOCK_3DES = BASE + "des-cbc" BLOCK_AES128 = BASE + "aes128-cbc" BLOCK_AES256 = BASE + "aes256-cbc" BLOCK_AES192 = BASE + "aes192-cbc" STREAM_ARCFOUR = BASE + "arcfour" KT_RSA_1_5 = BASE + "rsa-1_5" KT_RSA_OAEP = BASE + "rsa-oaep-mgf1p" KA_DH = BASE + "dh" WRAP_3DES = BASE + "kw-3des" WRAP_AES128 = BASE + "kw-aes128" WRAP_AES256 = BASE + "kw-aes256" WRAP_AES192 = BASE + "kw-aes192" DIGEST_SHA256 = BASE + "sha256" DIGEST_SHA512 = BASE + "sha512" DIGEST_RIPEMD160 = BASE + "ripemd160" class SCHEMA: """SCHEMA, XML Schema XML Schema (30-Mar-2001) is a W3C candidate recommendation. It is specified in http://www.w3.org/TR/xmlschema-1 (Structures) and http://www.w3.org/TR/xmlschema-2 (Datatypes). Schema has been under development for a comparitively long time, and other standards have at times used earlier drafts. This class defines the most-used, and sets BASE to the latest. BASE -- the basic namespace (2001) XSD1, XSI1 -- schema and schema-instance for 1999 XSD2, XSI2 -- schema and schema-instance for October 2000 XSD3, XSI3 -- schema and schema-instance for 2001 XSD_LIST -- a sequence of the XSDn values XSI_LIST -- a sequence of the XSIn values """ XSD1 = "http://www.w3.org/1999/XMLSchema" XSD2 = "http://www.w3.org/2000/10/XMLSchema" XSD3 = "http://www.w3.org/2001/XMLSchema" XSD_LIST = [ XSD1, XSD2, XSD3 ] XSI1 = "http://www.w3.org/1999/XMLSchema-instance" XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance" XSI3 = "http://www.w3.org/2001/XMLSchema-instance" XSI_LIST = [ XSI1, XSI2, XSI3 ] BASE = XSD3 class XSLT: """XSLT, XSL Transformations XSLT (16-Nov-1999) is a W3C Recommendation. It is specified in http://www.w3.org/TR/xslt/ BASE -- the basic namespace defined by this specification """ BASE = "http://www.w3.org/1999/XSL/Transform" class XPATH: """XPATH, XML Path Language XPATH (16-Nov-1999) is a W3C Recommendation. It is specified in http://www.w3.org/TR/xpath. This class is currently empty. """ pass class WSDL: """WSDL, Web Services Description Language WSDL (V1.1, 15-Mar-2001) is a W3C Note. It is specified in http://www.w3.org/TR/wsdl BASE -- the basic namespace defined by this specification BIND_SOAP -- SOAP binding for WSDL BIND_HTTP -- HTTP GET and POST binding for WSDL BIND_MIME -- MIME binding for WSDL """ BASE = "http://schemas.xmlsoap.org/wsdl/" BIND_SOAP = BASE + "soap/" BIND_HTTP = BASE + "http/" BIND_MIME = BASE + "mime/" class RNG: """RELAX NG, schema language for XML RELAX NG (03-Dec-2001) is a simple schema languge for XML, published under the auspices of OASIS. The specification, tutorial, and other information are available from http://www.relaxng.org. """ BASE = "http://relaxng.org/ns/structure/1.0" PyXML-0.8.2/ANNOUNCE0100644000076400001440000000435207614725672013065 0ustar martinusersTo be sent to: c.l.py.announce, xml-dev, www-dom, comp.text.xml, freshmeat.net, other suggestions? ================== Version 0.8.2 of the Python/XML distribution is now available. It should be considered a beta release, and can be downloaded from the following URLs: http://prdownloads.sourceforge.net/pyxml/PyXML-0.8.2.tar.gz http://prdownloads.sourceforge.net/pyxml/PyXML-0.8.2.win32-py2.2.exe http://prdownloads.sourceforge.net/pyxml/PyXML-0.8.2-2.2.Suse81.i386.rpm Changes in this version, compared to 0.8.1: * Updated to Expat 1.95.6. * Support more DOM L3 features in minidom: isWhitespaceInElementContent, schemaType, isId, DOMImplementationSource * Various bug fixes, including - 609641: minidom nodes not pickleable - 618156: Use character references in XMLGenerator if necessary - 622286: marshal.wddx: 'recordset' element typo - 624420: Can't create 2nd Sax2.Reader - 665486: Implement SAX skippedEntity for Expat The Python/XML distribution contains the basic tools required for processing XML data using the Python programming language, assembled into one easy-to-install package. The distribution includes parsers and standard interfaces such as SAX and DOM, along with various other useful modules. The package currently contains: * XML parsers: Pyexpat (Jack Jansen), xmlproc (Lars Marius Garshol), sgmlop (Fredrik Lundh). * SAX interface (Lars Marius Garshol) * minidom DOM implementation (Paul Prescod, others) * 4DOM and 4XPath from Fourthought (Uche Ogbuji, Mike Olson) * Schema implementations: TREX (James Tauber) * Various utility modules and functions (various people) * Documentation and example programs (various people) The code is being developed bazaar-style by contributors from the Python XML Special Interest Group, so please send comments and questions to . Bug reports may be filed on SourceForge: http://sourceforge.net/tracker/index.php?group_id=6473&atid=106473 For more information about Python and XML, see: http://www.python.org/topics/xml/ -- Martin v. Lwis http://www.informatik.hu-berlin.de/~loewis PyXML-0.8.2/CREDITS0100644000076400001440000001051507614471161012741 0ustar martinusers Evgeny Cherkashin eugeneai@icc.ru Expose Python codecs to pyexpat James Clark Expat parser Fred L. Drake, Jr. fdrake@acm.org http://python.starship.net/~fdrake/ XBEL maintainer Expat maintainer General minidom maintenance pyexpat maintenance Karl Waclawek Expat maintainer Stefane Fermigier First version of the DOM code. Lars Marius Garshol saxlib SAX implementation xmlproc XML parser Geir Ove Grnmo xmlarch architectural forms code Jack Jansen PyExpat extension module Jeff Johnson xml.dom.utils.FileReader class Lots of DOM bug reports Jeremy Kloth 4DOM, and various other things. A.M. Kuchling akuchlin@mems-exchange.org http://www.amk.ca Packaging XML HOWTO XML topic guide (http://pyxml.sourceforge.net/topics/) CNRI, 1895 Preston White Drive, Suite 100, Reston VA, 20191 1024D/8BBD77F0 8A1A 67CB B3E5 3972 06DE 3D3B 913B DC5E 8BBD 77F0 Martin von Lwis Original unicode wide-string module Synchronization of Python 2 and PyXML Fredrik Lundh sgmlop extension module Modified version of xmllib.py for use with sgmlop Sjoerd Mullender xmllib.py XML parser Sean McGrath Uche Ogbuji 4DOM, and various other things. Mike Olson 4DOM, and various other things. Paul Prescod minidom Guido van Rossum Benevolent dictator Convincing AMK about the __cmp__ method for DOM nodes Greg Stein xml.utils.qp_xml module Admin the XML-SIG CVS repository http://www.lyra.org/cgi-bin/viewcvs.cgi/xml/ gstein@lyra.org http://www.lyra.org/greg/ PO Box 760, Palo Alto, CA, 94302 James Tauber jtauber@bowstreet.com PyTREX Robin Thomas Strict and loose marshalling for WDDX. Various fixes to the xml.marshal.generic module. Christian Tismer Stephan Tolksdorf Add various minidom features PyXML-0.8.2/LICENCE0100644000076400001440000003657107410602340012705 0ustar martinusersThis file collects the licences for the various pieces of software included in this package, sorted by the package name in alphabetical order. Minor items (typically single-file contributions) appear at the end. 4DOM: Copyright (c) 2000 Fourthought Inc, USA All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of FourThought LLC not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. FOURTHOUGHT LLC DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL FOURTHOUGHT BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. PyExpat, SAX libraries: -------------------------------------------------------------------- BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 ----------------------------------------------------- 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software"). 2. Subject to the terms and conditions of this BeOpen Python License Agreement, BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use the Software alone or in any derivative version, provided, however, that the BeOpen Python License is retained in the Software, alone or in any derivative version prepared by Licensee. 3. BeOpen is making the Software available to Licensee on an "AS IS" basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 5. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 6. This License Agreement shall be governed by and interpreted in all respects by the law of the State of California, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between BeOpen and Licensee. This License Agreement does not grant permission to use BeOpen trademarks or trade names in a trademark sense to endorse or promote products or services of Licensee, or any third party. As an exception, the "BeOpen Python" logos available at http://www.pythonlabs.com/logos.html may be used according to the permissions granted on that web page. 7. By copying, installing or otherwise using the software, Licensee agrees to be bound by the terms and conditions of this License Agreement. CNRI OPEN SOURCE LICENSE AGREEMENT ---------------------------------- Python 1.6 CNRI OPEN SOURCE LICENSE AGREEMENT IMPORTANT: PLEASE READ THE FOLLOWING AGREEMENT CAREFULLY. BY CLICKING ON "ACCEPT" WHERE INDICATED BELOW, OR BY COPYING, INSTALLING OR OTHERWISE USING PYTHON 1.6 SOFTWARE, YOU ARE DEEMED TO HAVE AGREED TO THE TERMS AND CONDITIONS OF THIS LICENSE AGREEMENT. 1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6 software in source or binary form and its associated documentation, as released at the www.python.org Internet site on September 5, 2025 ("Python 1.6"). 2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2000 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1012. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1012". 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6. 4. CNRI is making Python 1.6 available to Licensee on an "AS IS" basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. This License Agreement shall be governed by and interpreted in all respects by the law of the State of Virginia, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between CNRI and Licensee. This License Agreement does not grant permission to use CNRI trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6, Licensee agrees to be bound by the terms and conditions of this License Agreement. ACCEPT CWI PERMISSIONS STATEMENT AND DISCLAIMER ---------------------------------------- Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- qp_xml: -------------------------------------------------------------------- Written by Greg Stein. Public Domain. No Copyright, no Rights Reserved, and no Warranties. -------------------------------------------------------------------- sgmlop.c: -------------------------------------------------------------------- Copyright (c) 1998 by Secret Labs AB. Permission to use, copy, modify, and distribute this software and its associated documentation for any purpose and without fee is hereby granted. This software is provided as is. -------------------------------------------------------------------- xmlproc: xmlproc is free and you can do as you like with it. If you change it, please let the author, Lars Marius Garshol, know about it. -------------------------------------------------------------------- setupext/install_data.py: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- schema/trex.py Copyright (c) 2001, James Tauber All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The name "James Tauber" may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. test/domapi/ (and test/test_pyxmldom.py) -------------------------------------------------------------------- Zope Public License (ZPL) Version 1.0 ------------------------------------- Copyright (c) Digital Creations. All rights reserved. This license has been certified as Open Source(tm). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Digital Creations requests that attribution be given to Zope in any manner possible. Zope includes a "Powered by Zope" button that is installed by default. While it is not a license violation to remove this button, it is requested that the attribution remain. A significant investment has been put into Zope, and this effort will continue if the Zope community continues to grow. This is one way to assure that growth. 4. All advertising materials and documentation mentioning features derived from or use of this software must display the following acknowledgement: "This product includes software developed by Digital Creations for use in the Z Object Publishing Environment (http://www.zope.org/)." In the event that the product being advertised includes an intact Zope distribution (with copyright and license included) then this clause is waived. 5. Names associated with Zope or Digital Creations must not be used to endorse or promote products derived from this software without prior written permission from Digital Creations. 6. Modified redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by Digital Creations for use in the Z Object Publishing Environment (http://www.zope.org/)." Intact (re-)distributions of any official Zope release do not require an external acknowledgement. 7. Modifications are encouraged but must be packaged separately as patches to official Zope releases. Distributions that do not clearly separate the patches from the original work must be clearly labeled as unofficial distributions. Modifications which do not carry the name Zope may be packaged in any form, as long as they conform to all of the clauses above. Disclaimer THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of contributions made by Digital Creations and many individuals on behalf of Digital Creations. Specific attributions are listed in the accompanying credits file. -------------------------------------------------------------------- Others: xml/dom/ext/c14n.py is distributed under the terms of the Python 2.0 copyright, or later. PyXML-0.8.2/MANIFEST0100644000076400001440000003414507614726123013060 0ustar martinusersANNOUNCE CREDITS LICENCE MANIFEST MANIFEST.in README README.dom README.pyexpat README.sgmlop TODO setup.cfg setup.py demo/README demo/dom/4tidy.py demo/dom/README demo/dom/__init__.py demo/dom/addr_book.dtd demo/dom/addr_book1.xml demo/dom/addr_book2.xml demo/dom/benchmark.py demo/dom/book_catalog1.xml demo/dom/building.py demo/dom/dom_from_html_file.py demo/dom/dom_from_xml_file.py demo/dom/domconv.py demo/dom/employee_table.html demo/dom/generate_html1.py demo/dom/generate_xml1.py demo/dom/html2html demo/dom/iterator1.py demo/dom/link_title_invert.py demo/dom/trace_ns.py demo/dom/visitor1.py demo/dom/xll_replace.py demo/dom/xpointer_query.py demo/dom/xptr.py demo/genxml/README demo/genxml/data.txt demo/genxml/loaddata.py demo/quotes/README demo/quotes/qtfmt.py demo/quotes/quotations.dtd demo/quotes/sample.xml demo/sax/README demo/sax/sax2obj.py demo/sax/saxdemo.py demo/sax/saxhack.py demo/sax/saxstats.py demo/sax/saxtimer.py demo/sax/saxtrace.py demo/sgmlop/benchsgml.py demo/sgmlop/benchxml.py demo/sgmlop/test2.htm demo/sgmlop/testxml1.py demo/sgmlop/testxml2.py demo/xbel/README demo/xbel/adr_parse.py demo/xbel/bookmark.py demo/xbel/lynx_parse.py demo/xbel/msie_parse.py demo/xbel/ns_parse.py demo/xbel/xbel-1.0.dtd demo/xbel/xbel-1.1.dtd demo/xbel/xbel2html.py demo/xbel/xbel_parse.py demo/xbel/doc/xbel.bib demo/xbel/doc/xbel.tex demo/xmlproc/catalog.soc demo/xmlproc/doctree.py demo/xmlproc/dtd2schema.py demo/xmlproc/dtdcheck.py demo/xmlproc/dtdcmd.py demo/xmlproc/dtddoc.py demo/xmlproc/nstest1.xml demo/xmlproc/outputters.py demo/xmlproc/urls.xml demo/xmlproc/wxValidator.py demo/xmlproc/xbel2html.py demo/xmlproc/xpcmd.py demo/xmlproc/xvcmd.py demo/xmlproc/dtds/xbel-1.0.dtd demo/xmlproc/dtds/xsa.dtd doc/xml-howto.tex doc/xml-howto.txt doc/xml-ref.tex doc/xml-ref.txt doc/4DOM/4DOM.web doc/4DOM/Extensions.api doc/4DOM/Extensions.html doc/4DOM/Ranges.api doc/4DOM/Ranges.html doc/4DOM/index.html doc/xmlproc/artikler.css doc/xmlproc/basicapi.gif doc/xmlproc/cmdline.gif doc/xmlproc/standard.css doc/xmlproc/wxval.gif doc/xmlproc/xmlproc-catalog-doco.html doc/xmlproc/xmlproc-doco.html doc/xmlproc/xmlproc-dtd-doco.html doc/xmlproc/xmlproc-license.html doc/xmlproc/xmlproc.html doc/xmlproc/xmlproc_cmdline.html doc/xmlproc/xmlproc_dtdparser.html doc/xmlproc/xmlproc_ns.html doc/xmlproc/xmlproc_tut.html extensions/boolean.c extensions/pyexpat.c extensions/sgmlop.c extensions/expat/lib/ascii.h extensions/expat/lib/asciitab.h extensions/expat/lib/expat.h extensions/expat/lib/expat.h.in extensions/expat/lib/iasciitab.h extensions/expat/lib/internal.h extensions/expat/lib/latin1tab.h extensions/expat/lib/macconfig.h extensions/expat/lib/nametab.h extensions/expat/lib/utf8tab.h extensions/expat/lib/winconfig.h extensions/expat/lib/xmlparse.c extensions/expat/lib/xmlrole.c extensions/expat/lib/xmlrole.h extensions/expat/lib/xmltok.c extensions/expat/lib/xmltok.h extensions/expat/lib/xmltok_impl.c extensions/expat/lib/xmltok_impl.h extensions/expat/lib/xmltok_ns.c mac/pyexpat.prj mac/pyexpat.prj.exp scripts/xmlproc_parse scripts/xmlproc_val setupext/__init__.py setupext/install_data.py test/chkdom_4dom.py test/chkdom_minidom.py test/enc_test.xml test/perf_expatbuilder.py test/quotes.xml test/regrtest.py test/test.xml test/test.xml.out test/test_c14n.py test/test_dom.py test/test_domreg.py test/test_encodings.py test/test_filter.py test/test_howto.py test/test_htmlb.py test/test_javadom.py test/test_marshal.py test/test_minidom.py test/test_pyexpat.py test/test_sax.py test/test_sax2.py test/test_sax2_xmlproc.py test/test_sax_xmlproc.py test/test_saxdrivers.py test/test_support.py test/test_utils.py test/test_xmlbuilder.py test/test_xmlproc.py test/testxml.py test/unittest.py test/xmlval_illformed.dtd test/dom/TestSuite.py test/dom/newtest_node.py test/dom/test.py test/dom/test_attr.py test/dom/test_cdatasection.py test/dom/test_characterdata.py test/dom/test_comment.py test/dom/test_demo.py test/dom/test_document.py test/dom/test_documentfragment.py test/dom/test_documenttype.py test/dom/test_domimplementation.py test/dom/test_element.py test/dom/test_entity.py test/dom/test_entityreference.py test/dom/test_html.py test/dom/test_namednodemap.py test/dom/test_node.py test/dom/test_nodeiterator.py test/dom/test_nodelist.py test/dom/test_notation.py test/dom/test_processinginstruction.py test/dom/test_pythonic.py test/dom/test_range.py test/dom/test_readers.py test/dom/test_struct.py test/dom/test_text.py test/dom/test_treewalker.py test/dom/borrowed/TestSuite.py test/dom/borrowed/af_20000919.py test/dom/borrowed/af_20000922.py test/dom/borrowed/nc_20000921.py test/dom/borrowed/uo_20010713.py test/dom/ext/TestSuite.py test/dom/ext/bigTest.html test/dom/ext/mulit-single.html test/dom/ext/single.html test/dom/ext/test_html_builder.py test/dom/ext/test_memory.py test/dom/ext/test_nss_print.py test/dom/ext/test_single_elements.py test/dom/ext/test_xhtml_printer.py test/dom/html/test.py test/dom/html/test_a.py test/dom/html/test_applet.py test/dom/html/test_area.py test/dom/html/test_base.py test/dom/html/test_basefont.py test/dom/html/test_blockquote.py test/dom/html/test_body.py test/dom/html/test_br.py test/dom/html/test_button.py test/dom/html/test_caption.py test/dom/html/test_col.py test/dom/html/test_collection.py test/dom/html/test_dir.py test/dom/html/test_div.py test/dom/html/test_dl.py test/dom/html/test_document.py test/dom/html/test_element.py test/dom/html/test_fieldset.py test/dom/html/test_font.py test/dom/html/test_form.py test/dom/html/test_frame.py test/dom/html/test_frameset.py test/dom/html/test_h.py test/dom/html/test_head.py test/dom/html/test_hr.py test/dom/html/test_html.py test/dom/html/test_html_dom_implementation.py test/dom/html/test_iframe.py test/dom/html/test_img.py test/dom/html/test_input.py test/dom/html/test_isindex.py test/dom/html/test_label.py test/dom/html/test_legend.py test/dom/html/test_li.py test/dom/html/test_link.py test/dom/html/test_map.py test/dom/html/test_menu.py test/dom/html/test_meta.py test/dom/html/test_mod.py test/dom/html/test_object.py test/dom/html/test_ol.py test/dom/html/test_optgroup.py test/dom/html/test_option.py test/dom/html/test_p.py test/dom/html/test_param.py test/dom/html/test_pre.py test/dom/html/test_q.py test/dom/html/test_script.py test/dom/html/test_section.py test/dom/html/test_select.py test/dom/html/test_style.py test/dom/html/test_table.py test/dom/html/test_td.py test/dom/html/test_textarea.py test/dom/html/test_title.py test/dom/html/test_tr.py test/dom/html/test_ul.py test/dom/html/util.py test/domapi/Base.py test/domapi/CoreLvl1.py test/domapi/CoreLvl2.py test/domapi/CoreLvl3.py test/domapi/Load3.py test/domapi/TraversalLvl2.py test/domapi/XMLLvl1.py test/domapi/XMLLvl2.py test/domapi/__init__.py test/output/test_c14n test/output/test_dom test/output/test_domreg test/output/test_encodings test/output/test_filter test/output/test_howto test/output/test_htmlb test/output/test_javadom test/output/test_marshal test/output/test_marshal.orig test/output/test_marshal.rej test/output/test_minidom test/output/test_parsers test/output/test_pyexpat test/output/test_sax test/output/test_sax2 test/output/test_sax2_xmlproc test/output/test_sax_xmlproc test/output/test_saxdrivers test/output/test_utils test/output/test_xmlbuilder test/output/test_xmlproc xml/FtCore.py xml/__init__.py xml/ns.py xml/dom/Attr.py xml/dom/CDATASection.py xml/dom/COPYRIGHT xml/dom/ChangeLog xml/dom/CharacterData.py xml/dom/Comment.py xml/dom/DOMImplementation.py xml/dom/Document.py xml/dom/DocumentFragment.py xml/dom/DocumentType.py xml/dom/Element.py xml/dom/Entity.py xml/dom/EntityReference.py xml/dom/Event.py xml/dom/FtNode.py xml/dom/MessageSource.py xml/dom/NamedNodeMap.py xml/dom/NodeFilter.py xml/dom/NodeIterator.py xml/dom/NodeList.py xml/dom/Notation.py xml/dom/ProcessingInstruction.py xml/dom/README xml/dom/Range.py xml/dom/TODO xml/dom/Text.py xml/dom/TreeWalker.py xml/dom/__init__.py xml/dom/de.po xml/dom/domreg.py xml/dom/en_US.po xml/dom/expatbuilder.py xml/dom/fr_FR.po xml/dom/javadom.py xml/dom/minicompat.py xml/dom/minidom.py xml/dom/minitraversal.py xml/dom/pulldom.py xml/dom/xmlbuilder.py xml/dom/de/LC_MESSAGES/4Suite.mo xml/dom/en_US/LC_MESSAGES/4Suite.mo xml/dom/ext/Dom2Sax.py xml/dom/ext/Printer.py xml/dom/ext/Visitor.py xml/dom/ext/XHtml2HtmlPrinter.py xml/dom/ext/XHtmlPrinter.py xml/dom/ext/__init__.py xml/dom/ext/c14n.py xml/dom/ext/reader/HtmlLib.py xml/dom/ext/reader/HtmlSax.py xml/dom/ext/reader/PyExpat.py xml/dom/ext/reader/Sax.py xml/dom/ext/reader/Sax2.py xml/dom/ext/reader/Sax2Lib.py xml/dom/ext/reader/Sgmlop.py xml/dom/ext/reader/__init__.py xml/dom/ext/reader/test_suite/Benchmark.py xml/dom/fr_FR/LC_MESSAGES/4Suite.mo xml/dom/html/GenerateHtml.py xml/dom/html/HTMLAnchorElement.py xml/dom/html/HTMLAppletElement.py xml/dom/html/HTMLAreaElement.py xml/dom/html/HTMLBRElement.py xml/dom/html/HTMLBaseElement.py xml/dom/html/HTMLBaseFontElement.py xml/dom/html/HTMLBodyElement.py xml/dom/html/HTMLButtonElement.py xml/dom/html/HTMLCollection.py xml/dom/html/HTMLDListElement.py xml/dom/html/HTMLDOMImplementation.py xml/dom/html/HTMLDirectoryElement.py xml/dom/html/HTMLDivElement.py xml/dom/html/HTMLDocument.py xml/dom/html/HTMLElement.py xml/dom/html/HTMLFieldSetElement.py xml/dom/html/HTMLFontElement.py xml/dom/html/HTMLFormElement.py xml/dom/html/HTMLFrameElement.py xml/dom/html/HTMLFrameSetElement.py xml/dom/html/HTMLHRElement.py xml/dom/html/HTMLHeadElement.py xml/dom/html/HTMLHeadingElement.py xml/dom/html/HTMLHtmlElement.py xml/dom/html/HTMLIFrameElement.py xml/dom/html/HTMLImageElement.py xml/dom/html/HTMLInputElement.py xml/dom/html/HTMLIsIndexElement.py xml/dom/html/HTMLLIElement.py xml/dom/html/HTMLLabelElement.py xml/dom/html/HTMLLegendElement.py xml/dom/html/HTMLLinkElement.py xml/dom/html/HTMLMapElement.py xml/dom/html/HTMLMenuElement.py xml/dom/html/HTMLMetaElement.py xml/dom/html/HTMLModElement.py xml/dom/html/HTMLOListElement.py xml/dom/html/HTMLObjectElement.py xml/dom/html/HTMLOptGroupElement.py xml/dom/html/HTMLOptionElement.py xml/dom/html/HTMLParagraphElement.py xml/dom/html/HTMLParamElement.py xml/dom/html/HTMLPreElement.py xml/dom/html/HTMLQuoteElement.py xml/dom/html/HTMLScriptElement.py xml/dom/html/HTMLSelectElement.py xml/dom/html/HTMLStyleElement.py xml/dom/html/HTMLTableCaptionElement.py xml/dom/html/HTMLTableCellElement.py xml/dom/html/HTMLTableColElement.py xml/dom/html/HTMLTableElement.py xml/dom/html/HTMLTableRowElement.py xml/dom/html/HTMLTableSectionElement.py xml/dom/html/HTMLTextAreaElement.py xml/dom/html/HTMLTitleElement.py xml/dom/html/HTMLUListElement.py xml/dom/html/__init__.py xml/dom/html/html_classes.xml xml/marshal/__init__.py xml/marshal/generic.py xml/marshal/wddx.py xml/parsers/__init__.py xml/parsers/expat.py xml/parsers/sgmllib.py xml/parsers/xmlproc/__init__.py xml/parsers/xmlproc/_outputters.py xml/parsers/xmlproc/catalog.py xml/parsers/xmlproc/charconv.py xml/parsers/xmlproc/dtdparser.py xml/parsers/xmlproc/errors.py xml/parsers/xmlproc/namespace.py xml/parsers/xmlproc/utils.py xml/parsers/xmlproc/xcatalog.py xml/parsers/xmlproc/xmlapp.py xml/parsers/xmlproc/xmldtd.py xml/parsers/xmlproc/xmlproc.py xml/parsers/xmlproc/xmlutils.py xml/parsers/xmlproc/xmlval.py xml/sax/__init__.py xml/sax/_exceptions.py xml/sax/expatreader.py xml/sax/handler.py xml/sax/sax2exts.py xml/sax/saxexts.py xml/sax/saxlib.py xml/sax/saxutils.py xml/sax/writer.py xml/sax/xmlreader.py xml/sax/drivers/__init__.py xml/sax/drivers/drv_htmllib.py xml/sax/drivers/drv_ltdriver.py xml/sax/drivers/drv_ltdriver_val.py xml/sax/drivers/drv_pyexpat.py xml/sax/drivers/drv_sgmllib.py xml/sax/drivers/drv_sgmlop.py xml/sax/drivers/drv_xmldc.py xml/sax/drivers/drv_xmllib.py xml/sax/drivers/drv_xmlproc.py xml/sax/drivers/drv_xmlproc_val.py xml/sax/drivers/drv_xmltoolkit.py xml/sax/drivers/pylibs.py xml/sax/drivers2/__init__.py xml/sax/drivers2/drv_htmllib.py xml/sax/drivers2/drv_javasax.py xml/sax/drivers2/drv_pyexpat.py xml/sax/drivers2/drv_sgmllib.py xml/sax/drivers2/drv_sgmlop.py xml/sax/drivers2/drv_sgmlop_html.py xml/sax/drivers2/drv_xmlproc.py xml/schema/__init__.py xml/schema/trex.py xml/unicode/__init__.py xml/unicode/iso8859.py xml/unicode/utf8_iso.py xml/utils/__init__.py xml/utils/characters.py xml/utils/iso8601.py xml/utils/qp_xml.py xml/xpath/BuiltInExtFunctions.py xml/xpath/Context.py xml/xpath/Conversions.py xml/xpath/CoreFunctions.py xml/xpath/ExpandedNameWrapper.py xml/xpath/MessageSource.py xml/xpath/NamespaceNode.py xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py xml/xpath/ParsedAbbreviatedRelativeLocationPath.py xml/xpath/ParsedAbsoluteLocationPath.py xml/xpath/ParsedAxisSpecifier.py xml/xpath/ParsedExpr.py xml/xpath/ParsedNodeTest.py xml/xpath/ParsedPredicateList.py xml/xpath/ParsedRelativeLocationPath.py xml/xpath/ParsedStep.py xml/xpath/Set.py xml/xpath/Util.py xml/xpath/XPathGrammar.py xml/xpath/XPathParser.py xml/xpath/XPathParserBase.py xml/xpath/__init__.py xml/xpath/pyxpath.py xml/xpath/yappsrt.py xml/xslt/ApplyTemplatesElement.py xml/xslt/AttributeElement.py xml/xslt/AttributeSetElement.py xml/xslt/AttributeValueTemplate.py xml/xslt/BuiltInExtElements.py xml/xslt/CallTemplateElement.py xml/xslt/ChooseElement.py xml/xslt/CommentElement.py xml/xslt/CopyElement.py xml/xslt/CopyOfElement.py xml/xslt/ElementElement.py xml/xslt/ForEachElement.py xml/xslt/HtmlWriter.py xml/xslt/IfElement.py xml/xslt/LiteralElement.py xml/xslt/LiteralText.py xml/xslt/MessageElement.py xml/xslt/MessageSource.py xml/xslt/NullWriter.py xml/xslt/NumberElement.py xml/xslt/OtherXslElement.py xml/xslt/OtherwiseElement.py xml/xslt/OutputHandler.py xml/xslt/ParamElement.py xml/xslt/ParsedLocationPathPattern.py xml/xslt/ParsedPattern.py xml/xslt/ParsedRelativePathPattern.py xml/xslt/ParsedStepPattern.py xml/xslt/PlainTextWriter.py xml/xslt/ProcessingInstructionElement.py xml/xslt/Processor.py xml/xslt/Roman.py xml/xslt/RtfWriter.py xml/xslt/SortElement.py xml/xslt/Stylesheet.py xml/xslt/StylesheetReader.py xml/xslt/TemplateElement.py xml/xslt/TextElement.py xml/xslt/TextSax.py xml/xslt/TextWriter.py xml/xslt/ValueOfElement.py xml/xslt/VariableElement.py xml/xslt/WhenElement.py xml/xslt/WithParamElement.py xml/xslt/XPattern.py xml/xslt/XPatternParser.py xml/xslt/XPatternParserBase.py xml/xslt/XmlWriter.py xml/xslt/XsltContext.py xml/xslt/XsltFunctions.py xml/xslt/_4xslt.py xml/xslt/__init__.py xml/xslt/minisupport.py PyXML-0.8.2/MANIFEST.in0100644000076400001440000000164407611541417013461 0ustar martinusersinclude ANNOUNCE CREDITS LICENCE MANIFEST MANIFEST.in README* TODO include setup.py recursive-include xml *.py *.po *.mo recursive-include mac *.prj *.prj.exp recursive-include doc *.html *.tex *.txt *.gif *.css *.api *.web recursive-include doc/man *.1 recursive-include extensions *.c *.h recursive-include extensions/expat *.html *Makefile expat.* *.dsp recursive-include test *.py *.xml *.html *.dtd include test/test.xml.out recursive-include test/output test_* recursive-include demo README *.py *.xml *.dtd *.html *.htm include demo/genxml/data.txt include demo/dom/html2html include demo/xbel/doc/xbel.bib include demo/xbel/doc/xbel.tex include demo/xmlproc/catalog.soc include xml/dom/COPYRIGHT include xml/dom/ChangeLog include xml/dom/README include xml/dom/TODO include xml/dom/html/html_classes.xml include setupext/*.py include scripts/xmlproc_parse include scripts/xmlproc_val global-exclude */CVS/* PyXML-0.8.2/README0100644000076400001440000000373107614471161012603 0ustar martinusers XML package v0.8.2 This is the Python XML package. The distribution contains a validating XML parser, an implementation of the SAX and DOM programming interfaces, an interface to the Expat parser (and the Expat parser itself), and a C helper module that can speed up xmllib.py by a factor of 5. There's even documentation! For information on the licensing conditions for each component, consult the LICENCE file. The only requirements for installing the package are Python 2.0 or later, and a C compiler. Note that the Python must actually be an INSTALLed python, rather than one that is being used directly from Python's build area. This release has been tested with Python 2.x. To compile everything, simply perform the following steps. 1) Run "python setup.py build" to copy *.py files and compile the C extensions. 2) To install everything in the site-packages directory as an xml/ package, run "python setup.py install". If you want to use PyXML's experimental XSLT package, you need to pass --with-xslt to setup.py. If you also want to install FourThought's 4Suite package, you should not install the XSLT package and also avoid the XPath package, so you can use the one from 4Suite. This can be done by using the command line option --without-xpath. If you use a binary distribution package, no compiler is needed, and setup.py does not need to be run. If you have difficulty installing this software, send a problem report to describing the problem. Software versions and credits: 4DOM Fourthought, Inc. (Uche Ogbuji, Mike Olson) 4XSLT Fourthought, Inc. (Uche Ogbuji, Mike Olson) PyExpat Jack Jansen, Fred Drake, Martin v. Lwis Expat 1.95.6 James Clark, Clark Cooper, Fred Drake, Karl Waclawek saxlib-1.0 Lars Marius Garshol sgmlop-000705 Fredrik Lundh xmlproc 0.70 Lars Marius Garshol minidom, pulldom Paul Prescod PyTREX James Tauber PyXML-0.8.2/README.dom0100644000076400001440000000242407534565152013364 0ustar martinusers4DOM Copyright (C) 2000 Fourthought Inc, USA http://www.python.org/sigs/xml-sig/ http://lists.fourthought.com/mailman/listinfo/4suite Description =========== 4DOM is an implementation of the World-Wide Web Consortium recommended standard document object model for Python. 4DOM implements DOM Core level 2, HTML level 2 and Level 2 Document Traversal. 4DOM should work on all platforms supported by Python. If you have any problems with a particular platform, please e-mail the authors. Installation ============ Simply copy to a directory in your PYTHONPATH. GenerateHtml.py is no longer needed. License/Copyright ================= 4DOM is copyrighted by Fourthought Inc (http://Fourthought.com). Please read the file COPYRIGHT for the complete copyright and terms of license. Documentation ============= Please see the file docs/4DOM.html for general documentation The DOM API is specified at http://www.w3.org/TR/DOM-Level-2/ Contact and Support =================== Please consider joining the 4Suite users and support mailing list http://lists.fourthought.com/mailman/listinfo/4suite You can send comments, bug-reports and support requests to one or both of the following addresses: xml-sig@python.org 4Suite@lists.fourthought.com PyXML-0.8.2/README.pyexpat0100644000076400001440000000306307534565152014277 0ustar martinusersPython Expat wrapper module =========================== Building the pyexpat module -------------------------------------- The module is built as part of running setup.py Using the pyexpat module ----------------------- The pyexpat module exports two functions: ParserCreate(encoding) Creates a new parser object. The optional encoding arg (a string) specifies the encoding. ErrorString(number) Return a string corresponding to the given error number. Parser objects have one method: Parse(data, isfinal) Parse some data. If the optional isfinal arg is 1 this is the last bit of data. Raises an exception in case of an error, the error attributes have information on the error. Parser objects have the following attributes: StartElementHandler, EndElementHandler, CharacterDataHandler, ProcessingInstructionHandler - The Python handlers called for various events. See below for the signatures. ErrorCode, ErrorLineNumber, ErrorColumnNumber, ErrorByteIndex - Readonly integers giving information on the current parse error. Testing it ---------- There's a very minimal test script in expattest.py. It should be easy to adapt it to generate ESIS (but I'm not familiar enough with ESIS to do it). This module parsed Hamlet in 2 seconds on an 180 Mhz R5000 SGI O2. Feedback -------- Please report problems to xml-sig@python.org. The author is Jack Jansen, jack@cwi.nl. The expat proper was written by James Clark and can be found at http://www.jclark.com/xml/ . Jack Jansen, CWI, Amsterdam jack@cwi.nl PyXML-0.8.2/README.sgmlop0100644000076400001440000000613107534565152014105 0ustar martinusers ============================= The sgmlop accelerator module ============================= sgmlop contains an optimized SGML/XML parser, designed as an add-on to the sgmllib/htmllib and xmllib modules shipped with Python 1.5. using empty callbacks, this driver is about 6 times faster than the original xmllib implementation. when using sgmlop directly, it can be more than 50 times faster. for more information on benchmarking sgmlop, see below. Enjoy /F fredrik@pythonware.com http://www.pythonware.com -------------------------------------------------------------------- Copyright (c) 1998 by Secret Labs AB. Permission to use, copy, modify, and distribute this software and its associated documentation for any purpose and without fee is hereby granted. This software is provided as is. -------------------------------------------------------------------- release info ------------ This is the third public release. Changes include: - added a starttag attribute parser written in C. this gives a considerable speedup on files using lots of tag attributes - the callback object can now have an sgmllib/xmllib interface (finish/handle) *or* a saxlib interface (see saxhack.py for an example). contents -------- README this file sgmllib.py a drop-in replacement for the sgmllib.py module distributed with Python 1.5 xmllib.py a drop-in replacement for the xmllib.py module distributed with Python 1.5 saxhack.py illustrates how to implement the SAX DocumentHandler interface directly with native sgmlop. this is over 30 times faster than a corresponding parser based on the original xmllib. sgmlop.dll a precompiled version for python 1.5 on win32 sgmlop.c accelerator source code sgmlop.mak makefile for MSVC++ 5.0 generated by opal/pymake. make sure to change the directory names before you use it on your own machine. bench*.py various test files and benchmarks test*.py benchmarks ---------- benchmarking the sgmlop parser is non-trivial; if you don't install any callbacks, it's some 300 times faster than the original xmllib (it can parse more than 10 MB/s on a fast Pentium II). this means that in a typical test, far more time is lost on the Python method call overhead than on the parsing proper. my earlier benchmarks used a 'collecting' parser, which stored all tags and elements in a list. with that setup, sgmlop is roughly 5 times faster than the original implementation. the benchxml.py script provided with this release uses empty parsers instead (that is, all callbacks exists, but they include only a 'pass' operation), in order to measure the parser and Python call overhead only. here's a typical test run (with the time for the original xmllib implementation set to 1): parser time -------------------------------------------------------------------- slow xmllib 1.0 fast xmllib 0.156 (6.4x) sgmlop dummy 0.019 (53.5x) sgmlop null 0.003 (297.8x) the null time is obtained by running the parser without any callbacks installed. PyXML-0.8.2/TODO0100644000076400001440000000047107507520265012412 0ustar martinusersTODO list: * More demo programs * Lots of docstrings for pydoc's sake * Flesh out the test suite more (measure coverage first) * Scripts for running the demo programs and verifying that they work demo/xbel/ * Update all the software to match the current XBEL DTD * Add a test suite for the basic parser PyXML-0.8.2/setup.cfg0100644000076400001440000000015607217436417013546 0ustar martinusers[bdist_rpm] doc_files = ANNOUNCE,CREDITS,LICENCE,README,README.dom,README.pyexpat,README.sgmlop,doc,demo,test PyXML-0.8.2/setup.py0100644000076400001440000001541607614717720013444 0ustar martinusers#! /usr/bin/env python # Setup script for the XML tools # # Targets: build install help import sys, os, string from distutils.core import setup, Extension from setupext import Data_Files, install_Data_Files, wininst_request_delete from distutils.sysconfig import get_config_vars # I want to override the default build directory so the extension # modules are compiled and placed in the build/xml directory # tree. This is a bit clumsy, but I don't see a better way to do # this at the moment. ext_modules = [] # Rename xml to _xmlplus for Python 2.x if sys.hexversion < 0x2000000: def xml(s): return "xml"+s else: def xml(s): return "_xmlplus"+s # special command-line arguments LIBEXPAT = None LDFLAGS = [] args = sys.argv[:] extra_packages = [] with_xpath = 1 with_xslt = 0 for arg in args: if string.find(arg, '--with-libexpat=') == 0: LIBEXPAT = string.split(arg, '=')[1] sys.argv.remove(arg) elif string.find(arg, '--ldflags=') == 0: LDFLAGS = string.split(string.split(arg, '=')[1]) sys.argv.remove(arg) elif arg == '--with-xpath': with_xpath = 1 sys.argv.remove(arg) elif arg == '--with-xslt': with_xslt = 1 sys.argv.remove(arg) elif arg == '--without-xpath': with_xpath = 0 sys.argv.remove(arg) elif arg == '--without-xslt': with_xslt = 0 sys.argv.remove(arg) if sys.platform[:6] == "darwin" and \ distutils.sysconfig.get_config_var("LDSHARED").find("-flat_namespace") == -1: # Mac OS X LDFLAGS.append('-flat_namespace') if with_xpath: extra_packages.append(xml('.xpath')) if with_xslt: extra_packages.append(xml('.xslt')) def get_expat_prefix(): if LIBEXPAT: return LIBEXPAT # XXX temporarily disable usage of installed expat # until we figure out a way to determine its version return for p in ("/usr", "/usr/local"): incs = os.path.join(p, "include") libs = os.path.join(p, "lib") if os.path.isfile(os.path.join(incs, "expat.h")) \ and (os.path.isfile(os.path.join(libs, "libexpat.so")) or os.path.isfile(os.path.join(libs, "libexpat.a"))): return p expat_prefix = get_expat_prefix() sources = ['extensions/pyexpat.c'] if expat_prefix: define_macros = [('HAVE_EXPAT_H', None)] include_dirs = [os.path.join(expat_prefix, "include")] libraries = ['expat'] library_dirs = [os.path.join(expat_prefix, "lib")] else: # To build expat 1.95.x, we need to find out the byteorder if sys.byteorder == "little": xmlbo = "1234" else: xmlbo = "4321" define_macros = [ ('XML_NS', '1'), ('XML_DTD', '1'), ('BYTEORDER', xmlbo), ('XML_CONTEXT_BYTES','1024'), ] include_dirs = ['extensions/expat/lib'] sources.extend([ 'extensions/expat/lib/xmlparse.c', 'extensions/expat/lib/xmlrole.c', 'extensions/expat/lib/xmltok.c', ]) libraries = [] library_dirs = [] ext_modules.append( Extension(xml('.parsers.pyexpat'), define_macros=define_macros, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_link_args=LDFLAGS, sources=sources )) # Build sgmlop ext_modules.append( Extension(xml('.parsers.sgmlop'), extra_link_args=LDFLAGS, sources=['extensions/sgmlop.c'], )) # Build boolean ext_modules.append( Extension(xml('.utils.boolean'), extra_link_args=LDFLAGS, sources=['extensions/boolean.c'], )) # On Windows, install the documentation into a directory xmldoc, along # with xml/_xmlplus. For RPMs, docs are installed into the RPM doc # directory via setup.cfg (usuall /usr/doc). On all other systems, the # documentation is not installed. doc2xmldoc = 0 if sys.platform == 'win32': doc2xmldoc = 1 # This is a fragment from MANIFEST.in which should contain all # files which are considered documentation (doc, demo, test, plus some # toplevel files) # distutils 1.0 has a bug where # recursive-include test/output test_* # is translated into a pattern ^test\\output\.*test\_[^/]*$ # on windows, which results in files not being included. Work around # this bug by using graft where possible. docfiles=""" recursive-include doc *.html *.tex *.txt *.gif *.css *.api *.web recursive-include demo README *.py *.xml *.dtd *.html *.htm include demo/genxml/data.txt include demo/dom/html2html include demo/xbel/doc/xbel.bib include demo/xbel/doc/xbel.tex include demo/xmlproc/catalog.soc recursive-include test *.py *.xml *.html *.dtd include test/test.xml.out graft test/output include ANNOUNCE CREDITS LICENCE README* TODO global-exclude */CVS/* """ if doc2xmldoc: xmldocfiles = [ Data_Files(copy_to = 'xmldoc', template = string.split(docfiles,"\n"), preserve_path = 1) ] else: xmldocfiles = [] setup (name = "PyXML", version = "0.8.2", # Needs to match xml/__init__.version_info description = "Python/XML package", author = "XML-SIG", author_email = "xml-sig@python.org", url = "http://www.python.org/sigs/xml-sig/", long_description = """XML Parsers and API for Python This version of PyXML was tested with Python 2.x. """, # Override certain command classes with our own ones cmdclass = {'install_data':install_Data_Files, 'bdist_wininst':wininst_request_delete }, package_dir = {xml(''):'xml'}, data_files = [Data_Files(base_dir='install_lib', copy_to=xml('/dom/de/LC_MESSAGES'), files=['xml/dom/de/LC_MESSAGES/4Suite.mo']), Data_Files(base_dir='install_lib', copy_to=xml('/dom/en_US/LC_MESSAGES'), files=['xml/dom/en_US/LC_MESSAGES/4Suite.mo']), Data_Files(base_dir='install_lib', copy_to=xml('/dom/fr_FR/LC_MESSAGES'), files=['xml/dom/fr_FR/LC_MESSAGES/4Suite.mo']), ] + xmldocfiles, packages = [xml(''), xml('.dom'), xml('.dom.html'), xml('.dom.ext'), xml('.dom.ext.reader'), xml('.marshal'), xml('.unicode'), xml('.parsers'), xml('.parsers.xmlproc'), xml('.sax'), xml('.sax.drivers'), xml('.sax.drivers2'), xml('.utils'), xml('.schema'), #xml('.xpath'), xml('.xslt') ] + extra_packages, ext_modules = ext_modules, scripts = ['scripts/xmlproc_parse', 'scripts/xmlproc_val'] ) PyXML-0.8.2/PKG-INFO0100644000076400001440000000047707614726124013026 0ustar martinusersMetadata-Version: 1.0 Name: PyXML Version: 0.8.2 Summary: Python/XML package Home-page: http://www.python.org/sigs/xml-sig/ Author: XML-SIG Author-email: xml-sig@python.org License: UNKNOWN Description: XML Parsers and API for Python This version of PyXML was tested with Python 2.x. Platform: UNKNOWN