diff options
author | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2012-08-03 15:38:17 -0400 |
---|---|---|
committer | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2012-08-03 15:38:27 -0400 |
commit | 913d320ee02d5e16b61a14d97b2b1111d307d0d3 (patch) | |
tree | 64411709ef9a914016ad2f6c1f8146b92e2a5d3b /src/lib | |
parent | fc296f452029120c79c25444195f346855ed6dde (diff) | |
download | bcfg2-913d320ee02d5e16b61a14d97b2b1111d307d0d3.tar.gz bcfg2-913d320ee02d5e16b61a14d97b2b1111d307d0d3.tar.bz2 bcfg2-913d320ee02d5e16b61a14d97b2b1111d307d0d3.zip |
removed Bcfg2.Client.XML abstraction layer since we depend directly on lxml.etree
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Bcfg2/Client/Frame.py | 16 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/APT.py | 7 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Chkconfig.py | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/DebInit.py | 3 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/POSIX.py | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/RPMng.py | 27 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/RcUpdate.py | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/SELinux.py | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/SMF.py | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/SYSV.py | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Systemd.py | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Upstart.py | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/YUM24.py | 10 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/YUMng.py | 38 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/__init__.py | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/launchd.py | 10 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/XML.py | 36 |
17 files changed, 78 insertions, 112 deletions
diff --git a/src/lib/Bcfg2/Client/Frame.py b/src/lib/Bcfg2/Client/Frame.py index b456738d0..829d8967e 100644 --- a/src/lib/Bcfg2/Client/Frame.py +++ b/src/lib/Bcfg2/Client/Frame.py @@ -472,12 +472,12 @@ class Frame: def GenerateStats(self): """Generate XML summary of execution statistics.""" - feedback = Bcfg2.Client.XML.Element("upload-statistics") - stats = Bcfg2.Client.XML.SubElement(feedback, - 'Statistics', - total=str(len(self.states)), - version='2.0', - revision=self.config.get('revision', '-1')) + feedback = lxml.etree.Element("upload-statistics") + stats = lxml.etree.SubElement(feedback, + 'Statistics', + total=str(len(self.states)), + version='2.0', + revision=self.config.get('revision', '-1')) good_entries = [key for key, val in list(self.states.items()) if val] good = len(good_entries) stats.set('good', str(good)) @@ -491,13 +491,13 @@ class Frame: (good_entries, "Good"), ([entry for entry in self.states if not \ self.states[entry]], "Bad")]: - container = Bcfg2.Client.XML.SubElement(stats, ename) + container = lxml.etree.SubElement(stats, ename) for item in data: item.set('qtext', '') container.append(item) item.text = None - timeinfo = Bcfg2.Client.XML.Element("OpStamps") + timeinfo = lxml.etree.Element("OpStamps") feedback.append(stats) for (event, timestamp) in list(self.times.items()): timeinfo.set(event, str(timestamp)) diff --git a/src/lib/Bcfg2/Client/Tools/APT.py b/src/lib/Bcfg2/Client/Tools/APT.py index ce7e9701f..c012e9746 100644 --- a/src/lib/Bcfg2/Client/Tools/APT.py +++ b/src/lib/Bcfg2/Client/Tools/APT.py @@ -7,6 +7,7 @@ warnings.filterwarnings("ignore", "apt API not stable yet", import apt.cache import os import Bcfg2.Client.Tools +import lxml.etree class APT(Bcfg2.Client.Tools.Tool): """The Debian toolset implements package and service operations and inherits @@ -83,9 +84,9 @@ class APT(Bcfg2.Client.Tools.Tool): else: extras = [(p.name, p.installedVersion) for p in self.pkg_cache if p.isInstalled and p.name not in packages] - return [Bcfg2.Client.XML.Element('Package', name=name, \ - type='deb', version=version) \ - for (name, version) in extras] + return [lxml.etree.Element('Package', name=name, + type='deb', version=version) + for (name, version) in extras] def VerifyDebsums(self, entry, modlist): output = self.cmd.run("%s -as %s" % (self.debsums, diff --git a/src/lib/Bcfg2/Client/Tools/Chkconfig.py b/src/lib/Bcfg2/Client/Tools/Chkconfig.py index 0169b12da..9d104e2b0 100644 --- a/src/lib/Bcfg2/Client/Tools/Chkconfig.py +++ b/src/lib/Bcfg2/Client/Tools/Chkconfig.py @@ -5,7 +5,7 @@ import os import Bcfg2.Client.Tools -import Bcfg2.Client.XML +import lxml.etree class Chkconfig(Bcfg2.Client.Tools.SvcTool): @@ -86,7 +86,7 @@ class Chkconfig(Bcfg2.Client.Tools.SvcTool): self.logger.debug('Found active services:') self.logger.debug(allsrv) specified = [srv.get('name') for srv in self.getSupportedEntries()] - return [Bcfg2.Client.XML.Element('Service', - type='chkconfig', - name=name) \ + return [lxml.etree.Element('Service', + type='chkconfig', + name=name) for name in allsrv if name not in specified] diff --git a/src/lib/Bcfg2/Client/Tools/DebInit.py b/src/lib/Bcfg2/Client/Tools/DebInit.py index 7d5af1127..f52ca9949 100644 --- a/src/lib/Bcfg2/Client/Tools/DebInit.py +++ b/src/lib/Bcfg2/Client/Tools/DebInit.py @@ -3,6 +3,7 @@ import glob import os import re +import lxml.etree import Bcfg2.Client.Tools # Debian squeeze and beyond uses a dependecy based boot sequence @@ -107,7 +108,7 @@ class DebInit(Bcfg2.Client.Tools.SvcTool): if self.svcre.match(fname).group('name') not in specified]: if name not in extra: extra.append(name) - return [Bcfg2.Client.XML.Element('Service', name=name, type='deb') for name \ + return [lxml.etree.Element('Service', name=name, type='deb') for name \ in extra] def Remove(self, _): diff --git a/src/lib/Bcfg2/Client/Tools/POSIX.py b/src/lib/Bcfg2/Client/Tools/POSIX.py index 64ea1b3e8..660ed51eb 100644 --- a/src/lib/Bcfg2/Client/Tools/POSIX.py +++ b/src/lib/Bcfg2/Client/Tools/POSIX.py @@ -12,13 +12,13 @@ import shutil import stat import sys import time +import lxml.etree # py3k compatibility if sys.hexversion >= 0x03000000: unicode = str import Bcfg2.Client.Tools import Bcfg2.Options -from Bcfg2.Client import XML log = logging.getLogger(__name__) @@ -521,7 +521,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): entry.get('name') nqtext += ":".join(ex_ents) entry.set('qtext', nqtext) - [entry.append(XML.Element('Prune', path=x)) + [entry.append(lxml.etree.Element('Prune', path=x)) for x in ex_ents] except OSError: ex_ents = [] diff --git a/src/lib/Bcfg2/Client/Tools/RPMng.py b/src/lib/Bcfg2/Client/Tools/RPMng.py index 91e2180ae..a7fbc0036 100644 --- a/src/lib/Bcfg2/Client/Tools/RPMng.py +++ b/src/lib/Bcfg2/Client/Tools/RPMng.py @@ -1,8 +1,9 @@ """Bcfg2 Support for RPMS""" -import os.path +import os import rpm import rpmtools +import lxml.etree import Bcfg2.Client.Tools class RPMng(Bcfg2.Client.Tools.PkgTool): @@ -148,7 +149,7 @@ class RPMng(Bcfg2.Client.Tools.PkgTool): instances = [inst for inst in entry if inst.tag == 'Instance' or inst.tag == 'Package'] if instances == []: # We have an old style no Instance entry. Convert it to new style. - instance = Bcfg2.Client.XML.SubElement(entry, 'Package') + instance = lxml.etree.SubElement(entry, 'Package') for attrib in list(entry.attrib.keys()): instance.attrib[attrib] = entry.attrib[attrib] if (self.pkg_checks and @@ -849,14 +850,14 @@ class RPMng(Bcfg2.Client.Tools.PkgTool): for (name, instances) in list(self.installed.items()): if name not in packages: - extra_entry = Bcfg2.Client.XML.Element('Package', name=name, type=self.pkgtype) + extra_entry = lxml.etree.Element('Package', name=name, type=self.pkgtype) for installed_inst in instances: if self.setup['extra']: self.logger.info("Extra Package %s %s." % \ (name, self.str_evra(installed_inst))) - tmp_entry = Bcfg2.Client.XML.SubElement(extra_entry, 'Instance', \ - version = installed_inst.get('version'), \ - release = installed_inst.get('release')) + tmp_entry = lxml.etree.SubElement(extra_entry, 'Instance', + version = installed_inst.get('version'), + release = installed_inst.get('release')) if installed_inst.get('epoch', None) != None: tmp_entry.set('epoch', str(installed_inst.get('epoch'))) if installed_inst.get('arch', None) != None: @@ -873,7 +874,7 @@ class RPMng(Bcfg2.Client.Tools.PkgTool): """ name = pkg_entry.get('name') - extra_entry = Bcfg2.Client.XML.Element('Package', name=name, type=self.pkgtype) + extra_entry = lxml.etree.Element('Package', name=name, type=self.pkgtype) instances = [inst for inst in pkg_entry if inst.tag == 'Instance' or inst.tag == 'Package'] if name in self.installOnlyPkgs: for installed_inst in installed_entry: @@ -887,9 +888,9 @@ class RPMng(Bcfg2.Client.Tools.PkgTool): # Extra package. self.logger.info("Extra InstallOnlyPackage %s %s." % \ (name, self.str_evra(installed_inst))) - tmp_entry = Bcfg2.Client.XML.SubElement(extra_entry, 'Instance', \ - version = installed_inst.get('version'), \ - release = installed_inst.get('release')) + tmp_entry = lxml.etree.SubElement(extra_entry, 'Instance', + version = installed_inst.get('version'), + release = installed_inst.get('release')) if installed_inst.get('epoch', None) != None: tmp_entry.set('epoch', str(installed_inst.get('epoch'))) if installed_inst.get('arch', None) != None: @@ -906,9 +907,9 @@ class RPMng(Bcfg2.Client.Tools.PkgTool): if not_found: self.logger.info("Extra Normal Package Instance %s %s" % \ (name, self.str_evra(installed_inst))) - tmp_entry = Bcfg2.Client.XML.SubElement(extra_entry, 'Instance', \ - version = installed_inst.get('version'), \ - release = installed_inst.get('release')) + tmp_entry = lxml.etree.SubElement(extra_entry, 'Instance', + version = installed_inst.get('version'), + release = installed_inst.get('release')) if installed_inst.get('epoch', None) != None: tmp_entry.set('epoch', str(installed_inst.get('epoch'))) if installed_inst.get('arch', None) != None: diff --git a/src/lib/Bcfg2/Client/Tools/RcUpdate.py b/src/lib/Bcfg2/Client/Tools/RcUpdate.py index ddf9c1f2d..e2d7ccfb5 100644 --- a/src/lib/Bcfg2/Client/Tools/RcUpdate.py +++ b/src/lib/Bcfg2/Client/Tools/RcUpdate.py @@ -2,7 +2,7 @@ import os import Bcfg2.Client.Tools -import Bcfg2.Client.XML +import lxml.etree class RcUpdate(Bcfg2.Client.Tools.SvcTool): @@ -77,7 +77,7 @@ class RcUpdate(Bcfg2.Client.Tools.SvcTool): self.logger.debug('Found active services:') self.logger.debug(allsrv) specified = [srv.get('name') for srv in self.getSupportedEntries()] - return [Bcfg2.Client.XML.Element('Service', - type='rc-update', - name=name) \ + return [lxml.etree.Element('Service', + type='rc-update', + name=name) for name in allsrv if name not in specified] diff --git a/src/lib/Bcfg2/Client/Tools/SELinux.py b/src/lib/Bcfg2/Client/Tools/SELinux.py index 1c0db904b..7785f3dfa 100644 --- a/src/lib/Bcfg2/Client/Tools/SELinux.py +++ b/src/lib/Bcfg2/Client/Tools/SELinux.py @@ -7,7 +7,7 @@ import struct import socket import selinux import seobject -import Bcfg2.Client.XML +import lxml.etree import Bcfg2.Client.Tools import Bcfg2.Client.Tools.POSIX @@ -227,7 +227,7 @@ class SELinuxEntryHandler(object): def key2entry(self, key): attrs = self._key2attrs(key) attrs["type"] = self.etype - return Bcfg2.Client.XML.Element("SELinux", **attrs) + return lxml.etree.Element("SELinux", **attrs) def _args(self, entry, method): if hasattr(self, "_%sargs" % method): diff --git a/src/lib/Bcfg2/Client/Tools/SMF.py b/src/lib/Bcfg2/Client/Tools/SMF.py index 3e0a9da13..fd9747b92 100644 --- a/src/lib/Bcfg2/Client/Tools/SMF.py +++ b/src/lib/Bcfg2/Client/Tools/SMF.py @@ -2,7 +2,7 @@ import glob import os - +import lxml.etree import Bcfg2.Client.Tools @@ -128,5 +128,5 @@ class SMF(Bcfg2.Client.Tools.SvcTool): [allsrv.remove(svc.get('FMRI')) for svc in self.getSupportedEntries() \ if svc.get("FMRI") in allsrv] - return [Bcfg2.Client.XML.Element("Service", type='smf', name=name) \ + return [lxml.etree.Element("Service", type='smf', name=name) \ for name in allsrv] diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index eb4a13dfb..4b83e985c 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -3,7 +3,7 @@ import tempfile import Bcfg2.Client.Tools -import Bcfg2.Client.XML +import lxml.etree noask = ''' diff --git a/src/lib/Bcfg2/Client/Tools/Systemd.py b/src/lib/Bcfg2/Client/Tools/Systemd.py index a295bc608..b35bff46a 100644 --- a/src/lib/Bcfg2/Client/Tools/Systemd.py +++ b/src/lib/Bcfg2/Client/Tools/Systemd.py @@ -3,7 +3,6 @@ """This is systemd support.""" import Bcfg2.Client.Tools -import Bcfg2.Client.XML class Systemd(Bcfg2.Client.Tools.SvcTool): """Systemd support for Bcfg2.""" diff --git a/src/lib/Bcfg2/Client/Tools/Upstart.py b/src/lib/Bcfg2/Client/Tools/Upstart.py index aa5a921a6..ef44fb5fb 100644 --- a/src/lib/Bcfg2/Client/Tools/Upstart.py +++ b/src/lib/Bcfg2/Client/Tools/Upstart.py @@ -4,7 +4,7 @@ import glob import re import Bcfg2.Client.Tools -import Bcfg2.Client.XML +import lxml.etree class Upstart(Bcfg2.Client.Tools.SvcTool): @@ -84,5 +84,5 @@ class Upstart(Bcfg2.Client.Tools.SvcTool): glob.glob("/etc/init/*.conf") \ if self.svcre.match(fname).group('name') not in specified]: extra.append(name) - return [Bcfg2.Client.XML.Element('Service', type='upstart', name=name) \ + return [lxml.etree.Element('Service', type='upstart', name=name) \ for name in extra] diff --git a/src/lib/Bcfg2/Client/Tools/YUM24.py b/src/lib/Bcfg2/Client/Tools/YUM24.py index 2bc821db3..a2957243b 100644 --- a/src/lib/Bcfg2/Client/Tools/YUM24.py +++ b/src/lib/Bcfg2/Client/Tools/YUM24.py @@ -4,7 +4,7 @@ import copy import os.path import sys import yum -import Bcfg2.Client.XML +import lxml.etree import Bcfg2.Client.Tools.RPMng if not hasattr(Bcfg2.Client.Tools.RPMng, 'RPMng'): @@ -113,10 +113,10 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): # installed but out of date data.update(self.yum_avail[entry.get('name')]) for (arch, (epoch, vers, rel)) in list(data.items()): - x = Bcfg2.Client.XML.SubElement(entry, "Instance", - name=entry.get('name'), - version=vers, arch=arch, - release=rel, epoch=epoch) + x = lxml.etree.SubElement(entry, "Instance", + name=entry.get('name'), + version=vers, arch=arch, + release=rel, epoch=epoch) if 'verify_flags' in entry.attrib: x.set('verify_flags', entry.get('verify_flags')) if 'verify' in entry.attrib: diff --git a/src/lib/Bcfg2/Client/Tools/YUMng.py b/src/lib/Bcfg2/Client/Tools/YUMng.py index 34029b9fe..230ff4603 100644 --- a/src/lib/Bcfg2/Client/Tools/YUMng.py +++ b/src/lib/Bcfg2/Client/Tools/YUMng.py @@ -10,7 +10,7 @@ import yum.callbacks import yum.Errors import yum.misc import rpmUtils.arch -import Bcfg2.Client.XML +import lxml.etree import Bcfg2.Client.Tools def build_yname(pkgname, inst): @@ -239,10 +239,10 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): # installed but out of date data.update(self.yum_avail[entry.get('name')]) for (arch, (epoch, vers, rel)) in list(data.items()): - x = Bcfg2.Client.XML.SubElement(entry, "Instance", - name=entry.get('name'), - version=vers, arch=arch, - release=rel, epoch=epoch) + x = lxml.etree.SubElement(entry, "Instance", + name=entry.get('name'), + version=vers, arch=arch, + release=rel, epoch=epoch) if 'verify_flags' in entry.attrib: x.set('verify_flags', entry.get('verify_flags')) if 'verify' in entry.attrib: @@ -257,7 +257,7 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): if instances == []: # We have an old style no Instance entry. Convert it to new style. - instance = Bcfg2.Client.XML.SubElement(entry, 'Package') + instance = lxml.etree.SubElement(entry, 'Package') for attrib in list(entry.attrib.keys()): instance.attrib[attrib] = entry.attrib[attrib] instances = [instance] @@ -626,8 +626,8 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): if len(POs) == 0: return None name = entry.get('name') - extra_entry = Bcfg2.Client.XML.Element('Package', name=name, - type=self.pkgtype) + extra_entry = lxml.etree.Element('Package', name=name, + type=self.pkgtype) instances = self._buildInstances(entry) _POs = [p for p in POs] # Shallow copy @@ -647,9 +647,9 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): for p in _POs: self.logger.debug(" Extra Instance Found: %s" % str(p)) - Bcfg2.Client.XML.SubElement(extra_entry, 'Instance', - epoch=p.epoch, name=p.name, version=p.version, - release=p.release, arch=p.arch) + lxml.etree.SubElement(extra_entry, 'Instance', + epoch=p.epoch, name=p.name, version=p.version, + release=p.release, arch=p.arch) if _POs == []: return None @@ -663,15 +663,15 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): for p in list(self.installed.keys()): if p not in packages: - entry = Bcfg2.Client.XML.Element('Package', name=p, - type=self.pkgtype) + entry = lxml.etree.Element('Package', name=p, + type=self.pkgtype) for i in self.installed[p]: - inst = Bcfg2.Client.XML.SubElement(entry, - 'Instance', - epoch=i['epoch'], - version=i['version'], - release=i['release'], - arch=i['arch']) + inst = lxml.etree.SubElement(entry, + 'Instance', + epoch=i['epoch'], + version=i['version'], + release=i['release'], + arch=i['arch']) extras.append(entry) diff --git a/src/lib/Bcfg2/Client/Tools/__init__.py b/src/lib/Bcfg2/Client/Tools/__init__.py index e4a0ec220..164a1eaeb 100644 --- a/src/lib/Bcfg2/Client/Tools/__init__.py +++ b/src/lib/Bcfg2/Client/Tools/__init__.py @@ -5,7 +5,7 @@ import sys from subprocess import Popen, PIPE import time -import Bcfg2.Client.XML +import lxml.etree from Bcfg2.Bcfg2Py3k import input __all__ = [tool.split('.')[0] \ @@ -290,9 +290,9 @@ class PkgTool(Tool): packages = [entry.get('name') for entry in self.getSupportedEntries()] extras = [data for data in list(self.installed.items()) \ if data[0] not in packages] - return [Bcfg2.Client.XML.Element('Package', name=name, \ - type=self.pkgtype, version=version) \ - for (name, version) in extras] + return [lxml.etree.Element('Package', name=name, + type=self.pkgtype, version=version) + for (name, version) in extras] class SvcTool(Tool): diff --git a/src/lib/Bcfg2/Client/Tools/launchd.py b/src/lib/Bcfg2/Client/Tools/launchd.py index 6f08559a2..dc817c89b 100644 --- a/src/lib/Bcfg2/Client/Tools/launchd.py +++ b/src/lib/Bcfg2/Client/Tools/launchd.py @@ -1,7 +1,7 @@ """launchd support for Bcfg2.""" import os - +import lxml.etree import Bcfg2.Client.Tools @@ -114,10 +114,10 @@ class launchd(Bcfg2.Client.Tools.Tool): [allsrv.remove(svc) for svc in [entry.get("name") for entry in self.getSupportedEntries()] if svc in allsrv] - return [Bcfg2.Client.XML.Element("Service", - type='launchd', - name=name, - status='on') for name in allsrv] + return [lxml.etree.Element("Service", + type='launchd', + name=name, + status='on') for name in allsrv] def BundleUpdated(self, bundle, states): """Reload launchd plist.""" diff --git a/src/lib/Bcfg2/Client/XML.py b/src/lib/Bcfg2/Client/XML.py deleted file mode 100644 index 858479611..000000000 --- a/src/lib/Bcfg2/Client/XML.py +++ /dev/null @@ -1,36 +0,0 @@ -'''XML lib compatibility layer for the Bcfg2 client''' - -# library will use lxml, then builtin xml.etree, then ElementTree - -try: - from lxml.etree import Element, SubElement, XML, tostring - from lxml.etree import XMLSyntaxError as ParseError - driver = 'lxml' -except ImportError: - # lxml not available - from xml.parsers.expat import ExpatError as ParseError - try: - import xml.etree.ElementTree - Element = xml.etree.ElementTree.Element - SubElement = xml.etree.ElementTree.SubElement - XML = xml.etree.ElementTree.XML - def tostring(e, encoding=None, xml_declaration=None): - return xml.etree.ElementTree.tostring(e, encoding=encoding) - driver = 'etree-py' - except ImportError: - try: - from elementtree.ElementTree import Element, SubElement, XML, tostring - driver = 'etree' - import elementtree.ElementTree - Element = elementtree.ElementTree.Element - SubElement = elementtree.ElementTree.SubElement - XML = elementtree.ElementTree.XML - def tostring(e, encoding=None, xml_declaration=None): - return elementtree.ElementTree.tostring(e) - - except ImportError: - print("Failed to load lxml, xml.etree and elementtree.ElementTree") - print("Cannot continue") - raise SystemExit(1) - -len([Element, SubElement, XML, tostring, ParseError]) |