## 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 = targetLines 1–500 of 1260. Load more
# # 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 ElementPath except 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