diff options
author | Stefan Israelsson Tampe <stefan.itampe@gmail.com> | 2019-03-13 09:20:18 +0100 |
---|---|---|
committer | Stefan Israelsson Tampe <stefan.itampe@gmail.com> | 2019-03-13 09:20:18 +0100 |
commit | 6b0070bb5c37b118eb09c1ec023999bbdf1781e7 (patch) | |
tree | 7bbc9df1036b0a7733ea45f3dd74a199929176e1 /modules/language/python/module/xml/etree | |
parent | e1bf1a32c8453ea485365e9704e7cb983db3b4bb (diff) | |
parent | db36b6633b5ccd709eac44635ca88e8683ddb4e3 (diff) |
Merge branch 'master' of https://gitlab.com/python-on-guile/python-on-guile
Diffstat (limited to 'modules/language/python/module/xml/etree')
-rw-r--r-- | modules/language/python/module/xml/etree/ElementInclude.py~ | 143 | ||||
-rw-r--r-- | modules/language/python/module/xml/etree/ElementPath.py~ | 314 | ||||
-rw-r--r-- | modules/language/python/module/xml/etree/ElementTree.py~ | 1656 | ||||
-rw-r--r-- | modules/language/python/module/xml/etree/__pycache__/ElementInclude.cpython-36.pyc | bin | 1559 -> 0 bytes | |||
-rw-r--r-- | modules/language/python/module/xml/etree/__pycache__/ElementPath.cpython-36.pyc | bin | 6135 -> 0 bytes | |||
-rw-r--r-- | modules/language/python/module/xml/etree/__pycache__/ElementTree.cpython-36.pyc | bin | 44728 -> 0 bytes | |||
-rw-r--r-- | modules/language/python/module/xml/etree/__pycache__/__init__.cpython-36.pyc | bin | 123 -> 0 bytes | |||
-rw-r--r-- | modules/language/python/module/xml/etree/__pycache__/cElementTree.cpython-36.pyc | bin | 165 -> 0 bytes |
8 files changed, 0 insertions, 2113 deletions
diff --git a/modules/language/python/module/xml/etree/ElementInclude.py~ b/modules/language/python/module/xml/etree/ElementInclude.py~ deleted file mode 100644 index 963470e..0000000 --- a/modules/language/python/module/xml/etree/ElementInclude.py~ +++ /dev/null @@ -1,143 +0,0 @@ -# -# ElementTree -# $Id: ElementInclude.py 3375 2008-02-13 08:05:08Z fredrik $ -# -# limited xinclude support for element trees -# -# history: -# 2003-08-15 fl created -# 2003-11-14 fl fixed default loader -# -# Copyright (c) 2003-2004 by Fredrik Lundh. All rights reserved. -# -# fredrik@pythonware.com -# http://www.pythonware.com -# -# -------------------------------------------------------------------- -# The ElementTree toolkit is -# -# Copyright (c) 1999-2008 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/psf/license for licensing details. - -## -# Limited XInclude support for the ElementTree package. -## - -import copy -from . import ElementTree - -XINCLUDE = "{http://www.w3.org/2001/XInclude}" - -XINCLUDE_INCLUDE = XINCLUDE + "include" -XINCLUDE_FALLBACK = XINCLUDE + "fallback" - -## -# Fatal include error. - -class FatalIncludeError(SyntaxError): - pass - -## -# Default loader. This loader reads an included resource from disk. -# -# @param href Resource reference. -# @param parse Parse mode. Either "xml" or "text". -# @param encoding Optional text encoding (UTF-8 by default for "text"). -# @return The expanded resource. If the parse mode is "xml", this -# is an ElementTree instance. If the parse mode is "text", this -# is a Unicode string. If the loader fails, it can return None -# or raise an OSError exception. -# @throws OSError If the loader fails to load the resource. - -def default_loader(href, parse, encoding=None): - if parse == "xml": - with open(href, 'rb') as file: - data = ElementTree.parse(file).getroot() - else: - if not encoding: - encoding = 'UTF-8' - with open(href, 'r', encoding=encoding) as file: - data = file.read() - return data - -## -# Expand XInclude directives. -# -# @param elem Root element. -# @param loader Optional resource loader. If omitted, it defaults -# to {@link default_loader}. If given, it should be a callable -# that implements the same interface as <b>default_loader</b>. -# @throws FatalIncludeError If the function fails to include a given -# resource, or if the tree contains malformed XInclude elements. -# @throws OSError If the function fails to load a given resource. - -def include(elem, loader=None): - if loader is None: - loader = default_loader - # look for xinclude elements - i = 0 - while i < len(elem): - e = elem[i] - if e.tag == XINCLUDE_INCLUDE: - # process xinclude directive - href = e.get("href") - parse = e.get("parse", "xml") - if parse == "xml": - node = loader(href, parse) - if node is None: - raise FatalIncludeError( - "cannot load %r as %r" % (href, parse) - ) - node = copy.copy(node) - if e.tail: - node.tail = (node.tail or "") + e.tail - elem[i] = node - elif parse == "text": - text = loader(href, parse, e.get("encoding")) - if text is None: - raise FatalIncludeError( - "cannot load %r as %r" % (href, parse) - ) - if i: - node = elem[i-1] - node.tail = (node.tail or "") + text + (e.tail or "") - else: - elem.text = (elem.text or "") + text + (e.tail or "") - del elem[i] - continue - else: - raise FatalIncludeError( - "unknown parse type in xi:include tag (%r)" % parse - ) - elif e.tag == XINCLUDE_FALLBACK: - raise FatalIncludeError( - "xi:fallback tag must be child of xi:include (%r)" % e.tag - ) - else: - include(e, loader) - i = i + 1 diff --git a/modules/language/python/module/xml/etree/ElementPath.py~ b/modules/language/python/module/xml/etree/ElementPath.py~ deleted file mode 100644 index ab6b79a..0000000 --- a/modules/language/python/module/xml/etree/ElementPath.py~ +++ /dev/null @@ -1,314 +0,0 @@ -# -# ElementTree -# $Id: ElementPath.py 3375 2008-02-13 08:05:08Z fredrik $ -# -# limited xpath support for element trees -# -# history: -# 2003-05-23 fl created -# 2003-05-28 fl added support for // etc -# 2003-08-27 fl fixed parsing of periods in element names -# 2007-09-10 fl new selection engine -# 2007-09-12 fl fixed parent selector -# 2007-09-13 fl added iterfind; changed findall to return a list -# 2007-11-30 fl added namespaces support -# 2009-10-30 fl added child element value filter -# -# Copyright (c) 2003-2009 by Fredrik Lundh. All rights reserved. -# -# fredrik@pythonware.com -# http://www.pythonware.com -# -# -------------------------------------------------------------------- -# The ElementTree toolkit is -# -# Copyright (c) 1999-2009 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/psf/license for licensing details. - -## -# Implementation module for XPath support. There's usually no reason -# to import this module directly; the <b>ElementTree</b> does this for -# you, if needed. -## - -import re - -xpath_tokenizer_re = re.compile( - r"(" - r"'[^']*'|\"[^\"]*\"|" - r"::|" - r"//?|" - r"\.\.|" - r"\(\)|" - r"[/.*:\[\]\(\)@=])|" - r"((?:\{[^}]+\})?[^/\[\]\(\)@=\s]+)|" - r"\s+" - ) - -def xpath_tokenizer(pattern, namespaces=None): - for token in xpath_tokenizer_re.findall(pattern): - tag = token[1] - if tag and tag[0] != "{" and ":" in tag: - try: - prefix, uri = tag.split(":", 1) - if not namespaces: - raise KeyError - yield token[0], "{%s}%s" % (namespaces[prefix], uri) - except KeyError: - raise SyntaxError("prefix %r not found in prefix map" % prefix) - else: - yield token - -def get_parent_map(context): - parent_map = context.parent_map - if parent_map is None: - context.parent_map = parent_map = {} - for p in context.root.iter(): - for e in p: - parent_map[e] = p - return parent_map - -def prepare_child(next, token): - tag = token[1] - def select(context, result): - for elem in result: - for e in elem: - if e.tag == tag: - yield e - return select - -def prepare_star(next, token): - def select(context, result): - for elem in result: - yield from elem - return select - -def prepare_self(next, token): - def select(context, result): - yield from result - return select - -def prepare_descendant(next, token): - try: - token = next() - except StopIteration: - return - if token[0] == "*": - tag = "*" - elif not token[0]: - tag = token[1] - else: - raise SyntaxError("invalid descendant") - def select(context, result): - for elem in result: - for e in elem.iter(tag): - if e is not elem: - yield e - return select - -def prepare_parent(next, token): - def select(context, result): - # FIXME: raise error if .. is applied at toplevel? - parent_map = get_parent_map(context) - result_map = {} - for elem in result: - if elem in parent_map: - parent = parent_map[elem] - if parent not in result_map: - result_map[parent] = None - yield parent - return select - -def prepare_predicate(next, token): - # FIXME: replace with real parser!!! refs: - # http://effbot.org/zone/simple-iterator-parser.htm - # http://javascript.crockford.com/tdop/tdop.html - signature = [] - predicate = [] - while 1: - try: - token = next() - except StopIteration: - return - if token[0] == "]": - break - if token[0] and token[0][:1] in "'\"": - token = "'", token[0][1:-1] - signature.append(token[0] or "-") - predicate.append(token[1]) - signature = "".join(signature) - # use signature to determine predicate type - if signature == "@-": - # [@attribute] predicate - key = predicate[1] - def select(context, result): - for elem in result: - if elem.get(key) is not None: - yield elem - return select - if signature == "@-='": - # [@attribute='value'] - key = predicate[1] - value = predicate[-1] - def select(context, result): - for elem in result: - if elem.get(key) == value: - yield elem - return select - if signature == "-" and not re.match(r"\-?\d+$", predicate[0]): - # [tag] - tag = predicate[0] - def select(context, result): - for elem in result: - if elem.find(tag) is not None: - yield elem - return select - if signature == "-='" and not re.match(r"\-?\d+$", predicate[0]): - # [tag='value'] - tag = predicate[0] - value = predicate[-1] - def select(context, result): - for elem in result: - for e in elem.findall(tag): - if "".join(e.itertext()) == value: - yield elem - break - return select - if signature == "-" or signature == "-()" or signature == "-()-": - # [index] or [last()] or [last()-index] - if signature == "-": - # [index] - index = int(predicate[0]) - 1 - if index < 0: - raise SyntaxError("XPath position >= 1 expected") - else: - if predicate[0] != "last": - raise SyntaxError("unsupported function") - if signature == "-()-": - try: - index = int(predicate[2]) - 1 - except ValueError: - raise SyntaxError("unsupported expression") - if index > -2: - raise SyntaxError("XPath offset from last() must be negative") - else: - index = -1 - def select(context, result): - parent_map = get_parent_map(context) - for elem in result: - try: - parent = parent_map[elem] - # FIXME: what if the selector is "*" ? - elems = list(parent.findall(elem.tag)) - if elems[index] is elem: - yield elem - except (IndexError, KeyError): - pass - return select - raise SyntaxError("invalid predicate") - -ops = { - "": prepare_child, - "*": prepare_star, - ".": prepare_self, - "..": prepare_parent, - "//": prepare_descendant, - "[": prepare_predicate, - } - -_cache = {} - -class _SelectorContext: - parent_map = None - def __init__(self, root): - self.root = root - -# -------------------------------------------------------------------- - -## -# Generate all matching objects. - -def iterfind(elem, path, namespaces=None): - # compile selector pattern - cache_key = (path, None if namespaces is None - else tuple(sorted(namespaces.items()))) - if path[-1:] == "/": - path = path + "*" # implicit all (FIXME: keep this?) - try: - selector = _cache[cache_key] - except KeyError: - if len(_cache) > 100: - _cache.clear() - if path[:1] == "/": - raise SyntaxError("cannot use absolute path on element") - next = iter(xpath_tokenizer(path, namespaces)).__next__ - try: - token = next() - except StopIteration: - return - selector = [] - while 1: - try: - selector.append(ops[token[0]](next, token)) - except StopIteration: - raise SyntaxError("invalid path") - try: - token = next() - if token[0] == "/": - token = next() - except StopIteration: - break - _cache[cache_key] = selector - # execute selector pattern - result = [elem] - context = _SelectorContext(elem) - for select in selector: - result = select(context, result) - return result - -## -# Find first matching object. - -def find(elem, path, namespaces=None): - return next(iterfind(elem, path, namespaces), None) - -## -# Find all matching objects. - -def findall(elem, path, namespaces=None): - return list(iterfind(elem, path, namespaces)) - -## -# Find text for first matching object. - -def findtext(elem, path, default=None, namespaces=None): - try: - elem = next(iterfind(elem, path, namespaces)) - return elem.text or "" - except StopIteration: - return default diff --git a/modules/language/python/module/xml/etree/ElementTree.py~ b/modules/language/python/module/xml/etree/ElementTree.py~ deleted file mode 100644 index cf4e1da..0000000 --- a/modules/language/python/module/xml/etree/ElementTree.py~ +++ /dev/null @@ -1,1656 +0,0 @@ -"""Lightweight XML support for Python. - - XML is an inherently hierarchical data format, and the most natural way to - represent it is with a tree. This module has two classes for this purpose: - - 1. ElementTree represents the whole XML document as a tree and - - 2. Element represents a single node in this tree. - - Interactions with the whole document (reading and writing to/from files) are - usually done on the ElementTree level. Interactions with a single XML element - and its sub-elements are done on the Element level. - - Element is a flexible container object designed to store hierarchical data - structures in memory. It can be described as a cross between a list and a - dictionary. Each Element has a number of properties associated with it: - - 'tag' - a string containing the element's name. - - 'attributes' - a Python dictionary storing the element's attributes. - - 'text' - a string containing the element's text content. - - 'tail' - an optional string containing text after the element's end tag. - - And a number of child elements stored in a Python sequence. - - To create an element instance, use the Element constructor, - or the SubElement factory function. - - You can also use the ElementTree class to wrap an element structure - and convert it to and from XML. - -""" - -#--------------------------------------------------------------------- -# Licensed to PSF under a Contributor Agreement. -# See http://www.python.org/psf/license for licensing details. -# -# ElementTree -# Copyright (c) 1999-2008 by Fredrik Lundh. All rights reserved. -# -# fredrik@pythonware.com -# http://www.pythonware.com -# -------------------------------------------------------------------- -# The ElementTree toolkit is -# -# Copyright (c) 1999-2008 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. -# -------------------------------------------------------------------- - -__all__ = [ - # public symbols - "Comment", - "dump", - "Element", "ElementTree", - "fromstring", "fromstringlist", - "iselement", "iterparse", - "parse", "ParseError", - "PI", "ProcessingInstruction", - "QName", - "SubElement", - "tostring", "tostringlist", - "TreeBuilder", - "VERSION", - "XML", "XMLID", - "XMLParser", "XMLPullParser", - "register_namespace", - ] - -VERSION = "1.3.0" - -import sys -import re -import warnings -import io -import collections -import contextlib - -from . import ElementPath - - -class ParseError(SyntaxError): - """An error when parsing an XML document. - - In addition to its exception value, a ParseError contains - two extra attributes: - 'code' - the specific exception code - 'position' - the line and column of the error - - """ - pass - -# -------------------------------------------------------------------- - - -def iselement(element): - """Return True if *element* appears to be an Element.""" - return hasattr(element, 'tag') - - -class Element: - """An XML element. - - This class is the reference implementation of the Element interface. - - An element's length is its number of subelements. That means if you - want to check if an element is truly empty, you should check BOTH - its length AND its text attribute. - - The element tag, attribute names, and attribute values can be either - bytes or strings. - - *tag* is the element name. *attrib* is an optional dictionary containing - element attributes. *extra* are additional element attributes given as - keyword arguments. - - Example form: - <tag attrib>text<child/>...</tag>tail - - """ - - tag = None - """The element's name.""" - - attrib = None - """Dictionary of the element's attributes.""" - - text = None - """ - Text before first subelement. This is either a string or the value None. - Note that if there is no text, this attribute may be either - None or the empty string, depending on the parser. - - """ - - tail = None - """ - 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. Note that if there - was no text, this attribute may be either None or an empty string, - depending on the parser. - - """ - - def __init__(self, tag, attrib={}, **extra): - if not isinstance(attrib, dict): - raise TypeError("attrib must be dict, not %s" % ( - attrib.__class__.__name__,)) - attrib = attrib.copy() - attrib.update(extra) - self.tag = tag - self.attrib = attrib - self._children = [] - - def __repr__(self): - return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self)) - - def makeelement(self, tag, attrib): - """Create a new element with the same type. - - *tag* is a string containing the element name. - *attrib* is a dictionary containing the element attributes. - - Do not call this method, use the SubElement factory function instead. - - """ - return self.__class__(tag, attrib) - - def copy(self): - """Return copy of current element. - - This creates a shallow copy. Subelements will be shared with the - original tree. - - """ - elem = self.makeelement(self.tag, self.attrib) - elem.text = self.text - elem.tail = self.tail - elem[:] = self - return elem - - def __len__(self): - return len(self._children) - - def __bool__(self): - warnings.warn( - "The behavior of this method will change in future versions. " - "Use specific 'len(elem)' or 'elem is not None' test instead.", - FutureWarning, stacklevel=2 - ) - return len(self._children) != 0 # emulate old behaviour, for now - - def __getitem__(self, index): - return self._children[index] - - def __setitem__(self, index, element): - # if isinstance(index, slice): - # for elt in element: - # assert iselement(elt) - # else: - # assert iselement(element) - self._children[index] = element - - def __delitem__(self, index): - del self._children[index] - - def append(self, subelement): - """Add *subelement* to the end of this element. - - The new element will appear in document order after the last existing - subelement (or directly after the text, if it's the first subelement), - but before the end tag for this element. - - """ - self._assert_is_element(subelement) - self._children.append(subelement) - - def extend(self, elements): - """Append subelements from a sequence. - - *elements* is a sequence with zero or more elements. - - """ - for element in elements: - self._assert_is_element(element) - self._children.extend(elements) - - def insert(self, index, subelement): - """Insert *subelement* at position *index*.""" - self._assert_is_element(subelement) - self._children.insert(index, subelement) - - def _assert_is_element(self, e): - # Need to refer to the actual Python implementation, not the - # shadowing C implementation. - if not isinstance(e, _Element_Py): - raise TypeError('expected an Element, not %s' % type(e).__name__) - - def remove(self, subelement): - """Remove matching subelement. - - Unlike the find methods, this method compares elements based on - identity, NOT ON tag value or contents. To remove subelements by - other means, the easiest way is to use a list comprehension to - select what elements to keep, and then use slice assignment to update - the parent element. - - ValueError is raised if a matching element could not be found. - - """ - # assert iselement(element) - self._children.remove(subelement) - - def getchildren(self): - """(Deprecated) Return all subelements. - - Elements are returned in document order. - - """ - warnings.warn( - "This method will be removed in future versions. " - "Use 'list(elem)' or iteration over elem instead.", - DeprecationWarning, stacklevel=2 - ) - return self._children - - def find(self, path, namespaces=None): - """Find first matching element by tag name or path. - - *path* is a string having either an element tag or an XPath, - *namespaces* is an optional mapping from namespace prefix to full name. - - Return the first matching element, or None if no element was found. - - """ - return ElementPath.find(self, path, namespaces) - - def findtext(self, path, default=None, namespaces=None): - """Find text for first matching element by tag name or path. - - *path* is a string having either an element tag or an XPath, - *default* is the value to return if the element was not found, - *namespaces* is an optional mapping from namespace prefix to full name. - - Return text content of first matching element, or default value if - none was found. Note that if an element is found having no text - content, the empty string is returned. - - """ - return ElementPath.findtext(self, path, default, namespaces) - - def findall(self, path, namespaces=None): - """Find all matching subelements by tag name or path. - - *path* is a string having either an element tag or an XPath, - *namespaces* is an optional mapping from namespace prefix to full name. - - Returns list containing all matching elements in document order. - - """ - return ElementPath.findall(self, path, namespaces) - - def iterfind(self, path, namespaces=None): - """Find all matching subelements by tag name or path. - - *path* is a string having either an element tag or an XPath, - *namespaces* is an optional mapping from namespace prefix to full name. - - Return an iterable yielding all matching elements in document order. - - """ - return ElementPath.iterfind(self, path, namespaces) - - def clear(self): - """Reset element. - - This function removes all subelements, clears all attributes, and sets - the text and tail attributes to None. - - """ - self.attrib.clear() - self._children = [] - self.text = self.tail = None - - def get(self, key, default=None): - """Get element attribute. - - Equivalent to attrib.get, but some implementations may handle this a - bit more efficiently. *key* is what attribute to look for, and - *default* is what to return if the attribute was not found. - - Returns a string containing the attribute value, or the default if - attribute was not found. - - """ - return self.attrib.get(key, default) - - def set(self, key, value): - """Set element attribute. - - Equivalent to attrib[key] = value, but some implementations may handle - this a bit more efficiently. *key* is what attribute to set, and - *value* is the attribute value to set it to. - - """ - self.attrib[key] = value - - def keys(self): - """Get list of attribute names. - - Names are returned in an arbitrary order, just like an ordinary - Python dict. Equivalent to attrib.keys() - - """ - return self.attrib.keys() - - def items(self): - """Get element attributes as a sequence. - - The attributes are returned in arbitrary order. Equivalent to - attrib.items(). - - Return a list of (name, value) tuples. - - """ - return self.attrib.items() - - def iter(self, tag=None): - """Create tree iterator. - - The iterator loops over the element and all subelements in document - order, returning all elements with a matching tag. - - If the tree structure is modified during iteration, new or removed - elements may or may not be included. To get a stable set, use the - list() function on the iterator, and loop over the resulting list. - - *tag* is what tags to look for (default is to return all elements) - - Return an iterator containing all the matching elements. - - """ - if tag == "*": - tag = None - if tag is None or self.tag == tag: - yield self - for e in self._children: - yield from e.iter(tag) - - # compatibility - def getiterator(self, tag=None): - # Change for a DeprecationWarning in 1.4 - warnings.warn( - "This method will be removed in future versions. " - "Use 'elem.iter()' or 'list(elem.iter())' instead.", - PendingDeprecationWarning, stacklevel=2 - ) - return list(self.iter(tag)) - - def itertext(self): - """Create text iterator. - - The iterator loops over the element and all subelements in document - order, returning all inner text. - - """ - tag = self.tag - if not isinstance(tag, str) and tag is not None: - return - t = self.text - if t: - yield t - for e in self: - yield from e.itertext() - t = e.tail - if t: - yield t - - -def SubElement(parent, tag, attrib={}, **extra): - """Subelement factory which creates an element instance, and appends it - to an existing parent. - - The element tag, attribute names, and attribute values can be either - bytes or Unicode strings. - - *parent* is the parent element, *tag* is the subelements name, *attrib* is - an optional directory containing element attributes, *extra* are - additional attributes given as keyword arguments. - - """ - attrib = attrib.copy() - attrib.update(extra) - element = parent.makeelement(tag, attrib) - parent.append(element) - return element - - -def Comment(text=None): - """Comment element factory. - - This function creates a special element which the standard serializer - serializes as an XML comment. - - *text* is a string containing the comment string. - - """ - element = Element(Comment) - element.text = text - return element - - -def ProcessingInstruction(target, text=None): - """Processing Instruction element factory. - - This function creates a special element which the standard serializer - serializes as an XML comment. - - *target* is a string containing the processing instruction, *text* is a - string containing the processing instruction contents, if any. - - """ - element = Element(ProcessingInstruction) - element.text = target - if text: - element.text = element.text + " " + text - return element - -PI = ProcessingInstruction - - -class QName: - """Qualified name wrapper. - - This class can be used to wrap a QName attribute value in order to get - proper namespace handing on output. - - *text_or_uri* is a string containing the QName value either in the form - {uri}local, or if the tag argument is given, the URI part of a QName. - - *tag* is an optional argument which if given, will make the first - argument (text_or_uri) be interpreted as a URI, and this argument (tag) - be interpreted as a local name. - - """ - def __init__(self, text_or_uri, tag=None): - if tag: - text_or_uri = "{%s}%s" % (text_or_uri, tag) - self.text = text_or_uri - def __str__(self): - return self.text - def __repr__(self): - return '<%s %r>' % (self.__class__.__name__, self.text) - def __hash__(self): - return hash(self.text) - def __le__(self, other): - if isinstance(other, QName): - return self.text <= other.text - return self.text <= other - def __lt__(self, other): - if isinstance(other, QName): - return self.text < other.text - return self.text < other - def __ge__(self, other): - if isinstance(other, QName): - return self.text >= other.text - return self.text >= other - def __gt__(self, other): - if isinstance(other, QName): - return self.text > other.text - return self.text > other - def __eq__(self, other): - if isinstance(other, QName): - return self.text == other.text - return self.text == other - -# -------------------------------------------------------------------- - - -class ElementTree: - """An XML element hierarchy. - - This class also provides support for serialization to and from - standard XML. - - *element* is an optional root element node, - *file* is an optional file handle or file name of an XML file whose - contents will be used to initialize the tree with. - - """ - def __init__(self, element=None, file=None): - # assert element is None or iselement(element) - self._root = element # first node - if file: - self.parse(file) - - def getroot(self): - """Return root element of this tree.""" - return self._root - - def _setroot(self, element): - """Replace root element of this tree. - - This will discard the current contents of the tree and replace it - with the given element. Use with care! - - """ - # assert iselement(element) - self._root = element - - def parse(self, source, parser=None): - """Load external XML document into element tree. - - *source* is a file name or file object, *parser* is an optional parser - instance that defaults to XMLParser. - - ParseError is raised if the parser fails to parse the document. - - Returns the root element of the given source document. - - """ - close_source = False - if not hasattr(source, "read"): - source = open(source, "rb") - close_source = True - try: - if parser is None: - # If no parser was specified, create a default XMLParser - parser = XMLParser() - if hasattr(parser, '_parse_whole'): - # The default XMLParser, when it comes from an accelerator, - # can define an internal _parse_whole API for efficiency. - # It can be used to parse the whole source without feeding - # it with chunks. - self._root = parser._parse_whole(source) - return self._root - while True: - data = source.read(65536) - if not data: - break - parser.feed(data) - self._root = parser.close() - return self._root - finally: - if close_source: - source.close() - - def iter(self, tag=None): - """Create and return tree iterator for the root element. - - The iterator loops over all elements in this tree, in document order. - - *tag* is a string with the tag name to iterate over - (default is to return all elements). - - """ - # assert self._root is not None - return self._root.iter(tag) - - # compatibility - def getiterator(self, tag=None): - # Change for a DeprecationWarning in 1.4 - warnings.warn( - "This method will be removed in future versions. " - "Use 'tree.iter()' or 'list(tree.iter())' instead.", - PendingDeprecationWarning, stacklevel=2 - ) - return list(self.iter(tag)) - - def find(self, path, namespaces=None): - """Find first matching element by tag name or path. - - Same as getroot().find(path), which is Element.find() - - *path* is a string having either an element tag or an XPath, - *namespaces* is an optional mapping from namespace prefix to full name. - - Return the first matching element, or None if no element was found. - - """ - # assert self._root is not None - if path[:1] == "/": - path = "." + path - warnings.warn( - "This search is broken in 1.3 and earlier, and will be " - "fixed in a future version. If you rely on the current " - "behaviour, change it to %r" % path, - FutureWarning, stacklevel=2 - ) - return self._root.find(path, namespaces) - - def findtext(self, path, default=None, namespaces=None): - """Find first matching element by tag name or path. - - Same as getroot().findtext(path), which is Element.findtext() - - *path* is a string having either an element tag or an XPath, - *namespaces* is an optional mapping from namespace prefix to full name. - - Return the first matching element, or None if no element was found. - - """ - # assert self._root is not None - if path[:1] == "/": - path = "." + path - warnings.warn( - "This search is broken in 1.3 and earlier, and will be " - "fixed in a future version. If you rely on the current " - "behaviour, change it to %r" % path, - FutureWarning, stacklevel=2 - ) - return self._root.findtext(path, default, namespaces) - - def findall(self, path, namespaces=None): - """Find all matching subelements by tag name or path. - - Same as getroot().findall(path), which is Element.findall(). - - *path* is a string having either an element tag or an XPath, - *namespaces* is an optional mapping from namespace prefix to full name. - - Return list containing all matching elements in document order. - - """ - # assert self._root is not None - if path[:1] == "/": - path = "." + path - warnings.warn( - "This search is broken in 1.3 and earlier, and will be " - "fixed in a future version. If you rely on the current " - "behaviour, change it to %r" % path, - FutureWarning, stacklevel=2 - ) - return self._root.findall(path, namespaces) - - def iterfind(self, path, namespaces=None): - """Find all matching subelements by tag name or path. - - Same as getroot().iterfind(path), which is element.iterfind() - - *path* is a string having either an element tag or an XPath, - *namespaces* is an optional mapping from namespace prefix to full name. - - Return an iterable yielding all matching elements in document order. - - """ - # assert self._root is not None - if path[:1] == "/": - path = "." + path - warnings.warn( - "This search is broken in 1.3 and earlier, and will be " - "fixed in a future version. If you rely on the current " - "behaviour, change it to %r" % path, - FutureWarning, stacklevel=2 - ) - return self._root.iterfind(path, namespaces) - - def write(self, file_or_filename, - encoding=None, - xml_declaration=None, - default_namespace=None, - method=None, *, - short_empty_elements=True): - """Write element tree to a file as XML. - - Arguments: - *file_or_filename* -- file name or a file object opened for writing - - *encoding* -- the output encoding (default: US-ASCII) - - *xml_declaration* -- bool indicating if an XML declaration should be - added to the output. If None, an XML declaration - is added if encoding IS NOT either of: - US-ASCII, UTF-8, or Unicode - - *default_namespace* -- sets the default XML namespace (for "xmlns") - - *method* -- either "xml" (default), "html, "text", or "c14n" - - *short_empty_elements* -- controls the formatting of elements - that contain no content. If True (default) - they are emitted as a single self-closed - tag, otherwise they are emitted as a pair - of start/end tags - - """ - if not method: - method = "xml" - elif method not in _serialize: - raise ValueError("unknown method %r" % method) - if not encoding: - if method == "c14n": - encoding = "utf-8" - else: - encoding = "us-ascii" - enc_lower = encoding.lower() - with _get_writer(file_or_filename, enc_lower) as write: - if method == "xml" and (xml_declaration or - (xml_declaration is None and - enc_lower not in ("utf-8", "us-ascii", "unicode"))): - declared_encoding = encoding - if enc_lower == "unicode": - # Retrieve the default encoding for the xml declaration - import locale - declared_encoding = locale.getpreferredencoding() - write("<?xml version='1.0' encoding='%s'?>\n" % ( - declared_encoding,)) - if method == "text": - _serialize_text(write, self._root) - else: - qnames, namespaces = _namespaces(self._root, default_namespace) - serialize = _serialize[method] - serialize(write, self._root, qnames, namespaces, - short_empty_elements=short_empty_elements) - - def write_c14n(self, file): - # lxml.etree compatibility. use output method instead - return self.write(file, method="c14n") - -# -------------------------------------------------------------------- -# serialization support - -@contextlib.contextmanager -def _get_writer(file_or_filename, encoding): - # returns text write method and release all resources after using - try: - write = file_or_filename.write - except AttributeError: - # file_or_filename is a file name - if encoding == "unicode": - file = open(file_or_filename, "w") - else: - file = open(file_or_filename, "w", encoding=encoding, - errors="xmlcharrefreplace") - with file: - yield file.write - else: - # file_or_filename is a file-like object - # encoding determines if it is a text or binary writer - if encoding == "unicode": - # use a text writer as is - yield write - else: - # wrap a binary writer with TextIOWrapper - with contextlib.ExitStack() as stack: - if isinstance(file_or_filename, io.BufferedIOBase): - file = file_or_filename - elif isinstance(file_or_filename, io.RawIOBase): - file = io.BufferedWriter(file_or_filename) - # Keep the original file open when the BufferedWriter is - # destroyed - stack.callback(file.detach) - else: - # This is to handle passed objects that aren't in the - # IOBase hierarchy, but just have a write method - file = io.BufferedIOBase() - file.writable = lambda: True - file.write = write - try: - # TextIOWrapper uses this methods to determine - # if BOM (for UTF-16, etc) should be added - file.seekable = file_or_filename.seekable - file.tell = file_or_filename.tell - except AttributeError: - pass - file = io.TextIOWrapper(file, - encoding=encoding, - errors="xmlcharrefreplace", - newline="\n") - # Keep the original file open when the TextIOWrapper is - # destroyed - stack.callback(file.detach) - yield file.write - -def _namespaces(elem, default_namespace=None): - # identify namespaces used in this tree - - # maps qnames to *encoded* prefix:local names - qnames = {None: None} - - # maps uri:s to prefixes - namespaces = {} - if default_namespace: - namespaces[default_namespace] = "" - - def add_qname(qname): - # calculate serialized qname representation - try: - if qname[:1] == "{": - uri, tag = qname[1:].rsplit("}", 1) - prefix = namespaces.get(uri) - if prefix is None: - prefix = _namespace_map.get(uri) - if prefix is None: - prefix = "ns%d" % len(namespaces) - if prefix != "xml": - namespaces[uri] = prefix - if prefix: - qnames[qname] = "%s:%s" % (prefix, tag) - else: - qnames[qname] = tag # default element - else: - if default_namespace: - # FIXME: can this be handled in XML 1.0? - raise ValueError( - "cannot use non-qualified names with " - "default_namespace option" - ) - qnames[qname] = qname - except TypeError: - _raise_serialization_error(qname) - - # populate qname and namespaces table - for elem in elem.iter(): - tag = elem.tag - if isinstance(tag, QName): - if tag.text not in qnames: - add_qname(tag.text) - elif isinstance(tag, str): - if tag not in qnames: - add_qname(tag) - elif tag is not None and tag is not Comment and tag is not PI: - _raise_serialization_error(tag) - for key, value in elem.items(): - if isinstance(key, QName): - key = key.text - if key not in qnames: - add_qname(key) - if isinstance(value, QName) and value.text not in qnames: - add_qname(value.text) - text = elem.text - if isinstance(text, QName) and text.text not in qnames: - add_qname(text.text) - return qnames, namespaces - -def _serialize_xml(write, elem, qnames, namespaces, - short_empty_elements, **kwargs): - tag = elem.tag - text = elem.text - if tag is Comment: - write("<!--%s-->" % text) - elif tag is ProcessingInstruction: - write("<?%s?>" % text) - else: - tag = qnames[tag] - if tag is None: - if text: - write(_escape_cdata(text)) - for e in elem: - _serialize_xml(write, e, qnames, None, - short_empty_elements=short_empty_elements) - else: - write("<" + tag) - items = list(elem.items()) - if items or namespaces: - if namespaces: - for v, k in sorted(namespaces.items(), - key=lambda x: x[1]): # sort on prefix - if k: - k = ":" + k - write(" xmlns%s=\"%s\"" % ( - k, - _escape_attrib(v) - )) - for k, v in sorted(items): # lexical order - if isinstance(k, QName): - k = k.text - if isinstance(v, QName): - v = qnames[v.text] - else: - v = _escape_attrib(v) - write(" %s=\"%s\"" % (qnames[k], v)) - if text or len(elem) or not short_empty_elements: - write(">") - if text: - write(_escape_cdata(text)) - for e in elem: - _serialize_xml(write, e, qnames, None, - short_empty_elements=short_empty_elements) - write("</" + tag + ">") - else: - write(" />") - if elem.tail: - write(_escape_cdata(elem.tail)) - -HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr", - "img", "input", "isindex", "link", "meta", "param") - -try: - HTML_EMPTY = set(HTML_EMPTY) -except NameError: - pass - -def _serialize_html(write, elem, qnames, namespaces, **kwargs): - tag = elem.tag - text = elem.text - if tag is Comment: - write("<!--%s-->" % _escape_cdata(text)) - elif tag is ProcessingInstruction: - write("<?%s?>" % _escape_cdata(text)) - else: - tag = qnames[tag] - if tag is None: - if text: - write(_escape_cdata(text)) - for e in elem: - _serialize_html(write, e, qnames, None) - else: - write("<" + tag) - items = list(elem.items()) - if items or namespaces: - if namespaces: - for v, k in sorted(namespaces.items(), - key=lambda x: x[1]): # sort on prefix - if k: - k = ":" + k - write(" xmlns%s=\"%s\"" % ( - k, - _escape_attrib(v) - )) - for k, v in sorted(items): # lexical order - if isinstance(k, QName): - k = k.text - if isinstance(v, QName): - v = qnames[v.text] - else: - v = _escape_attrib_html(v) - # FIXME: handle boolean attributes - write(" %s=\"%s\"" % (qnames[k], v)) - write(">") - ltag = tag.lower() - if text: - if ltag == "script" or ltag == "style": - write(text) - else: - write(_escape_cdata(text)) - for e in elem: - _serialize_html(write, e, qnames, None) - if ltag not in HTML_EMPTY: - write("</" + tag + ">") - if elem.tail: - write(_escape_cdata(elem.tail)) - -def _serialize_text(write, elem): - for part in elem.itertext(): - write(part) - if elem.tail: - write(elem.tail) - -_serialize = { - "xml": _serialize_xml, - "html": _serialize_html, - "text": _serialize_text, -# this optional method is imported at the end of the module -# "c14n": _serialize_c14n, -} - - -def register_namespace(prefix, uri): - """Register a namespace prefix. - - The registry is global, and any existing mapping for either the - given prefix or the namespace URI will be removed. - - *prefix* is the namespace prefix, *uri* is a namespace uri. Tags and - attributes in this namespace will be serialized with prefix if possible. - - ValueError is raised if prefix is reserved or is invalid. - - """ - if re.match(r"ns\d+$", prefix): - raise ValueError("Prefix format reserved for internal use") - for k, v in list(_namespace_map.items()): - if k == uri or v == prefix: - del _namespace_map[k] - _namespace_map[uri] = prefix - -_namespace_map = { - # "well-known" namespace prefixes - "http://www.w3.org/XML/1998/namespace": "xml", - "http://www.w3.org/1999/xhtml": "html", - "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf", - "http://schemas.xmlsoap.org/wsdl/": "wsdl", - # xml schema - "http://www.w3.org/2001/XMLSchema": "xs", - "http://www.w3.org/2001/XMLSchema-instance": "xsi", - # dublin core - "http://purl.org/dc/elements/1.1/": "dc", -} -# For tests and troubleshooting -register_namespace._namespace_map = _namespace_map - -def _raise_serialization_error(text): - raise TypeError( - "cannot serialize %r (type %s)" % (text, type(text).__name__) - ) - -def _escape_cdata(text): - # escape character data - try: - # it's worth avoiding do-nothing calls for strings that are - # shorter than 500 characters, or so. assume that's, by far, - # the most common case in most applications. - if "&" in text: - text = text.replace("&", "&") - if "<" in text: - text = text.replace("<", "<") - if ">" in text: - text = text.replace(">", ">") - return text - except (TypeError, AttributeError): - _raise_serialization_error(text) - -def _escape_attrib(text): - # escape attribute value - try: - if "&" in text: - text = text.replace("&", "&") - if "<" in text: - text = text.replace("<", "<") - if ">" in text: - text = text.replace(">", ">") - if "\"" in text: - text = text.replace("\"", """) - # The following business with carriage returns is to satisfy - # Section 2.11 of the XML specification, stating that - # CR or CR LN should be replaced with just LN - # http://www.w3.org/TR/REC-xml/#sec-line-ends - if "\r\n" in text: - text = text.replace("\r\n", "\n") - if "\r" in text: - text = text.replace("\r", "\n") - #The following four lines are issue 17582 - if "\n" in text: - text = text.replace("\n", " ") - if "\t" in text: - text = text.replace("\t", "	") - return text - except (TypeError, AttributeError): - _raise_serialization_error(text) - -def _escape_attrib_html(text): - # escape attribute value - try: - if "&" in text: - text = text.replace("&", "&") - if ">" in text: - text = text.replace(">", ">") - if "\"" in text: - text = text.replace("\"", """) - return text - except (TypeError, AttributeError): - _raise_serialization_error(text) - -# -------------------------------------------------------------------- - -def tostring(element, encoding=None, method=None, *, - short_empty_elements=True): - """Generate string representation of XML element. - - All subelements are included. If encoding is "unicode", a string - is returned. Otherwise a bytestring is returned. - - *element* is an Element instance, *encoding* is an optional output - encoding defaulting to US-ASCII, *method* is an optional output which can - be one of "xml" (default), "html", "text" or "c14n". - - Returns an (optionally) encoded string containing the XML data. - - """ - stream = io.StringIO() if encoding == 'unicode' else io.BytesIO() - ElementTree(element).write(stream, encoding, method=method, - short_empty_elements=short_empty_elements) - return stream.getvalue() - -class _ListDataStream(io.BufferedIOBase): - """An auxiliary stream accumulating into a list reference.""" - def __init__(self, lst): - self.lst = lst - - def writable(self): - return True - - def seekable(self): - return True - - def write(self, b): - self.lst.append(b) - - def tell(self): - return len(self.lst) - -def tostringlist(element, encoding=None, method=None, *, - short_empty_elements=True): - lst = [] - stream = _ListDataStream(lst) - ElementTree(element).write(stream, encoding, method=method, - short_empty_elements=short_empty_elements) - return lst - - -def dump(elem): - """Write element tree or element structure to sys.stdout. - - This function should be used for debugging only. - - *elem* is either an ElementTree, or a single Element. The exact output - format is implementation dependent. In this version, it's written as an - ordinary XML file. - - """ - # debugging - if not isinstance(elem, ElementTree): - elem = ElementTree(elem) - elem.write(sys.stdout, encoding="unicode") - tail = elem.getroot().tail - if not tail or tail[-1] != "\n": - sys.stdout.write("\n") - -# -------------------------------------------------------------------- -# parsing - - -def parse(source, parser=None): - """Parse XML document into element tree. - - *source* is a filename or file object containing XML data, - *parser* is an optional parser instance defaulting to XMLParser. - - Return an ElementTree instance. - - """ - tree = ElementTree() - tree.parse(source, parser) - return tree - - -def iterparse(source, events=None, parser=None): - """Incrementally parse XML document into ElementTree. - - This class also reports what's going on to the user based on the - *events* it is initialized with. The supported events are the strings - "start", "end", "start-ns" and "end-ns" (the "ns" events are used to get - detailed namespace information). If *events* is omitted, only - "end" events are reported. - - *source* is a filename or file object containing XML data, *events* is - a list of events to report back, *parser* is an optional parser instance. - - Returns an iterator providing (event, elem) pairs. - - """ - # Use the internal, undocumented _parser argument for now; When the - # parser argument of iterparse is removed, this can be killed. - pullparser = XMLPullParser(events=events, _parser=parser) - def iterator(): - try: - while True: - yield from pullparser.read_events() - # load event buffer - data = source.read(16 * 1024) - if not data: - break - pullparser.feed(data) - root = pullparser._close_and_return_root() - yield from pullparser.read_events() - it.root = root - finally: - if close_source: - source.close() - - class IterParseIterator(collections.Iterator): - __next__ = iterator().__next__ - it = IterParseIterator() - it.root = None - del iterator, IterParseIterator - - close_source = False - if not hasattr(source, "read"): - source = open(source, "rb") - close_source = True - - return it - - -class XMLPullParser: - - def __init__(self, events=None, *, _parser=None): - # The _parser argument is for internal use only and must not be relied - # upon in user code. It will be removed in a future release. - # See http://bugs.python.org/issue17741 for more details. - - self._events_queue = collections.deque() - self._parser = _parser or XMLParser(target=TreeBuilder()) - # wire up the parser for event reporting - if events is None: - events = ("end",) - self._parser._setevents(self._events_queue, events) - - def feed(self, data): - """Feed encoded data to parser.""" - if self._parser is None: - raise ValueError("feed() called after end of stream") - if data: - try: - self._parser.feed(data) - except SyntaxError as exc: - self._events_queue.append(exc) - - def _close_and_return_root(self): - # iterparse needs this to set its root attribute properly :( - root = self._parser.close() - self._parser = None - return root - - def close(self): - """Finish feeding data to parser. - - Unlike XMLParser, does not return the root element. Use - read_events() to consume elements from XMLPullParser. - """ - self._close_and_return_root() - - def read_events(self): - """Return an iterator over currently available (event, elem) pairs. - - Events are consumed from the internal event queue as they are - retrieved from the iterator. - """ - events = self._events_queue - while events: - event = events.popleft() - if isinstance(event, Exception): - raise event - else: - yield event - - -def XML(text, parser=None): - """Parse XML document from string constant. - - This function can be used to embed "XML Literals" in Python code. - - *text* is a string containing XML data, *parser* is an - optional parser instance, defaulting to the standard XMLParser. - - Returns an Element instance. - - """ - if not parser: - parser = XMLParser(target=TreeBuilder()) - parser.feed(text) - return parser.close() - - -def XMLID(text, parser=None): - """Parse XML document from string constant for its IDs. - - *text* is a string containing XML data, *parser* is an - optional parser instance, defaulting to the standard XMLParser. - - Returns an (Element, dict) tuple, in which the - dict maps element id:s to elements. - - """ - if not parser: - parser = XMLParser(target=TreeBuilder()) - parser.feed(text) - tree = parser.close() - ids = {} - for elem in tree.iter(): - id = elem.get("id") - if id: - ids[id] = elem - return tree, ids - -# Parse XML document from string constant. Alias for XML(). -fromstring = XML - -def fromstringlist(sequence, parser=None): - """Parse XML document from sequence of string fragments. - - *sequence* is a list of other sequence, *parser* is an optional parser - instance, defaulting to the standard XMLParser. - - Returns an Element instance. - - """ - if not parser: - parser = XMLParser(target=TreeBuilder()) - for text in sequence: - parser.feed(text) - return parser.close() - -# -------------------------------------------------------------------- - - -class TreeBuilder: - """Generic element structure builder. - - This builder converts a sequence of start, data, and end method - calls to a well-formed element structure. - - You can use this class to build an element structure using a custom XML - parser, or a parser for some other XML-like format. - - *element_factory* is an optional element factory which is called - to create new Element instances, as necessary. - - """ - def __init__(self, element_factory=None): - self._data = [] # data collector - self._elem = [] # element stack - self._last = None # last element - self._tail = None # true if we're after an end tag - if element_factory is None: - element_factory = Element - self._factory = element_factory - - def close(self): - """Flush builder buffers and return toplevel document Element.""" - assert len(self._elem) == 0, "missing end tags" - assert self._last is not None, "missing toplevel element" - return self._last - - def _flush(self): - if self._data: - if self._last is not None: - text = "".join(self._data) - if self._tail: - assert self._last.tail is None, "internal error (tail)" - self._last.tail = text - else: - assert self._last.text is None, "internal error (text)" - self._last.text = text - self._data = [] - - def data(self, data): - """Add text to current element.""" - self._data.append(data) - - def start(self, tag, attrs): - """Open new element and return it. - - *tag* is the element name, *attrs* is a dict containing element - attributes. - - """ - self._flush() - self._last = elem = self._factory(tag, attrs) - if self._elem: - self._elem[-1].append(elem) - self._elem.append(elem) - self._tail = 0 - return elem - - def end(self, tag): - """Close and return current Element. - - *tag* is the element name. - - """ - self._flush() - self._last = self._elem.pop() - assert self._last.tag == tag,\ - "end tag mismatch (expected %s, got %s)" % ( - self._last.tag, tag) - self._tail = 1 - return self._last - - -# also see ElementTree and TreeBuilder -class XMLParser: - """Element structure builder for XML source data based on the expat parser. - - *html* are predefined HTML entities (deprecated and not supported), - *target* is an optional target object which defaults to an instance of the - standard TreeBuilder class, *encoding* is an optional encoding string - which if given, overrides the encoding specified in the XML file: - http://www.iana.org/assignments/character-sets - - """ - - def __init__(self, html=0, target=None, encoding=None): - try: - from xml.parsers import expat - except ImportError: - try: - import pyexpat as expat - except ImportError: - raise ImportError( - "No module named expat; use SimpleXMLTreeBuilder instead" - ) - parser = expat.ParserCreate(encoding, "}") - if target is None: - target = TreeBuilder() - # underscored names are provided for compatibility only - self.parser = self._parser = parser - self.target = self._target = target - self._error = expat.error - self._names = {} # name memo cache - # main callbacks - parser.DefaultHandlerExpand = self._default - if hasattr(target, 'start'): - parser.StartElementHandler = self._start - if hasattr(target, 'end'): - parser.EndElementHandler = self._end - if hasattr(target, 'data'): - parser.CharacterDataHandler = target.data - # miscellaneous callbacks - if hasattr(target, 'comment'): - parser.CommentHandler = target.comment - if hasattr(target, 'pi'): - parser.ProcessingInstructionHandler = target.pi - # Configure pyexpat: buffering, new-style attribute handling. - parser.buffer_text = 1 - parser.ordered_attributes = 1 - parser.specified_attributes = 1 - self._doctype = None - self.entity = {} - try: - self.version = "Expat %d.%d.%d" % expat.version_info - except AttributeError: - pass # unknown - - def _setevents(self, events_queue, events_to_report): - # Internal API for XMLPullParser - # events_to_report: a list of events to report during parsing (same as - # the *events* of XMLPullParser's constructor. - # events_queue: a list of actual parsing events that will be populated - # by the underlying parser. - # - parser = self._parser - append = events_queue.append - for event_name in events_to_report: - if event_name == "start": - parser.ordered_attributes = 1 - parser.specified_attributes = 1 - def handler(tag, attrib_in, event=event_name, append=append, - start=self._start): - append((event, start(tag, attrib_in))) - parser.StartElementHandler = handler - elif event_name == "end": - def handler(tag, event=event_name, append=append, - end=self._end): - append((event, end(tag))) - parser.EndElementHandler = handler - elif event_name == "start-ns": - def handler(prefix, uri, event=event_name, append=append): - append((event, (prefix or "", uri or ""))) - parser.StartNamespaceDeclHandler = handler - elif event_name == "end-ns": - def handler(prefix, event=event_name, append=append): - append((event, None)) - parser.EndNamespaceDeclHandler = handler - else: - raise ValueError("unknown event %r" % event_name) - - def _raiseerror(self, value): - err = ParseError(value) - err.code = value.code - err.position = value.lineno, value.offset - raise err - - def _fixname(self, key): - # expand qname, and convert name string to ascii, if possible - try: - name = self._names[key] - except KeyError: - name = key - if "}" in name: - name = "{" + name - self._names[key] = name - return name - - def _start(self, tag, attr_list): - # Handler for expat's StartElementHandler. Since ordered_attributes - # is set, the attributes are reported as a list of alternating - # attribute name,value. - fixname = self._fixname - tag = fixname(tag) - attrib = {} - if attr_list: - for i in range(0, len(attr_list), 2): - attrib[fixname(attr_list[i])] = attr_list[i+1] - return self.target.start(tag, attrib) - - def _end(self, tag): - return self.target.end(self._fixname(tag)) - - def _default(self, text): - prefix = text[:1] - if prefix == "&": - # deal with undefined entities - try: - data_handler = self.target.data - except AttributeError: - return - try: - data_handler(self.entity[text[1:-1]]) - except KeyError: - from xml.parsers import expat - err = expat.error( - "undefined entity %s: line %d, column %d" % - (text, self.parser.ErrorLineNumber, - self.parser.ErrorColumnNumber) - ) - err.code = 11 # XML_ERROR_UNDEFINED_ENTITY - err.lineno = self.parser.ErrorLineNumber - err.offset = self.parser.ErrorColumnNumber - raise err - elif prefix == "<" and text[:9] == "<!DOCTYPE": - self._doctype = [] # inside a doctype declaration - elif self._doctype is not None: - # parse doctype contents - if prefix == ">": - self._doctype = None - return - text = text.strip() - if not text: - return - self._doctype.append(text) - n = len(self._doctype) - if n > 2: - type = self._doctype[1] - if type == "PUBLIC" and n == 4: - name, type, pubid, system = self._doctype - if pubid: - pubid = pubid[1:-1] - elif type == "SYSTEM" and n == 3: - name, type, system = self._doctype - pubid = None - else: - return - if hasattr(self.target, "doctype"): - self.target.doctype(name, pubid, system[1:-1]) - elif self.doctype != self._XMLParser__doctype: - # warn about deprecated call - self._XMLParser__doctype(name, pubid, system[1:-1]) - self.doctype(name, pubid, system[1:-1]) - self._doctype = None - - def doctype(self, name, pubid, system): - """(Deprecated) Handle doctype declaration - - *name* is the Doctype name, *pubid* is the public identifier, - and *system* is the system identifier. - - """ - warnings.warn( - "This method of XMLParser is deprecated. Define doctype() " - "method on the TreeBuilder target.", - DeprecationWarning, - ) - - # sentinel, if doctype is redefined in a subclass - __doctype = doctype - - def feed(self, data): - """Feed encoded data to parser.""" - try: - self.parser.Parse(data, 0) - except self._error as v: - self._raiseerror(v) - - def close(self): - """Finish feeding data to parser and return element structure.""" - try: - self.parser.Parse("", 1) # end of data - except self._error as v: - self._raiseerror(v) - try: - close_handler = self.target.close - except AttributeError: - pass - else: - return close_handler() - finally: - # get rid of circular references - del self.parser, self._parser - del self.target, self._target - - -# Import the C accelerators -try: - # Element is going to be shadowed by the C implementation. We need to keep - # the Python version of it accessible for some "creative" by external code - # (see tests) - _Element_Py = Element - - # Element, SubElement, ParseError, TreeBuilder, XMLParser - from _elementtree import * -except ImportError: - pass diff --git a/modules/language/python/module/xml/etree/__pycache__/ElementInclude.cpython-36.pyc b/modules/language/python/module/xml/etree/__pycache__/ElementInclude.cpython-36.pyc Binary files differdeleted file mode 100644 index 3d32db0..0000000 --- a/modules/language/python/module/xml/etree/__pycache__/ElementInclude.cpython-36.pyc +++ /dev/null diff --git a/modules/language/python/module/xml/etree/__pycache__/ElementPath.cpython-36.pyc b/modules/language/python/module/xml/etree/__pycache__/ElementPath.cpython-36.pyc Binary files differdeleted file mode 100644 index cec585b..0000000 --- a/modules/language/python/module/xml/etree/__pycache__/ElementPath.cpython-36.pyc +++ /dev/null diff --git a/modules/language/python/module/xml/etree/__pycache__/ElementTree.cpython-36.pyc b/modules/language/python/module/xml/etree/__pycache__/ElementTree.cpython-36.pyc Binary files differdeleted file mode 100644 index fadd600..0000000 --- a/modules/language/python/module/xml/etree/__pycache__/ElementTree.cpython-36.pyc +++ /dev/null diff --git a/modules/language/python/module/xml/etree/__pycache__/__init__.cpython-36.pyc b/modules/language/python/module/xml/etree/__pycache__/__init__.cpython-36.pyc Binary files differdeleted file mode 100644 index 40671c9..0000000 --- a/modules/language/python/module/xml/etree/__pycache__/__init__.cpython-36.pyc +++ /dev/null diff --git a/modules/language/python/module/xml/etree/__pycache__/cElementTree.cpython-36.pyc b/modules/language/python/module/xml/etree/__pycache__/cElementTree.cpython-36.pyc Binary files differdeleted file mode 100644 index 1a44430..0000000 --- a/modules/language/python/module/xml/etree/__pycache__/cElementTree.cpython-36.pyc +++ /dev/null |