summaryrefslogtreecommitdiff
path: root/modules/language/python/module/xml/etree
diff options
context:
space:
mode:
authorStefan Israelsson Tampe <stefan.itampe@gmail.com>2019-03-13 09:20:18 +0100
committerStefan Israelsson Tampe <stefan.itampe@gmail.com>2019-03-13 09:20:18 +0100
commit6b0070bb5c37b118eb09c1ec023999bbdf1781e7 (patch)
tree7bbc9df1036b0a7733ea45f3dd74a199929176e1 /modules/language/python/module/xml/etree
parente1bf1a32c8453ea485365e9704e7cb983db3b4bb (diff)
parentdb36b6633b5ccd709eac44635ca88e8683ddb4e3 (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.pycbin1559 -> 0 bytes
-rw-r--r--modules/language/python/module/xml/etree/__pycache__/ElementPath.cpython-36.pycbin6135 -> 0 bytes
-rw-r--r--modules/language/python/module/xml/etree/__pycache__/ElementTree.cpython-36.pycbin44728 -> 0 bytes
-rw-r--r--modules/language/python/module/xml/etree/__pycache__/__init__.cpython-36.pycbin123 -> 0 bytes
-rw-r--r--modules/language/python/module/xml/etree/__pycache__/cElementTree.cpython-36.pycbin165 -> 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("&", "&amp;")
- if "<" in text:
- text = text.replace("<", "&lt;")
- if ">" in text:
- text = text.replace(">", "&gt;")
- return text
- except (TypeError, AttributeError):
- _raise_serialization_error(text)
-
-def _escape_attrib(text):
- # escape attribute value
- try:
- if "&" in text:
- text = text.replace("&", "&amp;")
- if "<" in text:
- text = text.replace("<", "&lt;")
- if ">" in text:
- text = text.replace(">", "&gt;")
- if "\"" in text:
- text = text.replace("\"", "&quot;")
- # 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", "&#10;")
- if "\t" in text:
- text = text.replace("\t", "&#09;")
- return text
- except (TypeError, AttributeError):
- _raise_serialization_error(text)
-
-def _escape_attrib_html(text):
- # escape attribute value
- try:
- if "&" in text:
- text = text.replace("&", "&amp;")
- if ">" in text:
- text = text.replace(">", "&gt;")
- if "\"" in text:
- text = text.replace("\"", "&quot;")
- 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
deleted file mode 100644
index 3d32db0..0000000
--- a/modules/language/python/module/xml/etree/__pycache__/ElementInclude.cpython-36.pyc
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index cec585b..0000000
--- a/modules/language/python/module/xml/etree/__pycache__/ElementPath.cpython-36.pyc
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index fadd600..0000000
--- a/modules/language/python/module/xml/etree/__pycache__/ElementTree.cpython-36.pyc
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index 40671c9..0000000
--- a/modules/language/python/module/xml/etree/__pycache__/__init__.cpython-36.pyc
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index 1a44430..0000000
--- a/modules/language/python/module/xml/etree/__pycache__/cElementTree.cpython-36.pyc
+++ /dev/null
Binary files differ