1260 lines · 40.1 KB · Python
RawDownload
## ElementTree# $Id: ElementTree.py 2326 2005-03-17 07:45:21Z fredrik $## light-weight XML support for Python 1.5.2 and later.## history:# 2001-10-20 fl   created (from various sources)# 2001-11-01 fl   return root from parse method# 2002-02-16 fl   sort attributes in lexical order# 2002-04-06 fl   TreeBuilder refactoring, added PythonDoc markup# 2002-05-01 fl   finished TreeBuilder refactoring# 2002-07-14 fl   added basic namespace support to ElementTree.write# 2002-07-25 fl   added QName attribute support# 2002-10-20 fl   fixed encoding in write# 2002-11-24 fl   changed default encoding to ascii; fixed attribute encoding# 2002-11-27 fl   accept file objects or file names for parse/write# 2002-12-04 fl   moved XMLTreeBuilder back to this module# 2003-01-11 fl   fixed entity encoding glitch for us-ascii# 2003-02-13 fl   added XML literal factory# 2003-02-21 fl   added ProcessingInstruction/PI factory# 2003-05-11 fl   added tostring/fromstring helpers# 2003-05-26 fl   added ElementPath support# 2003-07-05 fl   added makeelement factory method# 2003-07-28 fl   added more well-known namespace prefixes# 2003-08-15 fl   fixed typo in ElementTree.findtext (Thomas Dartsch)# 2003-09-04 fl   fall back on emulator if ElementPath is not installed# 2003-10-31 fl   markup updates# 2003-11-15 fl   fixed nested namespace bug# 2004-03-28 fl   added XMLID helper# 2004-06-02 fl   added default support to findtext# 2004-06-08 fl   fixed encoding of non-ascii element/attribute names# 2004-08-23 fl   take advantage of post-2.1 expat features# 2005-02-01 fl   added iterparse implementation# 2005-03-02 fl   fixed iterparse support for pre-2.2 versions## Copyright (c) 1999-2005 by Fredrik Lundh.  All rights reserved.## fredrik@pythonware.com# http://www.pythonware.com## --------------------------------------------------------------------# The ElementTree toolkit is## Copyright (c) 1999-2005 by Fredrik Lundh## 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 MERCHANT-# ABILITY 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.# -------------------------------------------------------------------- # Licensed to PSF under a Contributor Agreement.# See http://www.python.org/2.4/license for licensing details. __all__ = [    # public symbols    "Comment",    "dump",    "Element", "ElementTree",    "fromstring",    "iselement", "iterparse",    "parse",    "PI", "ProcessingInstruction",    "QName",    "SubElement",    "tostring",    "TreeBuilder",    "VERSION", "XML",    "XMLParser", "XMLTreeBuilder",    ] ### The <b>Element</b> type is a flexible container object, designed to# store hierarchical data structures in memory. The type can be# described as a cross between a list and a dictionary.# <p># Each element has a number of properties associated with it:# <ul># <li>a <i>tag</i>. This is a string identifying what kind of data# this element represents (the element type, in other words).</li># <li>a number of <i>attributes</i>, stored in a Python dictionary.</li># <li>a <i>text</i> string.</li># <li>an optional <i>tail</i> string.</li># <li>a number of <i>child elements</i>, stored in a Python sequence</li># </ul>## To create an element instance, use the {@link #Element} or {@link# #SubElement} factory functions.# <p># The {@link #ElementTree} class can be used to wrap an element# structure, and convert it from and to XML.## import string, sys, re class _SimpleElementPath:    # emulate pre-1.2 find/findtext/findall behaviour    def find(self, element, tag):        for elem in element:            if elem.tag == tag:                return elem        return None    def findtext(self, element, tag, default=None):        for elem in element:            if elem.tag == tag:                return elem.text or ""        return default    def findall(self, element, tag):        if tag[:3] == ".//":            return element.getiterator(tag[3:])        result = []        for elem in element:            if elem.tag == tag:                result.append(elem)        return result try:    import ElementPathexcept ImportError:    # FIXME: issue warning in this case?    ElementPath = _SimpleElementPath() # TODO: add support for custom namespace resolvers/default namespaces# TODO: add improved support for incremental parsing VERSION = "1.2.6" ### Internal element class.  This class defines the Element interface,# and provides a reference implementation of this interface.# <p># You should not create instances of this class directly.  Use the# appropriate factory functions instead, such as {@link #Element}# and {@link #SubElement}.## @see Element# @see SubElement# @see Comment# @see ProcessingInstruction class _ElementInterface:    # <tag attrib>text<child/>...</tag>tail     ##    # (Attribute) Element tag.     tag = None     ##    # (Attribute) Element attribute dictionary.  Where possible, use    # {@link #_ElementInterface.get},    # {@link #_ElementInterface.set},    # {@link #_ElementInterface.keys}, and    # {@link #_ElementInterface.items} to access    # element attributes.     attrib = None     ##    # (Attribute) Text before first subelement.  This is either a    # string or the value None, if there was no text.     text = None     ##    # (Attribute) Text after this element's end tag, but before the    # next sibling element's start tag.  This is either a string or    # the value None, if there was no text.     tail = None # text after end tag, if any     def __init__(self, tag, attrib):        self.tag = tag        self.attrib = attrib        self._children = []     def __repr__(self):        return "<Element %s at %x>" % (self.tag, id(self))     ##    # Creates a new element object of the same type as this element.    #    # @param tag Element tag.    # @param attrib Element attributes, given as a dictionary.    # @return A new element instance.     def makeelement(self, tag, attrib):        return Element(tag, attrib)     ##    # Returns the number of subelements.    #    # @return The number of subelements.     def __len__(self):        return len(self._children)     ##    # Returns the given subelement.    #    # @param index What subelement to return.    # @return The given subelement.    # @exception IndexError If the given element does not exist.     def __getitem__(self, index):        return self._children[index]     ##    # Replaces the given subelement.    #    # @param index What subelement to replace.    # @param element The new element value.    # @exception IndexError If the given element does not exist.    # @exception AssertionError If element is not a valid object.     def __setitem__(self, index, element):        assert iselement(element)        self._children[index] = element     ##    # Deletes the given subelement.    #    # @param index What subelement to delete.    # @exception IndexError If the given element does not exist.     def __delitem__(self, index):        del self._children[index]     ##    # Returns a list containing subelements in the given range.    #    # @param start The first subelement to return.    # @param stop The first subelement that shouldn't be returned.    # @return A sequence object containing subelements.     def __getslice__(self, start, stop):        return self._children[start:stop]     ##    # Replaces a number of subelements with elements from a sequence.    #    # @param start The first subelement to replace.    # @param stop The first subelement that shouldn't be replaced.    # @param elements A sequence object with zero or more elements.    # @exception AssertionError If a sequence member is not a valid object.     def __setslice__(self, start, stop, elements):        for element in elements:            assert iselement(element)        self._children[start:stop] = list(elements)     ##    # Deletes a number of subelements.    #    # @param start The first subelement to delete.    # @param stop The first subelement to leave in there.     def __delslice__(self, start, stop):        del self._children[start:stop]     ##    # Adds a subelement to the end of this element.    #    # @param element The element to add.    # @exception AssertionError If a sequence member is not a valid object.     def append(self, element):        assert iselement(element)        self._children.append(element)     ##    # Inserts a subelement at the given position in this element.    #    # @param index Where to insert the new subelement.    # @exception AssertionError If the element is not a valid object.     def insert(self, index, element):        assert iselement(element)        self._children.insert(index, element)     ##    # Removes a matching subelement.  Unlike the <b>find</b> methods,    # this method compares elements based on identity, not on tag    # value or contents.    #    # @param element What element to remove.    # @exception ValueError If a matching element could not be found.    # @exception AssertionError If the element is not a valid object.     def remove(self, element):        assert iselement(element)        self._children.remove(element)     ##    # Returns all subelements.  The elements are returned in document    # order.    #    # @return A list of subelements.    # @defreturn list of Element instances     def getchildren(self):        return self._children     ##    # Finds the first matching subelement, by tag name or path.    #    # @param path What element to look for.    # @return The first matching element, or None if no element was found.    # @defreturn Element or None     def find(self, path):        return ElementPath.find(self, path)     ##    # Finds text for the first matching subelement, by tag name or path.    #    # @param path What element to look for.    # @param default What to return if the element was not found.    # @return The text content of the first matching element, or the    #     default value no element was found.  Note that if the element    #     has is found, but has no text content, this method returns an    #     empty string.    # @defreturn string     def findtext(self, path, default=None):        return ElementPath.findtext(self, path, default)     ##    # Finds all matching subelements, by tag name or path.    #    # @param path What element to look for.    # @return A list or iterator containing all matching elements,    #    in document order.    # @defreturn list of Element instances     def findall(self, path):        return ElementPath.findall(self, path)     ##    # Resets an element.  This function removes all subelements, clears    # all attributes, and sets the text and tail attributes to None.     def clear(self):        self.attrib.clear()        self._children = []        self.text = self.tail = None     ##    # Gets an element attribute.    #    # @param key What attribute to look for.    # @param default What to return if the attribute was not found.    # @return The attribute value, or the default value, if the    #     attribute was not found.    # @defreturn string or None     def get(self, key, default=None):        return self.attrib.get(key, default)     ##    # Sets an element attribute.    #    # @param key What attribute to set.    # @param value The attribute value.     def set(self, key, value):        self.attrib[key] = value     ##    # Gets a list of attribute names.  The names are returned in an    # arbitrary order (just like for an ordinary Python dictionary).    #    # @return A list of element attribute names.    # @defreturn list of strings     def keys(self):        return self.attrib.keys()     ##    # Gets element attributes, as a sequence.  The attributes are    # returned in an arbitrary order.    #    # @return A list of (name, value) tuples for all attributes.    # @defreturn list of (string, string) tuples     def items(self):        return self.attrib.items()     ##    # Creates a tree iterator.  The iterator loops over this element    # and all subelements, in document order, and returns all elements    # with a matching tag.    # <p>    # If the tree structure is modified during iteration, the result    # is undefined.    #    # @param tag What tags to look for (default is to return all elements).    # @return A list or iterator containing all the matching elements.    # @defreturn list or iterator     def getiterator(self, tag=None):        nodes = []        if tag == "*":            tag = None        if tag is None or self.tag == tag:            nodes.append(self)        for node in self._children:            nodes.extend(node.getiterator(tag))        return nodes # compatibility_Element = _ElementInterface ### Element factory.  This function returns an object implementing the# standard Element interface.  The exact class or type of that object# is implementation dependent, but it will always be compatible with# the {@link #_ElementInterface} class in this module.# <p># The element name, attribute names, and attribute values can be# either 8-bit ASCII strings or Unicode strings.## @param tag The element name.# @param attrib An optional dictionary, containing element attributes.# @param **extra Additional attributes, given as keyword arguments.# @return An element instance.# @defreturn Element def Element(tag, attrib={}, **extra):    attrib = attrib.copy()    attrib.update(extra)    return _ElementInterface(tag, attrib) ### Subelement factory.  This function creates an element instance, and# appends it to an existing element.# <p># The element name, attribute names, and attribute values can be# either 8-bit ASCII strings or Unicode strings.## @param parent The parent element.# @param tag The subelement name.# @param attrib An optional dictionary, containing element attributes.# @param **extra Additional attributes, given as keyword arguments.# @return An element instance.# @defreturn Element def SubElement(parent, tag, attrib={}, **extra):    attrib = attrib.copy()    attrib.update(extra)    element = parent.makeelement(tag, attrib)    parent.append(element)    return element ### Comment element factory.  This factory function creates a special# element that will be serialized as an XML comment.# <p># The comment string can be either an 8-bit ASCII string or a Unicode# string.## @param text A string containing the comment string.# @return An element instance, representing a comment.# @defreturn Element def Comment(text=None):    element = Element(Comment)    element.text = text    return element ### PI element factory.  This factory function creates a special element# that will be serialized as an XML processing instruction.## @param target A string containing the PI target.# @param text A string containing the PI contents, if any.# @return An element instance, representing a PI.# @defreturn Element def ProcessingInstruction(target, text=None):    element = Element(ProcessingInstruction)    element.text = target

Lines 1–500 of 1260.