diff --git a/README.rst b/README.rst
index f00ca0e7b484b89f44f66653ae5517d8d066187a..c9004316fe791162356fe3edc2547817b2888998 100644
--- a/README.rst
+++ b/README.rst
@@ -141,6 +141,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 Change history
 --------------
 
+Version 2.29.4 (12/14/2017)
+
+- Fix for exporting the child of an element, when that child is
+  declared as an instance of an abstract type (abstract="true" in
+  the schema).  When exporting, the type of the child needs to be
+  determine at runtime through polymorphism.  This fix prevents the
+  containing (parent) object from passing the name of the abstract
+  class to the instance of the concrete class when calling its
+  export function.  Thanks to Rob Calvert for reporting this and for
+  his analysis that helped me understand the problem.
+
 Version 2.29.3 (12/11/2017)
 
 - Resolved an issue with a type casting problem that occurs when a
diff --git a/generateDS.html b/generateDS.html
index 1dcd6c3c2f4625f65a7389f80378b50a3fce96fd..0184ba9eed0f4d87f068aa4e42ced4e6adb25173 100644
--- a/generateDS.html
+++ b/generateDS.html
@@ -220,7 +220,7 @@ They are used by updateversion.py. -->
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.3</td>
+<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.4</td>
 </tr>
 </tbody>
 </table>
@@ -229,7 +229,7 @@ They are used by updateversion.py. -->
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">date:</th><td class="field-body">December 11, 2017</td>
+<tr class="field"><th class="field-name">date:</th><td class="field-body">December 14, 2017</td>
 </tr>
 </tbody>
 </table>
@@ -3380,7 +3380,7 @@ following among others:</p>
 <div class="footer">
 <hr class="footer" />
 <a class="reference external" href="generateDS.txt">View document source</a>.
-Generated on: 2017-12-11 21:49 UTC.
+Generated on: 2017-12-14 22:46 UTC.
 Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
 
 </div>
diff --git a/generateDS.py b/generateDS.py
index 146f8a07b0e0f68074ba746743da0af03eb1954f..bfe6ae7da92c07d9a948c80f5287e0e36ced437a 100755
--- a/generateDS.py
+++ b/generateDS.py
@@ -229,7 +229,7 @@ logging.disable(logging.INFO)
 # Do not modify the following VERSION comments.
 # Used by updateversion.py.
 ##VERSION##
-VERSION = '2.29.3'
+VERSION = '2.29.4'
 ##VERSION##
 
 BaseStrTypes = six.string_types
@@ -2751,14 +2751,14 @@ def generateExportChildren(wrt, element, hasChildren, namespace):
                     wrt("%sfor %s_ in self.%s:\n" % (
                         fill, name, name,))
                     wrt("%s    %s_.export(outfile, level, namespace_, "
-                        "name_='%s', pretty_print=pretty_print)\n" % (
-                            fill, name, unmappedName, ))
+                        "pretty_print=pretty_print)\n" % (
+                            fill, name, ))
                 elif abstract_child:
                     wrt("%sif self.%s is not None:\n" % (fill, name, ))
                     wrt("%s    self.%s.export(outfile, level, "
-                        "namespace_, name_='%s', "
+                        "namespace_, "
                         "pretty_print=pretty_print)\n" % (
-                            fill, name, unmappedName, ))
+                            fill, name, ))
                 elif child.getMaxOccurs() > 1:
                     generateExportFn_2(
                         wrt, child, unmappedName, namespace, '    ')
@@ -5051,6 +5051,18 @@ else:
 #xmldisable#    doc = etree_.parse(infile, parser=parser, **kwargs)
 #xmldisable#    return doc
 
+#xmldisable#def parsexmlstring_(instring, parser=None, **kwargs):
+#xmldisable#    if parser is None:
+#xmldisable#        # Use the lxml ElementTree compatible parser so that, e.g.,
+#xmldisable#        #   we ignore comments.
+#xmldisable#        try:
+#xmldisable#            parser = etree_.ETCompatXMLParser()
+#xmldisable#        except AttributeError:
+#xmldisable#            # fallback to xml.etree
+#xmldisable#            parser = etree_.XMLParser()
+#xmldisable#    element = etree_.fromstring(instring, parser=parser, **kwargs)
+#xmldisable#    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -5879,12 +5891,15 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
-%(preserve_cdata_tags)s    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
+%(preserve_cdata_tags)s    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = '%(rootElement)s'
@@ -5892,7 +5907,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 #silence#    if not silence:
 #silence#        sys.stdout.write('<?xml version="1.0" ?>\\n')
 #silence#        rootObj.export(
diff --git a/generateDS.txt b/generateDS.txt
index 9d1961ba03af3beea5c0f9c8e434b5f24feb31a1..608888fa407f30f005a6eaf2dcac5d58fcf78309 100644
--- a/generateDS.txt
+++ b/generateDS.txt
@@ -12,7 +12,7 @@ generateDS -- Generate Data Structures from XML Schema
 
 .. version
 
-:revision: 2.29.3
+:revision: 2.29.4
 
 .. version
 
diff --git a/generateds_gui_notes.html b/generateds_gui_notes.html
index 0c269e45ed3436349f7b4fdb8bcb0669fe86e37c..576b4823901a7286063de69e5c341426a248f164 100644
--- a/generateds_gui_notes.html
+++ b/generateds_gui_notes.html
@@ -220,7 +220,7 @@ They are used by updateversion.py. -->
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.3</td>
+<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.4</td>
 </tr>
 </tbody>
 </table>
@@ -229,7 +229,7 @@ They are used by updateversion.py. -->
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">date:</th><td class="field-body">December 11, 2017</td>
+<tr class="field"><th class="field-name">date:</th><td class="field-body">December 14, 2017</td>
 </tr>
 </tbody>
 </table>
@@ -401,7 +401,7 @@ $ mv generateds_gui.mo locale/ru/LC_MESSAGES/
 <div class="footer">
 <hr class="footer" />
 <a class="reference external" href="generateds_gui_notes.txt">View document source</a>.
-Generated on: 2017-12-11 21:49 UTC.
+Generated on: 2017-12-14 22:46 UTC.
 Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
 
 </div>
diff --git a/generateds_gui_notes.txt b/generateds_gui_notes.txt
index a45bea962aacc6c12e734273558e801ec948d88a..59a6d69929b7e2d94a16fcfebe3acfa403bb6eb9 100644
--- a/generateds_gui_notes.txt
+++ b/generateds_gui_notes.txt
@@ -12,7 +12,7 @@ GenerateDS GUI Notes
 
 .. version
 
-:revision: 2.29.3
+:revision: 2.29.4
 
 .. version
 
diff --git a/gui/generateds_gui.py b/gui/generateds_gui.py
index acf8ee3212ca695557768524115729e410159ad2..4e13f9014b955ae5e2764adc18f6d5af7df9e1bb 100644
--- a/gui/generateds_gui.py
+++ b/gui/generateds_gui.py
@@ -41,7 +41,7 @@ from libgenerateDS.gui import generateds_gui_session
 # Do not modify the following VERSION comments.
 # Used by updateversion.py.
 ##VERSION##
-VERSION = '2.29.3'
+VERSION = '2.29.4'
 ##VERSION##
 
 
diff --git a/librarytemplate_howto.html b/librarytemplate_howto.html
index 5897afcea7510fb78d152564159714f14c99a0c4..0dff031ed8cd9ef36ac318baea9fdc1e05c7b222 100644
--- a/librarytemplate_howto.html
+++ b/librarytemplate_howto.html
@@ -217,7 +217,7 @@ dkuhlman (at) davekuhlman (dot) org
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.3</td>
+<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.4</td>
 </tr>
 </tbody>
 </table>
@@ -226,7 +226,7 @@ dkuhlman (at) davekuhlman (dot) org
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">date:</th><td class="field-body">December 11, 2017</td>
+<tr class="field"><th class="field-name">date:</th><td class="field-body">December 14, 2017</td>
 </tr>
 </tbody>
 </table>
@@ -380,7 +380,7 @@ this command for your needs.  For example, you may need to use
 <div class="footer">
 <hr class="footer" />
 <a class="reference external" href="librarytemplate_howto.txt">View document source</a>.
-Generated on: 2017-12-11 21:49 UTC.
+Generated on: 2017-12-14 22:46 UTC.
 Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
 
 </div>
diff --git a/librarytemplate_howto.txt b/librarytemplate_howto.txt
index 051534981e3c389e5fd016849d7a507ff997fc28..702e57190902bc0b975802f2d3cf5bd4376f78d1 100644
--- a/librarytemplate_howto.txt
+++ b/librarytemplate_howto.txt
@@ -8,7 +8,7 @@ How to package a generateDS.py generated library
 
 .. version
 
-:revision: 2.29.3
+:revision: 2.29.4
 
 .. version
 
diff --git a/process_includes.py b/process_includes.py
index 8568033984079038722c1ed347a3a51040ae4d90..723639a1b42cb1469423a51b7a341eef80036311 100644
--- a/process_includes.py
+++ b/process_includes.py
@@ -40,7 +40,7 @@ except ImportError:
 # Do not modify the following VERSION comments.
 # Used by updateversion.py.
 ##VERSION##
-VERSION = '2.29.3'
+VERSION = '2.29.4'
 ##VERSION##
 
 CatalogDict = {}
diff --git a/setup.py b/setup.py
index da910b9b68a6d921aa9e0c71b2a5d712e86bcc58..93eeec3cd2ecd5f131b6121fdb7cffbc67caf0ef 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@ setup(name="generateDS",
 # Do not modify the following VERSION comments.
 # Used by updateversion.py.
 ##VERSION##
-    version="2.29.3",
+    version="2.29.4",
 ##VERSION##
     author="Dave Kuhlman",
     author_email="dkuhlman@davekuhlman.org",
diff --git a/tests/OnePer/oneperType00_2One.py b/tests/OnePer/oneperType00_2One.py
index 2bd2128cf3beb38f49a9f508348bcba0519c5d53..1ffccc37012a5bc7491676ebb9a1f943ee9e6cb8 100644
--- a/tests/OnePer/oneperType00_2One.py
+++ b/tests/OnePer/oneperType00_2One.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -869,13 +881,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'oneperType00_1'
@@ -883,7 +898,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/OnePer/oneperType01_2One.py b/tests/OnePer/oneperType01_2One.py
index f22521e3cbd850c7c2de151eee805f0cd772eb56..f5a426785df579d9b21a8677b13f55f27e3a5ca5 100644
--- a/tests/OnePer/oneperType01_2One.py
+++ b/tests/OnePer/oneperType01_2One.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -946,13 +958,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'oneperType01_1'
@@ -960,7 +975,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/OnePer/oneperType02_2One.py b/tests/OnePer/oneperType02_2One.py
index b7f4e2439e785ff0a34ad886ed72d7aafe3302e8..6c37be00d342bb1760475e2a43f908f6b79dc0db 100644
--- a/tests/OnePer/oneperType02_2One.py
+++ b/tests/OnePer/oneperType02_2One.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -946,13 +958,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'oneperType02_1'
@@ -960,7 +975,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/OnePer/oneperType03_2One.py b/tests/OnePer/oneperType03_2One.py
index a240d227e09a385cb5d5b32e0a9a09b647bf01c5..5b825bedc4e8a640b7f0b578918dc19bb8840eca 100644
--- a/tests/OnePer/oneperType03_2One.py
+++ b/tests/OnePer/oneperType03_2One.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -946,13 +958,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'oneperType03_1'
@@ -960,7 +975,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/abstract_type1_sup.py b/tests/abstract_type1_sup.py
index af44aab5aa1ed68c68e20e53c9d914ba6d2db9f7..8f617deb6e71d0637aeb0c3bfdc6450c06d0770b 100644
--- a/tests/abstract_type1_sup.py
+++ b/tests/abstract_type1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -774,7 +786,7 @@ class carrierType(GeneratedsSuper):
         else:
             eol_ = ''
         for fleet_ in self.fleet:
-            fleet_.export(outfile, level, namespace_, name_='fleet', pretty_print=pretty_print)
+            fleet_.export(outfile, level, namespace_, pretty_print=pretty_print)
     def build(self, node):
         already_processed = set()
         self.buildAttributes(node, node.attrib, already_processed)
@@ -1081,13 +1093,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'carrierType'
@@ -1095,7 +1110,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/annotations1_sup.py b/tests/annotations1_sup.py
index b95527acc3f700656b8186b8a7cd019428ce8901..306fae8476f21d08dafaa9866d84d2a171121478 100644
--- a/tests/annotations1_sup.py
+++ b/tests/annotations1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1073,13 +1085,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'document1Type'
@@ -1087,7 +1102,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/anonymous_type1_sup.py b/tests/anonymous_type1_sup.py
index 200d52e89b62469ffc5dbe43f3cbc0aed3f17d2e..80237f134a4e23c22f397699ea442a65708bec58 100644
--- a/tests/anonymous_type1_sup.py
+++ b/tests/anonymous_type1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1140,13 +1152,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'FooList'
@@ -1154,7 +1169,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/anysimpletype1_sup.py b/tests/anysimpletype1_sup.py
index 126c501beef7e6909245006052c5e51adb4c2075..e3f355a74447484bf801731ab14a327719841ce8 100644
--- a/tests/anysimpletype1_sup.py
+++ b/tests/anysimpletype1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -970,13 +982,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'test1element'
@@ -984,7 +999,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/anywildcard1_sup.py b/tests/anywildcard1_sup.py
index 95dfc40e454d593c6ccf2d882299dba47ca38adb..22dac15ddab75ec97afecdb54c680756aac43d47 100644
--- a/tests/anywildcard1_sup.py
+++ b/tests/anywildcard1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1322,13 +1334,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'PlantType_single'
@@ -1336,7 +1351,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/attr_groups1_sup.py b/tests/attr_groups1_sup.py
index 676f8c643c10860e3236def7fdff091fc05082b0..4c34fd7e30abf7ccb00f45537b95212a362354b3 100644
--- a/tests/attr_groups1_sup.py
+++ b/tests/attr_groups1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -968,13 +980,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'GetUserReq'
@@ -982,7 +997,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/catalogtest1_sup.py b/tests/catalogtest1_sup.py
index f0c9f3d82280ad54252ff659ba73d4fa9db19226..65a9e4d9e9d15c2dc6b063da3521409a6cde6914 100644
--- a/tests/catalogtest1_sup.py
+++ b/tests/catalogtest1_sup.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -779,13 +791,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = ''
@@ -793,7 +808,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/cdata1_sup.py b/tests/cdata1_sup.py
index ce39ea62eb386f3efaaa6144401bd743576f85ec..147ebb03491126598754772eceb6ced989983b9c 100644
--- a/tests/cdata1_sup.py
+++ b/tests/cdata1_sup.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -940,13 +952,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'cdataListType'
@@ -954,7 +969,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/cleanupname1_sup.py b/tests/cleanupname1_sup.py
index 3d6c984c43bfc6f7704b24d52e3011f7ec690a26..0c1f1fce554b6a964ebcfa09fed9a18c7277b874 100644
--- a/tests/cleanupname1_sup.py
+++ b/tests/cleanupname1_sup.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1290,13 +1302,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'dataKind'
@@ -1304,7 +1319,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/copy_all b/tests/copy_all
index 0ba8184c9c1db728091361091da41f331beb54fe..87ffae9b2e519691494b406141c39add94491087 100755
--- a/tests/copy_all
+++ b/tests/copy_all
@@ -59,7 +59,7 @@ cp rem_dup_elems2_sup.py rem_dup_elems1_sup.py
 cp rem_dup_elems2_sub.py rem_dup_elems1_sub.py
 cp disable_xml_super2_sup.py disable_xml_super1_sup.py
 cp disable_xml_super2_sub.py disable_xml_super1_sub.py
-cp defaults_cases_export2_sub.py defaults_cases_export1_sub.py
-cp defaults_cases_export2_sup.py defaults_cases_export1_sup.py
+#cp defaults_cases_export2_sub.py defaults_cases_export1_sub.py
+#cp defaults_cases_export2_sup.py defaults_cases_export1_sup.py
 cp mixedcontent2_sub.py mixedcontent1_sub.py
 cp mixedcontent2_sup.py mixedcontent1_sup.py
diff --git a/tests/defaults_cases1_sup.py b/tests/defaults_cases1_sup.py
index 024b77a4623edc7584dbaf587b42dcd1f8523732..e576fe27d0ab5b983342c99851e70c37b58dff4a 100644
--- a/tests/defaults_cases1_sup.py
+++ b/tests/defaults_cases1_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1175,13 +1187,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'DefaultTypes'
@@ -1189,7 +1204,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/defaults_coverage1_sup.py b/tests/defaults_coverage1_sup.py
index 08d5248f8b24ecc1f0662df451206c4b68b67198..0979dee14e6c3e89f7bdc2744062c93a67b7130a 100644
--- a/tests/defaults_coverage1_sup.py
+++ b/tests/defaults_coverage1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1538,13 +1550,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'DefaultTypes'
@@ -1552,7 +1567,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/disable_xml_super1_sup.py b/tests/disable_xml_super1_sup.py
index 78be9fb9c96cfa9a6c237f2f0a8b6e9f0c928360..fd6688ad86a9094e2dbe6840d4bff96d09382415 100644
--- a/tests/disable_xml_super1_sup.py
+++ b/tests/disable_xml_super1_sup.py
@@ -58,6 +58,18 @@ else:
 ##     doc = etree_.parse(infile, parser=parser, **kwargs)
 ##     return doc
 
+## def parsexmlstring_(instring, parser=None, **kwargs):
+##     if parser is None:
+##         # Use the lxml ElementTree compatible parser so that, e.g.,
+##         #   we ignore comments.
+##         try:
+##             parser = etree_.ETCompatXMLParser()
+##         except AttributeError:
+##             # fallback to xml.etree
+##             parser = etree_.XMLParser()
+##     element = etree_.fromstring(instring, parser=parser, **kwargs)
+##     return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
diff --git a/tests/extensions1_sup.py b/tests/extensions1_sup.py
index efd5c319d3062316a7e78c3c406acf2b6776798c..e24e044a131b94510d10ece7942582c126216490 100644
--- a/tests/extensions1_sup.py
+++ b/tests/extensions1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1859,13 +1871,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'containerType'
@@ -1873,7 +1888,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/ipo1_sup.py b/tests/ipo1_sup.py
index c1c929adb6debd2130f543f8d307161c0ac990f7..5299bd7e544220980523d2962f9905d87c09ed51 100644
--- a/tests/ipo1_sup.py
+++ b/tests/ipo1_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1526,13 +1538,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'PurchaseOrderType'
@@ -1540,7 +1555,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/ipo2_sup.py b/tests/ipo2_sup.py
index c1c929adb6debd2130f543f8d307161c0ac990f7..5299bd7e544220980523d2962f9905d87c09ed51 100644
--- a/tests/ipo2_sup.py
+++ b/tests/ipo2_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1526,13 +1538,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'PurchaseOrderType'
@@ -1540,7 +1555,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/mapcleanname1_sup.py b/tests/mapcleanname1_sup.py
index 711180efc8a1004e3e17df066ce6477a1e476da1..b3fe993427d385ac71ad79af4f7371a37c6f72bc 100644
--- a/tests/mapcleanname1_sup.py
+++ b/tests/mapcleanname1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1637,13 +1649,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'complex_type01'
@@ -1651,7 +1666,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/mixedcontent1_sup.py b/tests/mixedcontent1_sup.py
index 59f9c98fe47f68eacd845e30b426ee52fcfc2a48..475c35de75dcbf43c378596af41d017703873a5b 100644
--- a/tests/mixedcontent1_sup.py
+++ b/tests/mixedcontent1_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1319,13 +1331,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'rootType'
@@ -1333,7 +1348,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/mixedcontent2_sup.py b/tests/mixedcontent2_sup.py
index 59f9c98fe47f68eacd845e30b426ee52fcfc2a48..475c35de75dcbf43c378596af41d017703873a5b 100644
--- a/tests/mixedcontent2_sup.py
+++ b/tests/mixedcontent2_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1319,13 +1331,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'rootType'
@@ -1333,7 +1348,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/nested_def1_sup.py b/tests/nested_def1_sup.py
index 1627dc469f479627a62078fef1c17de465e354d7..eea9981dc3251c05dca239dd8b7e553a28709258 100644
--- a/tests/nested_def1_sup.py
+++ b/tests/nested_def1_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1189,13 +1201,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'containerType'
@@ -1203,7 +1218,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/out1_sup.py b/tests/out1_sup.py
index b2588ef79bbdbd626bac75ad9f83f6d7a3243e49..898638cdc0e83f1ea4250e3445c294efba518584 100644
--- a/tests/out1_sup.py
+++ b/tests/out1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -3579,13 +3591,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'people'
@@ -3593,7 +3608,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/people_procincl1_sup.py b/tests/people_procincl1_sup.py
index 2fa8158f465b043ebe0d91cf14c6ca4d23cef29b..87585435833a5d7a56412502d2851fb87188963a 100644
--- a/tests/people_procincl1_sup.py
+++ b/tests/people_procincl1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1544,7 +1556,7 @@ class agent(GeneratedsSuper):
         if self.info is not None:
             self.info.export(outfile, level, namespace_, name_='info', pretty_print=pretty_print)
         for vehicle_ in self.vehicle:
-            vehicle_.export(outfile, level, namespace_, name_='vehicle', pretty_print=pretty_print)
+            vehicle_.export(outfile, level, namespace_, pretty_print=pretty_print)
     def build(self, node):
         already_processed = set()
         self.buildAttributes(node, node.attrib, already_processed)
@@ -2978,13 +2990,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'people'
@@ -2992,7 +3007,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/prefix_classname1_sup.py b/tests/prefix_classname1_sup.py
index b28364c3fced26247332819060342d95d7e79a78..04ac7be2d087f7529cd7277c5a3bd4c09e472621 100644
--- a/tests/prefix_classname1_sup.py
+++ b/tests/prefix_classname1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -2584,13 +2596,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'people'
@@ -2598,7 +2613,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/recursive_simpletype1_sup.py b/tests/recursive_simpletype1_sup.py
index 05c042934359a285a7f954e2effdf2249486a924..bb467f4f6446a7d0b0eae10417b14b8e6e6a8055 100644
--- a/tests/recursive_simpletype1_sup.py
+++ b/tests/recursive_simpletype1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -884,13 +896,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'PersonType'
@@ -898,7 +913,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/reference_simpletype1_sup.py b/tests/reference_simpletype1_sup.py
index 3f3f4307eebd7170f0e0717552f59d0ba1332be1..e9fb502eedf0b179689ffa78c5309557a11923da 100644
--- a/tests/reference_simpletype1_sup.py
+++ b/tests/reference_simpletype1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -902,13 +914,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'xs_integer'
@@ -916,7 +931,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/rem_dup_elems1_sup.py b/tests/rem_dup_elems1_sup.py
index beef45bcaeb67c255fee95abcf3e2031417b3be0..c4ed8e3e4e52d499a177e4b97584d4d49728b6a4 100644
--- a/tests/rem_dup_elems1_sup.py
+++ b/tests/rem_dup_elems1_sup.py
@@ -56,6 +56,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -958,13 +970,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'authorsType'
@@ -972,7 +987,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/simplecontent_restriction1_sup.py b/tests/simplecontent_restriction1_sup.py
index d5f878562982234890957908e55c49ce9455561c..c1ba056e495cd9cdd0d0ff7dfe5511677f78baf8 100644
--- a/tests/simplecontent_restriction1_sup.py
+++ b/tests/simplecontent_restriction1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1077,13 +1089,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'IdentifierType'
@@ -1091,7 +1106,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/simpletype_memberspecs1_sup.py b/tests/simpletype_memberspecs1_sup.py
index cd93882f60bfa6aa7739d052630facf3f0e52d72..442879777f2cda805286d047ffd4dd0ed933c4be 100644
--- a/tests/simpletype_memberspecs1_sup.py
+++ b/tests/simpletype_memberspecs1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -934,13 +946,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'SpecialDate'
@@ -948,7 +963,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/simpletypes_other1_sup.py b/tests/simpletypes_other1_sup.py
index b29530995aa20af955b893b69e8d68e363210410..32ef27f480d52d37d7b0a1be54d893e0827433f8 100644
--- a/tests/simpletypes_other1_sup.py
+++ b/tests/simpletypes_other1_sup.py
@@ -55,6 +55,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1279,13 +1291,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'simpleTypeTestsType'
@@ -1293,7 +1308,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/to_etree1_sup.py b/tests/to_etree1_sup.py
index 911ec6dfcb17e7df3bb800255472329d11b80ecf..f2b634d228b5feff71edb20097ed2527c6754f79 100644
--- a/tests/to_etree1_sup.py
+++ b/tests/to_etree1_sup.py
@@ -57,6 +57,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -3028,13 +3040,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'peopleType'
@@ -3042,7 +3057,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
 ##     if not silence:
 ##         sys.stdout.write('<?xml version="1.0" ?>\n')
 ##         rootObj.export(
diff --git a/tests/validate_simpletypes1_sup.py b/tests/validate_simpletypes1_sup.py
index 938d76edba685b2c7de8f91c0252353795f5342c..dd6a1fa5e08bf1b4dcccd8ab7c8770748fcb259a 100644
--- a/tests/validate_simpletypes1_sup.py
+++ b/tests/validate_simpletypes1_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1724,13 +1736,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'containerType'
@@ -1738,7 +1753,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tests/validate_simpletypes1_warnings.txt b/tests/validate_simpletypes1_warnings.txt
index 0309c68763e45e5a00c0dc1c5161a5dae5051534..2b72df6b010bd6bdfb669ced141bd39b8aa2b965 100644
--- a/tests/validate_simpletypes1_warnings.txt
+++ b/tests/validate_simpletypes1_warnings.txt
@@ -1,60 +1,60 @@
-tests/validate_simpletypes2_sup.py:1047: UserWarning: Value "2" does not match xsd minExclusive restriction on integer_range_1_st
+tests/validate_simpletypes2_sup.py:1059: UserWarning: Value "2" does not match xsd minExclusive restriction on integer_range_1_st
   warnings_.warn('Value "%(value)s" does not match xsd minExclusive restriction on integer_range_1_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1057: UserWarning: Value "mmaaa1234mnopzzz" does not match xsd pattern restrictions: [['^aaa.*zzz$', '^bbb.*xxx$'], ['^.*123.*$', '^.*456.*$']]
+tests/validate_simpletypes2_sup.py:1069: UserWarning: Value "mmaaa1234mnopzzz" does not match xsd pattern restrictions: [['^aaa.*zzz$', '^bbb.*xxx$'], ['^.*123.*$', '^.*456.*$']]
   warnings_.warn('Value "%s" does not match xsd pattern restrictions: %s' % (value.encode('utf-8'), self.validate_pattern_st_patterns_, ))
-tests/validate_simpletypes2_sup.py:1070: UserWarning: Value "floatxx" does not match xsd enumeration restriction on token_enum_st
+tests/validate_simpletypes2_sup.py:1082: UserWarning: Value "floatxx" does not match xsd enumeration restriction on token_enum_st
   warnings_.warn('Value "%(value)s" does not match xsd enumeration restriction on token_enum_st' % {"value" : value.encode("utf-8")} )
-tests/validate_simpletypes2_sup.py:1077: UserWarning: Value "22" does not match xsd maxInclusive restriction on integer_range_incl_st
+tests/validate_simpletypes2_sup.py:1089: UserWarning: Value "22" does not match xsd maxInclusive restriction on integer_range_incl_st
   warnings_.warn('Value "%(value)s" does not match xsd maxInclusive restriction on integer_range_incl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1082: UserWarning: Value "-40" does not match xsd minExclusive restriction on integer_range_excl_st
+tests/validate_simpletypes2_sup.py:1094: UserWarning: Value "-40" does not match xsd minExclusive restriction on integer_range_excl_st
   warnings_.warn('Value "%(value)s" does not match xsd minExclusive restriction on integer_range_excl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1091: UserWarning: Value "mno pqr" does not match xsd minLength restriction on min_max_length_st
+tests/validate_simpletypes2_sup.py:1103: UserWarning: Value "mno pqr" does not match xsd minLength restriction on min_max_length_st
   warnings_.warn('Value "%(value)s" does not match xsd minLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} )
-tests/validate_simpletypes2_sup.py:1096: UserWarning: Value "012345" does not match xsd length restriction on length_st
+tests/validate_simpletypes2_sup.py:1108: UserWarning: Value "012345" does not match xsd length restriction on length_st
   warnings_.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} )
-tests/validate_simpletypes2_sup.py:1173: UserWarning: Value "0.2" does not match xsd minInclusive restriction on anonymous_float_valueType
+tests/validate_simpletypes2_sup.py:1185: UserWarning: Value "0.2" does not match xsd minInclusive restriction on anonymous_float_valueType
   warnings_.warn('Value "%(value)s" does not match xsd minInclusive restriction on anonymous_float_valueType' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1167: UserWarning: Value "efgh" does not match xsd pattern restrictions: [['^abcd$|^ef\\|gh$']]
+tests/validate_simpletypes2_sup.py:1179: UserWarning: Value "efgh" does not match xsd pattern restrictions: [['^abcd$|^ef\\|gh$']]
   warnings_.warn('Value "%s" does not match xsd pattern restrictions: %s' % (value.encode('utf-8'), self.validate_vbar_pattern_st_patterns_, ))
-tests/validate_simpletypes2_sup.py:1049: UserWarning: Value "9" does not match xsd maxExclusive restriction on integer_range_1_st
+tests/validate_simpletypes2_sup.py:1061: UserWarning: Value "9" does not match xsd maxExclusive restriction on integer_range_1_st
   warnings_.warn('Value "%(value)s" does not match xsd maxExclusive restriction on integer_range_1_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1057: UserWarning: Value "aaa1234mnopzzzbcd" does not match xsd pattern restrictions: [['^aaa.*zzz$', '^bbb.*xxx$'], ['^.*123.*$', '^.*456.*$']]
+tests/validate_simpletypes2_sup.py:1069: UserWarning: Value "aaa1234mnopzzzbcd" does not match xsd pattern restrictions: [['^aaa.*zzz$', '^bbb.*xxx$'], ['^.*123.*$', '^.*456.*$']]
   warnings_.warn('Value "%s" does not match xsd pattern restrictions: %s' % (value.encode('utf-8'), self.validate_pattern_st_patterns_, ))
-tests/validate_simpletypes2_sup.py:1075: UserWarning: Value "-50" does not match xsd minInclusive restriction on integer_range_incl_st
+tests/validate_simpletypes2_sup.py:1087: UserWarning: Value "-50" does not match xsd minInclusive restriction on integer_range_incl_st
   warnings_.warn('Value "%(value)s" does not match xsd minInclusive restriction on integer_range_incl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1089: UserWarning: Value "asdf asdf asdf asdf asdf asdf" does not match xsd maxLength restriction on min_max_length_st
+tests/validate_simpletypes2_sup.py:1101: UserWarning: Value "asdf asdf asdf asdf asdf asdf" does not match xsd maxLength restriction on min_max_length_st
   warnings_.warn('Value "%(value)s" does not match xsd maxLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} )
-tests/validate_simpletypes2_sup.py:1096: UserWarning: Value "01234567890" does not match xsd length restriction on length_st
+tests/validate_simpletypes2_sup.py:1108: UserWarning: Value "01234567890" does not match xsd length restriction on length_st
   warnings_.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} )
-tests/validate_simpletypes2_sup.py:1106: UserWarning: Value "2015-05-01" does not match xsd minInclusive restriction on date_minincl_st
+tests/validate_simpletypes2_sup.py:1118: UserWarning: Value "2015-05-01" does not match xsd minInclusive restriction on date_minincl_st
   warnings_.warn('Value "%(value)s" does not match xsd minInclusive restriction on date_minincl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1111: UserWarning: Value "2015-11-01" does not match xsd maxInclusive restriction on date_maxincl_st
+tests/validate_simpletypes2_sup.py:1123: UserWarning: Value "2015-11-01" does not match xsd maxInclusive restriction on date_maxincl_st
   warnings_.warn('Value "%(value)s" does not match xsd maxInclusive restriction on date_maxincl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1116: UserWarning: Value "2015-05-01" does not match xsd minExclusive restriction on date_minexcl_st
+tests/validate_simpletypes2_sup.py:1128: UserWarning: Value "2015-05-01" does not match xsd minExclusive restriction on date_minexcl_st
   warnings_.warn('Value "%(value)s" does not match xsd minExclusive restriction on date_minexcl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1121: UserWarning: Value "2015-11-01" does not match xsd maxExclusive restriction on date_maxexcl_st
+tests/validate_simpletypes2_sup.py:1133: UserWarning: Value "2015-11-01" does not match xsd maxExclusive restriction on date_maxexcl_st
   warnings_.warn('Value "%(value)s" does not match xsd maxExclusive restriction on date_maxexcl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1126: UserWarning: Value "13:30:00" does not match xsd minInclusive restriction on time_minincl_st
+tests/validate_simpletypes2_sup.py:1138: UserWarning: Value "13:30:00" does not match xsd minInclusive restriction on time_minincl_st
   warnings_.warn('Value "%(value)s" does not match xsd minInclusive restriction on time_minincl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1131: UserWarning: Value "17:00:00" does not match xsd maxInclusive restriction on time_maxincl_st
+tests/validate_simpletypes2_sup.py:1143: UserWarning: Value "17:00:00" does not match xsd maxInclusive restriction on time_maxincl_st
   warnings_.warn('Value "%(value)s" does not match xsd maxInclusive restriction on time_maxincl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1136: UserWarning: Value "13:30:00" does not match xsd minExclusive restriction on time_minexcl_st
+tests/validate_simpletypes2_sup.py:1148: UserWarning: Value "13:30:00" does not match xsd minExclusive restriction on time_minexcl_st
   warnings_.warn('Value "%(value)s" does not match xsd minExclusive restriction on time_minexcl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1141: UserWarning: Value "17:00:00" does not match xsd maxExclusive restriction on time_maxexcl_st
+tests/validate_simpletypes2_sup.py:1153: UserWarning: Value "17:00:00" does not match xsd maxExclusive restriction on time_maxexcl_st
   warnings_.warn('Value "%(value)s" does not match xsd maxExclusive restriction on time_maxexcl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1146: UserWarning: Value "2015-06-01 13:20:10" does not match xsd minInclusive restriction on datetime_minincl_st
+tests/validate_simpletypes2_sup.py:1158: UserWarning: Value "2015-06-01 13:20:10" does not match xsd minInclusive restriction on datetime_minincl_st
   warnings_.warn('Value "%(value)s" does not match xsd minInclusive restriction on datetime_minincl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1151: UserWarning: Value "2015-11-01 14:20:10" does not match xsd maxInclusive restriction on datetime_maxincl_st
+tests/validate_simpletypes2_sup.py:1163: UserWarning: Value "2015-11-01 14:20:10" does not match xsd maxInclusive restriction on datetime_maxincl_st
   warnings_.warn('Value "%(value)s" does not match xsd maxInclusive restriction on datetime_maxincl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1156: UserWarning: Value "2015-06-01 13:20:10" does not match xsd minExclusive restriction on datetime_minexcl_st
+tests/validate_simpletypes2_sup.py:1168: UserWarning: Value "2015-06-01 13:20:10" does not match xsd minExclusive restriction on datetime_minexcl_st
   warnings_.warn('Value "%(value)s" does not match xsd minExclusive restriction on datetime_minexcl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1161: UserWarning: Value "2015-11-01 14:20:10" does not match xsd maxExclusive restriction on datetime_maxexcl_st
+tests/validate_simpletypes2_sup.py:1173: UserWarning: Value "2015-11-01 14:20:10" does not match xsd maxExclusive restriction on datetime_maxexcl_st
   warnings_.warn('Value "%(value)s" does not match xsd maxExclusive restriction on datetime_maxexcl_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1175: UserWarning: Value "6.6" does not match xsd maxInclusive restriction on anonymous_float_valueType
+tests/validate_simpletypes2_sup.py:1187: UserWarning: Value "6.6" does not match xsd maxInclusive restriction on anonymous_float_valueType
   warnings_.warn('Value "%(value)s" does not match xsd maxInclusive restriction on anonymous_float_valueType' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1054: UserWarning: Value "aaa12zzz" does not match xsd minLength restriction on pattern_st
+tests/validate_simpletypes2_sup.py:1066: UserWarning: Value "aaa12zzz" does not match xsd minLength restriction on pattern_st
   warnings_.warn('Value "%(value)s" does not match xsd minLength restriction on pattern_st' % {"value" : value} )
-tests/validate_simpletypes2_sup.py:1057: UserWarning: Value "aaa12zzz" does not match xsd pattern restrictions: [['^aaa.*zzz$', '^bbb.*xxx$'], ['^.*123.*$', '^.*456.*$']]
+tests/validate_simpletypes2_sup.py:1069: UserWarning: Value "aaa12zzz" does not match xsd pattern restrictions: [['^aaa.*zzz$', '^bbb.*xxx$'], ['^.*123.*$', '^.*456.*$']]
   warnings_.warn('Value "%s" does not match xsd pattern restrictions: %s' % (value.encode('utf-8'), self.validate_pattern_st_patterns_, ))
-tests/validate_simpletypes2_sup.py:1599: UserWarning: Value "pqrst" does not match xsd minLength restriction on simpleTwoElementTwoType
+tests/validate_simpletypes2_sup.py:1611: UserWarning: Value "pqrst" does not match xsd minLength restriction on simpleTwoElementTwoType
   warnings_.warn('Value "%(value)s" does not match xsd minLength restriction on simpleTwoElementTwoType' % {"value" : value.encode("utf-8")} )
diff --git a/tests/validate_simpletypes2_sup.py b/tests/validate_simpletypes2_sup.py
index 938d76edba685b2c7de8f91c0252353795f5342c..dd6a1fa5e08bf1b4dcccd8ab7c8770748fcb259a 100644
--- a/tests/validate_simpletypes2_sup.py
+++ b/tests/validate_simpletypes2_sup.py
@@ -54,6 +54,18 @@ def parsexml_(infile, parser=None, **kwargs):
     doc = etree_.parse(infile, parser=parser, **kwargs)
     return doc
 
+def parsexmlstring_(instring, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    element = etree_.fromstring(instring, parser=parser, **kwargs)
+    return element
+
 #
 # Namespace prefix definition table (and other attributes, too)
 #
@@ -1724,13 +1736,16 @@ def parseEtree(inFileName, silence=False):
 
 
 def parseString(inString, silence=False):
-    if sys.version_info.major == 2:
-        from StringIO import StringIO as IOBuffer
-    else:
-        from io import BytesIO as IOBuffer
+    '''Parse a string, create the object tree, and export it.
+
+    Arguments:
+    - inString -- A string.  This XML fragment should not start
+      with an XML declaration containing an encoding.
+    - silence -- A boolean.  If False, export the object.
+    Returns -- The root object in the tree.
+    '''
     parser = None
-    doc = parsexml_(IOBuffer(inString), parser)
-    rootNode = doc.getroot()
+    rootNode= parsexmlstring_(inString, parser)
     rootTag, rootClass = get_root_tag(rootNode)
     if rootClass is None:
         rootTag = 'containerType'
@@ -1738,7 +1753,6 @@ def parseString(inString, silence=False):
     rootObj = rootClass.factory()
     rootObj.build(rootNode)
     # Enable Python to collect the space used by the DOM.
-    doc = None
     if not silence:
         sys.stdout.write('<?xml version="1.0" ?>\n')
         rootObj.export(
diff --git a/tutorial/generateds_tutorial.html b/tutorial/generateds_tutorial.html
index 6bcda28d5e51a08df8621768c209ffd77d89b42a..40a49cd9a4ec0d54f9b0eeded0145481d474d8e4 100644
--- a/tutorial/generateds_tutorial.html
+++ b/tutorial/generateds_tutorial.html
@@ -219,7 +219,7 @@ They are used by updateversion.py. -->
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.3</td>
+<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.29.4</td>
 </tr>
 </tbody>
 </table>
@@ -228,7 +228,7 @@ They are used by updateversion.py. -->
 <col class="field-name" />
 <col class="field-body" />
 <tbody valign="top">
-<tr class="field"><th class="field-name">date:</th><td class="field-body">December 11, 2017</td>
+<tr class="field"><th class="field-name">date:</th><td class="field-body">December 14, 2017</td>
 </tr>
 </tbody>
 </table>
@@ -1210,7 +1210,7 @@ named <tt class="docutils literal">garden_api.py</tt>, you can create an instanc
 <div class="footer">
 <hr class="footer" />
 <a class="reference external" href="generateds_tutorial.txt">View document source</a>.
-Generated on: 2017-12-11 21:49 UTC.
+Generated on: 2017-12-14 22:46 UTC.
 Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
 
 </div>
diff --git a/tutorial/generateds_tutorial.txt b/tutorial/generateds_tutorial.txt
index 31249981150c05f3dbc83b122814509ee3d7a79d..ec4b328ac12c7bf91332506a580f60053e9e0223 100644
--- a/tutorial/generateds_tutorial.txt
+++ b/tutorial/generateds_tutorial.txt
@@ -11,7 +11,7 @@ generateDS -- Introduction and Tutorial
 
 .. version
 
-:revision: 2.29.3
+:revision: 2.29.4
 
 .. version
 
diff --git a/tutorial/generateds_tutorial.zip b/tutorial/generateds_tutorial.zip
index 4c6f535896bcc912fc6e2b4a715ba0ec1c59a05b..2df8e3b9633f8cec64f6150fb17446a73cb67f39 100644
Binary files a/tutorial/generateds_tutorial.zip and b/tutorial/generateds_tutorial.zip differ