Package lxml :: Package tests :: Module test_etree |
[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_etree

       1  # -*- coding: utf-8 -*-
       2
       3  """
       4  Tests specific to the extended etree API
       5
       6  Tests that apply to the general ElementTree API should go into
       7  test_elementtree
       8  """
       9
      10  import os.path, unittest, copy, sys, operator
      11
      12  this_dir = os.path.dirname(__file__)
      13  if this_dir not in sys.path:
      14      sys.path.insert(0, this_dir) # needed for Py3
      15
      16  from common_imports import etree, StringIO, BytesIO, HelperTestCase, fileInTestDir
      17  from common_imports import LargeFileLikeUnicode, doctest, make_doctest
      18  from common_imports import canonicalize, sorted, _str, _bytes
      19
      20  print("")
      21  print("TESTED VERSION: %s" % etree.__version__)
      22  print("    Python:           " + repr(sys.version_info))
      23  print("    lxml.etree:       " + repr(etree.LXML_VERSION))
      24  print("    libxml used:      " + repr(etree.LIBXML_VERSION))
      25  print("    libxml compiled:  " + repr(etree.LIBXML_COMPILED_VERSION))
      26  print("    libxslt used:     " + repr(etree.LIBXSLT_VERSION))
      27  print("    libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
      28  print("")
      29
      30  try:
      31      _unicode = unicode
      32  except NameError:
      33      # Python 3
      34      _unicode = str
      35
      36 -class ETreeOnlyTestCase(HelperTestCase):
      37      """Tests only for etree, not ElementTree"""
      38      etree = etree
      39
      40 -    def test_version(self):
      41          self.assert_(isinstance(etree.__version__, _unicode))
      42          self.assert_(isinstance(etree.LXML_VERSION, tuple))
      43          self.assertEqual(len(etree.LXML_VERSION), 4)
      44          self.assert_(isinstance(etree.LXML_VERSION[0], int))
      45          self.assert_(isinstance(etree.LXML_VERSION[1], int))
      46          self.assert_(isinstance(etree.LXML_VERSION[2], int))
      47          self.assert_(isinstance(etree.LXML_VERSION[3], int))
      48          self.assert_(etree.__version__.startswith(
      49              str(etree.LXML_VERSION[0])))
      50
      51 -    def test_c_api(self):
      52          if hasattr(self.etree, '__pyx_capi__'):
      53              # newer Pyrex compatible C-API
      54              self.assert_(isinstance(self.etree.__pyx_capi__, dict))
      55              self.assert_(len(self.etree.__pyx_capi__) > 0)
      56          else:
      57              # older C-API mechanism
      58              self.assert_(hasattr(self.etree, '_import_c_api'))
      59
      60 -    def test_element_names(self):
      61          Element = self.etree.Element
      62          el = Element('name')
      63          self.assertEquals(el.tag, 'name')
      64          el = Element('{}name')
      65          self.assertEquals(el.tag, 'name')
      66
      67 -    def test_element_name_empty(self):
      68          Element = self.etree.Element
      69          el = Element('name')
      70          self.assertRaises(ValueError, Element, '{}')
      71          self.assertRaises(ValueError, setattr, el, 'tag', '{}')
      72
      73          self.assertRaises(ValueError, Element, '{test}')
      74          self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
      75
      76 -    def test_element_name_colon(self):
      77          Element = self.etree.Element
      78          self.assertRaises(ValueError, Element, 'p:name')
      79          self.assertRaises(ValueError, Element, '{test}p:name')
      80
      81          el = Element('name')
      82          self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
      83
      84 -    def test_element_name_quote(self):
      85          Element = self.etree.Element
      86          self.assertRaises(ValueError, Element, "p'name")
      87          self.assertRaises(ValueError, Element, 'p"name')
      88
      89          self.assertRaises(ValueError, Element, "{test}p'name")
      90          self.assertRaises(ValueError, Element, '{test}p"name')
      91
      92          el = Element('name')
      93          self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
      94          self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
      95
      96 -    def test_element_name_space(self):
      97          Element = self.etree.Element
      98          self.assertRaises(ValueError, Element, ' name ')
      99          self.assertRaises(ValueError, Element, 'na me')
     100          self.assertRaises(ValueError, Element, '{test} name')
     101
     102          el = Element('name')
     103          self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
     104
     105 -    def test_subelement_name_empty(self):
     106          Element = self.etree.Element
     107          SubElement = self.etree.SubElement
     108
     109          el = Element('name')
     110          self.assertRaises(ValueError, SubElement, el, '{}')
     111          self.assertRaises(ValueError, SubElement, el, '{test}')
     112
     113 -    def test_subelement_name_colon(self):
     114          Element = self.etree.Element
     115          SubElement = self.etree.SubElement
     116
     117          el = Element('name')
     118          self.assertRaises(ValueError, SubElement, el, 'p:name')
     119          self.assertRaises(ValueError, SubElement, el, '{test}p:name')
     120
     121 -    def test_subelement_name_quote(self):
     122          Element = self.etree.Element
     123          SubElement = self.etree.SubElement
     124
     125          el = Element('name')
     126          self.assertRaises(ValueError, SubElement, el, "p'name")
     127          self.assertRaises(ValueError, SubElement, el, "{test}p'name")
     128
     129          self.assertRaises(ValueError, SubElement, el, 'p"name')
     130          self.assertRaises(ValueError, SubElement, el, '{test}p"name')
     131
     132 -    def test_subelement_name_space(self):
     133          Element = self.etree.Element
     134          SubElement = self.etree.SubElement
     135
     136          el = Element('name')
     137          self.assertRaises(ValueError, SubElement, el, ' name ')
     138          self.assertRaises(ValueError, SubElement, el, 'na me')
     139          self.assertRaises(ValueError, SubElement, el, '{test} name')
     140
     141 -    def test_qname_empty(self):
     142          QName = self.etree.QName
     143          self.assertRaises(ValueError, QName, '')
     144          self.assertRaises(ValueError, QName, 'test', '')
     145
     146 -    def test_qname_colon(self):
     147          QName = self.etree.QName
     148          self.assertRaises(ValueError, QName, 'p:name')
     149          self.assertRaises(ValueError, QName, 'test', 'p:name')
     150
     151 -    def test_qname_space(self):
     152          QName = self.etree.QName
     153          self.assertRaises(ValueError, QName, ' name ')
     154          self.assertRaises(ValueError, QName, 'na me')
     155          self.assertRaises(ValueError, QName, 'test', ' name')
     156
     157 -    def test_qname_text_resolve(self):
     158          # ET doesn't resove QNames as text values
     159          etree = self.etree
     160          qname = etree.QName('http://myns', 'a')
     161          a = etree.Element(qname, nsmap={'p' : 'http://myns'})
     162          a.text = qname
     163
     164          self.assertEquals("p:a", a.text)
     165
     166 -    def test_nsmap_prefix_invalid(self):
     167          etree = self.etree
     168          self.assertRaises(ValueError,
     169                            etree.Element, "root", nsmap={'"' : 'testns'})
     170          self.assertRaises(ValueError,
     171                            etree.Element, "root", nsmap={'&' : 'testns'})
     172          self.assertRaises(ValueError,
     173                            etree.Element, "root", nsmap={'a:b' : 'testns'})
     174
     175 -    def test_attribute_set(self):
     176          Element = self.etree.Element
     177          root = Element("root")
     178          root.set("attr", "TEST")
     179          self.assertEquals("TEST", root.get("attr"))
     180
     181 -    def test_attribute_set_invalid(self):
     182          # ElementTree accepts arbitrary attribute values
     183          # lxml.etree allows only strings
     184          Element = self.etree.Element
     185          root = Element("root")
     186          self.assertRaises(TypeError, root.set, "newattr", 5)
     187          self.assertRaises(TypeError, root.set, "newattr", None)
     188
     189 -    def test_pi(self):
     190          # lxml.etree separates target and text
     191          Element = self.etree.Element
     192          SubElement = self.etree.SubElement
     193          ProcessingInstruction = self.etree.ProcessingInstruction
     194
     195          a = Element('a')
     196          a.append(ProcessingInstruction('foo', 'some more text'))
     197          self.assertEquals(a[0].target, 'foo')
     198          self.assertEquals(a[0].text, 'some more text')
     199
     200 -    def test_pi_parse(self):
     201          XML = self.etree.XML
     202          root = XML(_bytes("<test><?mypi my test ?></test>"))
     203          self.assertEquals(root[0].target, "mypi")
     204          self.assertEquals(root[0].text, "my test ")
     205
     206 -    def test_deepcopy_pi(self):
     207          # previously caused a crash
     208          ProcessingInstruction = self.etree.ProcessingInstruction
     209
     210          a = ProcessingInstruction("PI", "ONE")
     211          b = copy.deepcopy(a)
     212          b.text = "ANOTHER"
     213
     214          self.assertEquals('ONE',     a.text)
     215          self.assertEquals('ANOTHER', b.text)
     216
     217 -    def test_attribute_set(self):
     218          # ElementTree accepts arbitrary attribute values
     219          # lxml.etree allows only strings
     220          Element = self.etree.Element
     221
     222          root = Element("root")
     223          root.set("attr", "TEST")
     224          self.assertEquals("TEST", root.get("attr"))
     225          self.assertRaises(TypeError, root.set, "newattr", 5)
     226
     227 -    def test_parse_remove_comments(self):
     228          fromstring = self.etree.fromstring
     229          tostring = self.etree.tostring
     230          XMLParser = self.etree.XMLParser
     231
     232          xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     233          parser = XMLParser(remove_comments=True)
     234          root = fromstring(xml, parser)
     235          self.assertEquals(
     236              _bytes('<a><b><c/></b></a>'),
     237              tostring(root))
     238
     239 -    def test_parse_remove_pis(self):
     240          parse = self.etree.parse
     241          tostring = self.etree.tostring
     242          XMLParser = self.etree.XMLParser
     243
     244          xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>')
     245
     246          f = BytesIO(xml)
     247          tree = parse(f)
     248          self.assertEquals(
     249              xml,
     250              tostring(tree))
     251
     252          parser = XMLParser(remove_pis=True)
     253          tree = parse(f, parser)
     254          self.assertEquals(
     255              _bytes('<a><b><c/></b></a>'),
     256              tostring(tree))
     257
     258 -    def test_parse_parser_type_error(self):
     259          # ET raises IOError only
     260          parse = self.etree.parse
     261          self.assertRaises(TypeError, parse, 'notthere.xml', object())
     262
     263 -    def test_parse_error_logging(self):
     264          parse = self.etree.parse
     265          f = BytesIO('<a><b></c></b></a>')
     266          self.etree.clear_error_log()
     267          try:
     268              parse(f)
     269              logs = None
     270          except SyntaxError:
     271              e = sys.exc_info()[1]
     272              logs = e.error_log
     273          f.close()
     274          self.assert_([ log for log in logs
     275                         if 'mismatch' in log.message ])
     276          self.assert_([ log for log in logs
     277                         if 'PARSER'   in log.domain_name])
     278          self.assert_([ log for log in logs
     279                         if 'TAG_NAME_MISMATCH' in log.type_name ])
     280          self.assert_([ log for log in logs
     281                         if 1 == log.line ])
     282          self.assert_([ log for log in logs
     283                         if 15 == log.column ])
     284
     285 -    def test_iterparse_tree_comments(self):
     286          # ET removes comments
     287          iterparse = self.etree.iterparse
     288          tostring = self.etree.tostring
     289
     290          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     291          events = list(iterparse(f))
     292          root = events[-1][1]
     293          self.assertEquals(3, len(events))
     294          self.assertEquals(
     295              _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
     296              tostring(root))
     297
     298 -    def test_iterparse_comments(self):
     299          # ET removes comments
     300          iterparse = self.etree.iterparse
     301          tostring = self.etree.tostring
     302
     303          def name(event, el):
     304              if event == 'comment':
     305                  return el.text
     306              else:
     307                  return el.tag
     308
     309          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     310          events = list(iterparse(f, events=('end', 'comment')))
     311          root = events[-1][1]
     312          self.assertEquals(6, len(events))
     313          self.assertEquals(['A', ' B ', 'c', 'b', 'C', 'a'],
     314                            [ name(*item) for item in events ])
     315          self.assertEquals(
     316              _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
     317              tostring(root))
     318
     319 -    def test_iterparse_pis(self):
     320          # ET removes pis
     321          iterparse = self.etree.iterparse
     322          tostring = self.etree.tostring
     323          ElementTree = self.etree.ElementTree
     324
     325          def name(event, el):
     326              if event == 'pi':
     327                  return (el.target, el.text)
     328              else:
     329                  return el.tag
     330
     331          f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
     332          events = list(iterparse(f, events=('end', 'pi')))
     333          root = events[-2][1]
     334          self.assertEquals(8, len(events))
     335          self.assertEquals([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
     336                             ('pid','d'), 'a', ('pie','e')],
     337                            [ name(*item) for item in events ])
     338          self.assertEquals(
     339              _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
     340              tostring(ElementTree(root)))
     341
     342 -    def test_iterparse_remove_comments(self):
     343          iterparse = self.etree.iterparse
     344          tostring = self.etree.tostring
     345
     346          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     347          events = list(iterparse(f, remove_comments=True,
     348                                  events=('end', 'comment')))
     349          root = events[-1][1]
     350          self.assertEquals(3, len(events))
     351          self.assertEquals(['c', 'b', 'a'],
     352                            [ el.tag for (event, el) in events ])
     353          self.assertEquals(
     354              _bytes('<a><b><c/></b></a>'),
     355              tostring(root))
     356
     357 -    def test_iterparse_broken(self):
     358          iterparse = self.etree.iterparse
     359          f = BytesIO('<a><b><c/></a>')
     360          # ET raises ExpatError, lxml raises XMLSyntaxError
     361          self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
     362
     363 -    def test_iterparse_strip(self):
     364          iterparse = self.etree.iterparse
     365          f = BytesIO("""
     366                 <a>  \n \n  <b> b test </b>  \n
     367
     368                 \n\t <c> \n </c> </a>  \n """)
     369          iterator = iterparse(f, remove_blank_text=True)
     370          text = [ (element.text, element.tail)
     371                   for event, element in iterator ]
     372          self.assertEquals(
     373              [(" b test ", None), (" \n ", None), (None, None)],
     374              text)
     375
     376 -    def test_iterparse_tag(self):
     377          iterparse = self.etree.iterparse
     378          f = BytesIO('<a><b><d/></b><c/></a>')
     379
     380          iterator = iterparse(f, tag="b", events=('start', 'end'))
     381          events = list(iterator)
     382          root = iterator.root
     383          self.assertEquals(
     384              [('start', root[0]), ('end', root[0])],
     385              events)
     386
     387 -    def test_iterparse_tag_all(self):
     388          iterparse = self.etree.iterparse
     389          f = BytesIO('<a><b><d/></b><c/></a>')
     390
     391          iterator = iterparse(f, tag="*", events=('start', 'end'))
     392          events = list(iterator)
     393          self.assertEquals(
     394              8,
     395              len(events))
     396
     397 -    def test_iterparse_encoding_error(self):
     398          text = _str('Søk på nettet')
     399          wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
     400          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
     401                        ).encode('iso-8859-1')
     402
     403          self.assertRaises(self.etree.ParseError,
     404                            list, self.etree.iterparse(BytesIO(xml_latin1)))
     405
     406 -    def test_iterparse_encoding_8bit_override(self):
     407          text = _str('Søk på nettet', encoding="UTF-8")
     408          wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
     409          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
     410                        ).encode('iso-8859-1')
     411
     412          iterator = self.etree.iterparse(BytesIO(xml_latin1),
     413                                          encoding="iso-8859-1")
     414          self.assertEquals(1, len(list(iterator)))
     415
     416          a = iterator.root
     417          self.assertEquals(a.text, text)
     418
     419 -    def test_iterparse_keep_cdata(self):
     420          tostring = self.etree.tostring
     421          f = BytesIO('<root><![CDATA[test]]></root>')
     422          context = self.etree.iterparse(f, strip_cdata=False)
     423          content = [ el.text for event,el in context ]
     424
     425          self.assertEquals(['test'], content)
     426          self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
     427                            tostring(context.root))
     428
     429 -    def test_parser_encoding_unknown(self):
     430          self.assertRaises(
     431              LookupError, self.etree.XMLParser, encoding="hopefully unknown")
     432
     433 -    def test_elementtree_parser_target_type_error(self):
     434          assertEquals = self.assertEquals
     435          assertFalse  = self.assertFalse
     436
     437          events = []
     438          class Target(object):
     439              def start(self, tag, attrib):
     440                  events.append("start")
     441                  assertFalse(attrib)
     442                  assertEquals("TAG", tag)
     443              def end(self, tag):
     444                  events.append("end")
     445                  assertEquals("TAG", tag)
     446              def close(self):
     447                  return "DONE" # no Element!
     448
     449          parser = self.etree.XMLParser(target=Target())
     450          tree = self.etree.ElementTree()
     451
     452          self.assertRaises(TypeError,
     453                            tree.parse, BytesIO("<TAG/>"), parser=parser)
     454          self.assertEquals(["start", "end"], events)
     455
     456 -    def test_parser_target_comment(self):
     457          events = []
     458          class Target(object):
     459              def start(self, tag, attrib):
     460                  events.append("start-" + tag)
     461              def end(self, tag):
     462                  events.append("end-" + tag)
     463              def data(self, data):
     464                  events.append("data-" + data)
     465              def comment(self, text):
     466                  events.append("comment-" + text)
     467              def close(self):
     468                  return "DONE"
     469
     470          parser = self.etree.XMLParser(target=Target())
     471
     472          parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
     473          done = parser.close()
     474
     475          self.assertEquals("DONE", done)
     476          self.assertEquals(["comment-a", "start-root", "data-A", "comment-b",
     477                             "start-sub", "end-sub", "comment-c", "data-B",
     478                             "end-root", "comment-d"],
     479                            events)
     480
     481 -    def test_parser_target_pi(self):
     482          events = []
     483          class Target(object):
     484              def start(self, tag, attrib):
     485                  events.append("start-" + tag)
     486              def end(self, tag):
     487                  events.append("end-" + tag)
     488              def data(self, data):
     489                  events.append("data-" + data)
     490              def pi(self, target, data):
     491                  events.append("pi-" + target + "-" + data)
     492              def close(self):
     493                  return "DONE"
     494
     495          parser = self.etree.XMLParser(target=Target())
     496
     497          parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
     498          done = parser.close()
     499
     500          self.assertEquals("DONE", done)
     501          self.assertEquals(["pi-test-a", "start-root", "data-A", "pi-test-b",
     502                             "data-B", "end-root", "pi-test-c"],
     503                            events)
     504
     505 -    def test_parser_target_cdata(self):
     506          events = []
     507          class Target(object):
     508              def start(self, tag, attrib):
     509                  events.append("start-" + tag)
     510              def end(self, tag):
     511                  events.append("end-" + tag)
     512              def data(self, data):
     513                  events.append("data-" + data)
     514              def close(self):
     515                  return "DONE"
     516
     517          parser = self.etree.XMLParser(target=Target(),
     518                                        strip_cdata=False)
     519
     520          parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
     521          done = parser.close()
     522
     523          self.assertEquals("DONE", done)
     524          self.assertEquals(["start-root", "data-A", "start-a",
     525                             "data-ca", "end-a", "data-B", "end-root"],
     526                            events)
     527
     528 -    def test_iterwalk_tag(self):
     529          iterwalk = self.etree.iterwalk
     530          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
     531
     532          iterator = iterwalk(root, tag="b", events=('start', 'end'))
     533          events = list(iterator)
     534          self.assertEquals(
     535              [('start', root[0]), ('end', root[0])],
     536              events)
     537
     538 -    def test_iterwalk_tag_all(self):
     539          iterwalk = self.etree.iterwalk
     540          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
     541
     542          iterator = iterwalk(root, tag="*", events=('start', 'end'))
     543          events = list(iterator)
     544          self.assertEquals(
     545              8,
     546              len(events))
     547
     548 -    def test_iterwalk(self):
     549          iterwalk = self.etree.iterwalk
     550          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     551
     552          events = list(iterwalk(root))
     553          self.assertEquals(
     554              [('end', root[0]), ('end', root[1]), ('end', root)],
     555              events)
     556
     557 -    def test_iterwalk_start(self):
     558          iterwalk = self.etree.iterwalk
     559          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     560
     561          iterator = iterwalk(root, events=('start',))
     562          events = list(iterator)
     563          self.assertEquals(
     564              [('start', root), ('start', root[0]), ('start', root[1])],
     565              events)
     566
     567 -    def test_iterwalk_start_end(self):
     568          iterwalk = self.etree.iterwalk
     569          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     570
     571          iterator = iterwalk(root, events=('start','end'))
     572          events = list(iterator)
     573          self.assertEquals(
     574              [('start', root), ('start', root[0]), ('end', root[0]),
     575               ('start', root[1]), ('end', root[1]), ('end', root)],
     576              events)
     577
     578 -    def test_iterwalk_clear(self):
     579          iterwalk = self.etree.iterwalk
     580          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     581
     582          iterator = iterwalk(root)
     583          for event, elem in iterator:
     584              elem.clear()
     585
     586          self.assertEquals(0,
     587                            len(root))
     588
     589 -    def test_iterwalk_attrib_ns(self):
     590          iterwalk = self.etree.iterwalk
     591          root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
     592
     593          attr_name = '{testns}bla'
     594          events = []
     595          iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
     596          for event, elem in iterator:
     597              events.append(event)
     598              if event == 'start':
     599                  if elem.tag != '{ns1}a':
     600                      elem.set(attr_name, 'value')
     601
     602          self.assertEquals(
     603              ['start-ns', 'start', 'start', 'start-ns', 'start',
     604               'end', 'end-ns', 'end', 'end', 'end-ns'],
     605              events)
     606
     607          self.assertEquals(
     608              None,
     609              root.get(attr_name))
     610          self.assertEquals(
     611              'value',
     612              root[0].get(attr_name))
     613
     614 -    def test_iterwalk_getiterator(self):
     615          iterwalk = self.etree.iterwalk
     616          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
     617
     618          counts = []
     619          for event, elem in iterwalk(root):
     620              counts.append(len(list(elem.getiterator())))
     621          self.assertEquals(
     622              [1,2,1,4],
     623              counts)
     624
     625 -    def test_resolve_string_dtd(self):
     626          parse = self.etree.parse
     627          parser = self.etree.XMLParser(dtd_validation=True)
     628          assertEqual = self.assertEqual
     629          test_url = _str("__nosuch.dtd")
     630
     631          class MyResolver(self.etree.Resolver):
     632              def resolve(self, url, id, context):
     633                  assertEqual(url, test_url)
     634                  return self.resolve_string(
     635                      _str('''<!ENTITY myentity "%s">
     636                          <!ELEMENT doc ANY>''') % url, context)
     637
     638          parser.resolvers.add(MyResolver())
     639
     640          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
     641          tree = parse(StringIO(xml), parser)
     642          root = tree.getroot()
     643          self.assertEquals(root.text, test_url)
     644
     645 -    def test_resolve_filename_dtd(self):
     646          parse = self.etree.parse
     647          parser = self.etree.XMLParser(attribute_defaults=True)
     648          assertEqual = self.assertEqual
     649          test_url = _str("__nosuch.dtd")
     650
     651          class MyResolver(self.etree.Resolver):
     652              def resolve(self, url, id, context):
     653                  assertEqual(url, test_url)
     654                  return self.resolve_filename(
     655                      fileInTestDir('test.dtd'), context)
     656
     657          parser.resolvers.add(MyResolver())
     658
     659          xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
     660          tree = parse(StringIO(xml), parser)
     661          root = tree.getroot()
     662          self.assertEquals(
     663              root.attrib,    {'default': 'valueA'})
     664          self.assertEquals(
     665              root[0].attrib, {'default': 'valueB'})
     666
     667 -    def test_resolve_empty(self):
     668          parse = self.etree.parse
     669          parser = self.etree.XMLParser(load_dtd=True)
     670          assertEqual = self.assertEqual
     671          test_url = _str("__nosuch.dtd")
     672
     673          class check(object):
     674              resolved = False
     675
     676          class MyResolver(self.etree.Resolver):
     677              def resolve(self, url, id, context):
     678                  assertEqual(url, test_url)
     679                  check.resolved = True
     680                  return self.resolve_empty(context)
     681
     682          parser.resolvers.add(MyResolver())
     683
     684          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
     685          self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
     686          self.assert_(check.resolved)
     687
     688 -    def test_resolve_error(self):
     689          parse = self.etree.parse
     690          parser = self.etree.XMLParser(dtd_validation=True)
     691
     692          class _LocalException(Exception):
     693              pass
     694
     695          class MyResolver(self.etree.Resolver):
     696              def resolve(self, url, id, context):
     697                  raise _LocalException
     698
     699          parser.resolvers.add(MyResolver())
     700
     701          xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
     702          self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
     703
     704      if etree.LIBXML_VERSION > (2,6,20):
     705 -        def test_entity_parse(self):
     706              parse = self.etree.parse
     707              tostring = self.etree.tostring
     708              parser = self.etree.XMLParser(resolve_entities=False)
     709              Entity = self.etree.Entity
     710
     711              xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
     712              tree = parse(BytesIO(xml), parser)
     713              root = tree.getroot()
     714              self.assertEquals(root[0].tag, Entity)
     715              self.assertEquals(root[0].text, "&myentity;")
     716              self.assertEquals(root[0].tail, None)
     717              self.assertEquals(root[0].name, "myentity")
     718
     719              self.assertEquals(_bytes('<doc>&myentity;</doc>'),
     720                                tostring(root))
     721
     722 -    def test_entity_append(self):
     723          Entity = self.etree.Entity
     724          Element = self.etree.Element
     725          tostring = self.etree.tostring
     726
     727          root = Element("root")
     728          root.append( Entity("test") )
     729
     730          self.assertEquals(root[0].tag, Entity)
     731          self.assertEquals(root[0].text, "&test;")
     732          self.assertEquals(root[0].tail, None)
     733          self.assertEquals(root[0].name, "test")
     734
     735          self.assertEquals(_bytes('<root>&test;</root>'),
     736                            tostring(root))
     737
     738 -    def test_entity_values(self):
     739          Entity = self.etree.Entity
     740          self.assertEquals(Entity("test").text, '&test;')
     741          self.assertEquals(Entity("#17683").text, '&#17683;')
     742          self.assertEquals(Entity("#x1768").text, '&#x1768;')
     743          self.assertEquals(Entity("#x98AF").text, '&#x98AF;')
     744
     745 -    def test_entity_error(self):
     746          Entity = self.etree.Entity
     747          self.assertRaises(ValueError, Entity, 'a b c')
     748          self.assertRaises(ValueError, Entity, 'a,b')
     749          self.assertRaises(ValueError, Entity, 'a\0b')
     750          self.assertRaises(ValueError, Entity, '#abc')
     751          self.assertRaises(ValueError, Entity, '#xxyz')
     752
     753 -    def test_cdata(self):
     754          CDATA = self.etree.CDATA
     755          Element = self.etree.Element
     756          tostring = self.etree.tostring
     757
     758          root = Element("root")
     759          root.text = CDATA('test')
     760
     761          self.assertEquals('test',
     762                            root.text)
     763          self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
     764                            tostring(root))
     765
     766 -    def test_cdata_type(self):
     767          CDATA = self.etree.CDATA
     768          Element = self.etree.Element
     769          root = Element("root")
     770
     771          root.text = CDATA("test")
     772          self.assertEquals('test', root.text)
     773
     774          root.text = CDATA(_str("test"))
     775          self.assertEquals('test', root.text)
     776
     777          self.assertRaises(TypeError, CDATA, 1)
     778
     779 -    def test_cdata_errors(self):
     780          CDATA = self.etree.CDATA
     781          Element = self.etree.Element
     782
     783          root = Element("root")
     784          cdata = CDATA('test')
     785
     786          self.assertRaises(TypeError,
     787                            setattr, root, 'tail', cdata)
     788          self.assertRaises(TypeError,
     789                            root.set, 'attr', cdata)
     790          self.assertRaises(TypeError,
     791                            operator.setitem, root.attrib, 'attr', cdata)
     792
     793 -    def test_cdata_parser(self):
     794          tostring = self.etree.tostring
     795          parser = self.etree.XMLParser(strip_cdata=False)
     796          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
     797
     798          self.assertEquals('test', root.text)
     799          self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
     800                            tostring(root))
     801
     802      # TypeError in etree, AssertionError in ElementTree;
     803 -    def test_setitem_assert(self):
     804          Element = self.etree.Element
     805          SubElement = self.etree.SubElement
     806
     807          a = Element('a')
     808          b = SubElement(a, 'b')
     809
     810          self.assertRaises(TypeError,
     811                            a.__setitem__, 0, 'foo')
     812
     813 -    def test_append_None(self):
     814          # raises AssertionError in ElementTree
     815          Element = self.etree.Element
     816          self.assertRaises(TypeError, Element('a').append, None)
     817
     818 -    def test_addnext(self):
     819          Element = self.etree.Element
     820          SubElement = self.etree.SubElement
     821          root = Element('root')
     822          SubElement(root, 'a')
     823          SubElement(root, 'b')
     824
     825          self.assertEquals(['a', 'b'],
     826                            [c.tag for c in root])
     827          root[1].addnext(root[0])
     828          self.assertEquals(['b', 'a'],
     829                            [c.tag for c in root])
     830
     831 -    def test_addprevious(self):
     832          Element = self.etree.Element
     833          SubElement = self.etree.SubElement
     834          root = Element('root')
     835          SubElement(root, 'a')
     836          SubElement(root, 'b')
     837
     838          self.assertEquals(['a', 'b'],
     839                            [c.tag for c in root])
     840          root[0].addprevious(root[1])
     841          self.assertEquals(['b', 'a'],
     842                            [c.tag for c in root])
     843
     844 -    def test_addnext_root(self):
     845          Element = self.etree.Element
     846          a = Element('a')
     847          b = Element('b')
     848          self.assertRaises(TypeError, a.addnext, b)
     849
     850 -    def test_addnext_root(self):
     851          Element = self.etree.Element
     852          a = Element('a')
     853          b = Element('b')
     854          self.assertRaises(TypeError, a.addnext, b)
     855
     856 -    def test_addprevious_pi(self):
     857          Element = self.etree.Element
     858          SubElement = self.etree.SubElement
     859          PI = self.etree.PI
     860          root = Element('root')
     861          SubElement(root, 'a')
     862          pi = PI('TARGET', 'TEXT')
     863          pi.tail = "TAIL"
     864
     865          self.assertEquals(_bytes('<root><a></a></root>'),
     866                            self._writeElement(root))
     867          root[0].addprevious(pi)
     868          self.assertEquals(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
     869                            self._writeElement(root))
     870
     871 -    def test_addprevious_root_pi(self):
     872          Element = self.etree.Element
     873          PI = self.etree.PI
     874          root = Element('root')
     875          pi = PI('TARGET', 'TEXT')
     876          pi.tail = "TAIL"
     877
     878          self.assertEquals(_bytes('<root></root>'),
     879                            self._writeElement(root))
     880          root.addprevious(pi)
     881          self.assertEquals(_bytes('<?TARGET TEXT?>\n<root></root>'),
     882                            self._writeElement(root))
     883
     884 -    def test_addnext_pi(self):
     885          Element = self.etree.Element
     886          SubElement = self.etree.SubElement
     887          PI = self.etree.PI
     888          root = Element('root')
     889          SubElement(root, 'a')
     890          pi = PI('TARGET', 'TEXT')
     891          pi.tail = "TAIL"
     892
     893          self.assertEquals(_bytes('<root><a></a></root>'),
     894                            self._writeElement(root))
     895          root[0].addnext(pi)
     896          self.assertEquals(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
     897                            self._writeElement(root))
     898
     899 -    def test_addnext_root_pi(self):
     900          Element = self.etree.Element
     901          PI = self.etree.PI
     902          root = Element('root')
     903          pi = PI('TARGET', 'TEXT')
     904          pi.tail = "TAIL"
     905
     906          self.assertEquals(_bytes('<root></root>'),
     907                            self._writeElement(root))
     908          root.addnext(pi)
     909          self.assertEquals(_bytes('<root></root>\n<?TARGET TEXT?>'),
     910                            self._writeElement(root))
     911
     912 -    def test_addnext_comment(self):
     913          Element = self.etree.Element
     914          SubElement = self.etree.SubElement
     915          Comment = self.etree.Comment
     916          root = Element('root')
     917          SubElement(root, 'a')
     918          comment = Comment('TEXT ')
     919          comment.tail = "TAIL"
     920
     921          self.assertEquals(_bytes('<root><a></a></root>'),
     922                            self._writeElement(root))
     923          root[0].addnext(comment)
     924          self.assertEquals(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
     925                            self._writeElement(root))
     926
     927 -    def test_addnext_root_comment(self):
     928          Element = self.etree.Element
     929          Comment = self.etree.Comment
     930          root = Element('root')
     931          comment = Comment('TEXT ')
     932          comment.tail = "TAIL"
     933
     934          self.assertEquals(_bytes('<root></root>'),
     935                            self._writeElement(root))
     936          root.addnext(comment)
     937          self.assertEquals(_bytes('<root></root>\n<!--TEXT -->'),
     938                            self._writeElement(root))
     939
     940 -    def test_addprevious_comment(self):
     941          Element = self.etree.Element
     942          SubElement = self.etree.SubElement
     943          Comment = self.etree.Comment
     944          root = Element('root')
     945          SubElement(root, 'a')
     946          comment = Comment('TEXT ')
     947          comment.tail = "TAIL"
     948
     949          self.assertEquals(_bytes('<root><a></a></root>'),
     950                            self._writeElement(root))
     951          root[0].addprevious(comment)
     952          self.assertEquals(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
     953                            self._writeElement(root))
     954
     955 -    def test_addprevious_root_comment(self):
     956          Element = self.etree.Element
     957          Comment = self.etree.Comment
     958          root = Element('root')
     959          comment = Comment('TEXT ')
     960          comment.tail = "TAIL"
     961
     962          self.assertEquals(_bytes('<root></root>'),
     963                            self._writeElement(root))
     964          root.addprevious(comment)
     965          self.assertEquals(_bytes('<!--TEXT -->\n<root></root>'),
     966                            self._writeElement(root))
     967
     968      # ET's Elements have items() and key(), but not values()
     969 -    def test_attribute_values(self):
     970          XML = self.etree.XML
     971
     972          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
     973          values = root.values()
     974          values.sort()
     975          self.assertEquals(['Alpha', 'Beta', 'Gamma'], values)
     976
     977      # gives error in ElementTree
     978 -    def test_comment_empty(self):
     979          Element = self.etree.Element
     980          Comment = self.etree.Comment
     981
     982          a = Element('a')
     983          a.append(Comment())
     984          self.assertEquals(
     985              _bytes('<a><!----></a>'),
     986              self._writeElement(a))
     987
     988      # ElementTree ignores comments
     989 -    def test_comment_parse_empty(self):
     990          ElementTree = self.etree.ElementTree
     991          tostring = self.etree.tostring
     992
     993          xml = _bytes('<a><b/><!----><c/></a>')
     994          f = BytesIO(xml)
     995          doc = ElementTree(file=f)
     996          a = doc.getroot()
     997          self.assertEquals(
     998              '',
     999              a[1].text)
    1000          self.assertEquals(
    1001              xml,
    1002              tostring(a))
    1003
    1004      # ElementTree ignores comments
    1005 -    def test_comment_no_proxy_yet(self):
    1006          ElementTree = self.etree.ElementTree
    1007
    1008          f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
    1009          doc = ElementTree(file=f)
    1010          a = doc.getroot()
    1011          self.assertEquals(
    1012              ' hoi ',
    1013              a[1].text)
    1014
    1015      # does not raise an exception in ElementTree
    1016 -    def test_comment_immutable(self):
    1017          Element = self.etree.Element
    1018          Comment = self.etree.Comment
    1019
    1020          c = Comment()
    1021          el = Element('myel')
    1022
    1023          self.assertRaises(TypeError, c.append, el)
    1024          self.assertRaises(TypeError, c.insert, 0, el)
    1025          self.assertRaises(TypeError, c.set, "myattr", "test")
    1026
    1027      # test passing 'None' to dump
    1028 -    def test_dump_none(self):
    1029          self.assertRaises(TypeError, self.etree.dump, None)
    1030
    1031 -    def test_prefix(self):
    1032          ElementTree = self.etree.ElementTree
    1033
    1034          f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
    1035          doc = ElementTree(file=f)
    1036          a = doc.getroot()
    1037          self.assertEquals(
    1038              None,
    1039              a.prefix)
    1040          self.assertEquals(
    1041              'foo',
    1042              a[0].prefix)
    1043
    1044 -    def test_prefix_default_ns(self):
    1045          ElementTree = self.etree.ElementTree
    1046
    1047          f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
    1048          doc = ElementTree(file=f)
    1049          a = doc.getroot()
    1050          self.assertEquals(
    1051              None,
    1052              a.prefix)
    1053          self.assertEquals(
    1054              None,
    1055              a[0].prefix)
    1056
    1057 -    def test_getparent(self):
    1058          Element = self.etree.Element
    1059          SubElement = self.etree.SubElement
    1060
    1061          a = Element('a')
    1062          b = SubElement(a, 'b')
    1063          c = SubElement(a, 'c')
    1064          d = SubElement(b, 'd')
    1065          self.assertEquals(
    1066              None,
    1067              a.getparent())
    1068          self.assertEquals(
    1069              a,
    1070              b.getparent())
    1071          self.assertEquals(
    1072              b.getparent(),
    1073              c.getparent())
    1074          self.assertEquals(
    1075              b,
    1076              d.getparent())
    1077
    1078 -    def test_iterchildren(self):
    1079          XML = self.etree.XML
    1080
    1081          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1082          result = []
    1083          for el in root.iterchildren():
    1084              result.append(el.tag)
    1085          self.assertEquals(['one', 'two', 'three'], result)
    1086
    1087 -    def test_iterchildren_reversed(self):
    1088          XML = self.etree.XML
    1089
    1090          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1091          result = []
    1092          for el in root.iterchildren(reversed=True):
    1093              result.append(el.tag)
    1094          self.assertEquals(['three', 'two', 'one'], result)
    1095
    1096 -    def test_iterchildren_tag(self):
    1097          XML = self.etree.XML
    1098
    1099          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1100          result = []
    1101          for el in root.iterchildren(tag='two'):
    1102              result.append(el.text)
    1103          self.assertEquals(['Two', 'Bla'], result)
    1104
    1105 -    def test_iterchildren_tag_reversed(self):
    1106          XML = self.etree.XML
    1107
    1108          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1109          result = []
    1110          for el in root.iterchildren(reversed=True, tag='two'):
    1111              result.append(el.text)
    1112          self.assertEquals(['Bla', 'Two'], result)
    1113
    1114 -    def test_iterancestors(self):
    1115          Element    = self.etree.Element
    1116          SubElement = self.etree.SubElement
    1117
    1118          a = Element('a')
    1119          b = SubElement(a, 'b')
    1120          c = SubElement(a, 'c')
    1121          d = SubElement(b, 'd')
    1122          self.assertEquals(
    1123              [],
    1124              list(a.iterancestors()))
    1125          self.assertEquals(
    1126              [a],
    1127              list(b.iterancestors()))
    1128          self.assertEquals(
    1129              [a],
    1130              list(c.iterancestors()))
    1131          self.assertEquals(
    1132              [b, a],
    1133              list(d.iterancestors()))
    1134
    1135 -    def test_iterancestors_tag(self):
    1136          Element    = self.etree.Element
    1137          SubElement = self.etree.SubElement
    1138
    1139          a = Element('a')
    1140          b = SubElement(a, 'b')
    1141          c = SubElement(a, 'c')
    1142          d = SubElement(b, 'd')
    1143          self.assertEquals(
    1144              [a],
    1145              list(d.iterancestors(tag='a')))
    1146
    1147 -    def test_iterdescendants(self):
    1148          Element = self.etree.Element
    1149          SubElement = self.etree.SubElement
    1150
    1151          a = Element('a')
    1152          b = SubElement(a, 'b')
    1153          c = SubElement(a, 'c')
    1154          d = SubElement(b, 'd')
    1155          e = SubElement(c, 'e')
    1156
    1157          self.assertEquals(
    1158              [b, d, c, e],
    1159              list(a.iterdescendants()))
    1160          self.assertEquals(
    1161              [],
    1162              list(d.iterdescendants()))
    1163
    1164 -    def test_iterdescendants_tag(self):
    1165          Element = self.etree.Element
    1166          SubElement = self.etree.SubElement
    1167
    1168          a = Element('a')
    1169          b = SubElement(a, 'b')
    1170          c = SubElement(a, 'c')
    1171          d = SubElement(b, 'd')
    1172          e = SubElement(c, 'e')
    1173
    1174          self.assertEquals(
    1175              [],
    1176              list(a.iterdescendants('a')))
    1177          a2 = SubElement(e, 'a')
    1178          self.assertEquals(
    1179              [a2],
    1180              list(a.iterdescendants('a')))
    1181          self.assertEquals(
    1182              [a2],
    1183              list(c.iterdescendants('a')))
    1184
    1185 -    def test_getroottree(self):
    1186          Element = self.etree.Element
    1187          SubElement = self.etree.SubElement
    1188
    1189          a = Element('a')
    1190          b = SubElement(a, 'b')
    1191          c = SubElement(a, 'c')
    1192          d = SubElement(b, 'd')
    1193          self.assertEquals(
    1194              a,
    1195              a.getroottree().getroot())
    1196          self.assertEquals(
    1197              a,
    1198              b.getroottree().getroot())
    1199          self.assertEquals(
    1200              a,
    1201              d.getroottree().getroot())
    1202
    1203 -    def test_getnext(self):
    1204          Element    = self.etree.Element
    1205          SubElement = self.etree.SubElement
    1206
    1207          a = Element('a')
    1208          b = SubElement(a, 'b')
    1209          c = SubElement(a, 'c')
    1210          self.assertEquals(
    1211              None,
    1212              a.getnext())
    1213          self.assertEquals(
    1214              c,
    1215              b.getnext())
    1216          self.assertEquals(
    1217              None,
    1218              c.getnext())
    1219
    1220 -    def test_getprevious(self):
    1221          Element    = self.etree.Element
    1222          SubElement = self.etree.SubElement
    1223
    1224          a = Element('a')
    1225          b = SubElement(a, 'b')
    1226          c = SubElement(a, 'c')
    1227          d = SubElement(b, 'd')
    1228          self.assertEquals(
    1229              None,
    1230              a.getprevious())
    1231          self.assertEquals(
    1232              b,
    1233              c.getprevious())
    1234          self.assertEquals(
    1235              None,
    1236              b.getprevious())
    1237
    1238 -    def test_itersiblings(self):
    1239          Element    = self.etree.Element
    1240          SubElement = self.etree.SubElement
    1241
    1242          a = Element('a')
    1243          b = SubElement(a, 'b')
    1244          c = SubElement(a, 'c')
    1245          d = SubElement(b, 'd')
    1246          self.assertEquals(
    1247              [],
    1248              list(a.itersiblings()))
    1249          self.assertEquals(
    1250              [c],
    1251              list(b.itersiblings()))
    1252          self.assertEquals(
    1253              [],
    1254              list(c.itersiblings()))
    1255          self.assertEquals(
    1256              [b],
    1257              list(c.itersiblings(preceding=True)))
    1258          self.assertEquals(
    1259              [],
    1260              list(b.itersiblings(preceding=True)))
    1261
    1262 -    def test_itersiblings_tag(self):
    1263          Element    = self.etree.Element
    1264          SubElement = self.etree.SubElement
    1265
    1266          a = Element('a')
    1267          b = SubElement(a, 'b')
    1268          c = SubElement(a, 'c')
    1269          d = SubElement(b, 'd')
    1270          self.assertEquals(
    1271              [],
    1272              list(a.itersiblings(tag='XXX')))
    1273          self.assertEquals(
    1274              [c],
    1275              list(b.itersiblings(tag='c')))
    1276          self.assertEquals(
    1277              [b],
    1278              list(c.itersiblings(preceding=True, tag='b')))
    1279          self.assertEquals(
    1280              [],
    1281              list(c.itersiblings(preceding=True, tag='c')))
    1282
    1283 -    def test_parseid(self):
    1284          parseid = self.etree.parseid
    1285          XML     = self.etree.XML
    1286          xml_text = _bytes('''
    1287          <!DOCTYPE document [
    1288          <!ELEMENT document (h1,p)*>
    1289          <!ELEMENT h1 (#PCDATA)>
    1290          <!ATTLIST h1 myid ID #REQUIRED>
    1291          <!ELEMENT p  (#PCDATA)>
    1292          <!ATTLIST p  someid ID #REQUIRED>
    1293          ]>
    1294          <document>
    1295            <h1 myid="chapter1">...</h1>
    1296            <p id="note1" class="note">...</p>
    1297            <p>Regular paragraph.</p>
    1298            <p xml:id="xmlid">XML:ID paragraph.</p>
    1299            <p someid="warn1" class="warning">...</p>
    1300          </document>
    1301          ''')
    1302
    1303          tree, dic = parseid(BytesIO(xml_text))
    1304          root = tree.getroot()
    1305          root2 = XML(xml_text)
    1306          self.assertEquals(self._writeElement(root),
    1307                            self._writeElement(root2))
    1308          expected = {
    1309              "chapter1" : root[0],
    1310              "xmlid"    : root[3],
    1311              "warn1"    : root[4]
    1312              }
    1313          self.assert_("chapter1" in dic)
    1314          self.assert_("warn1" in dic)
    1315          self.assert_("xmlid" in dic)
    1316          self._checkIDDict(dic, expected)
    1317
    1318 -    def test_XMLDTDID(self):
    1319          XMLDTDID = self.etree.XMLDTDID
    1320          XML      = self.etree.XML
    1321          xml_text = _bytes('''
    1322          <!DOCTYPE document [
    1323          <!ELEMENT document (h1,p)*>
    1324          <!ELEMENT h1 (#PCDATA)>
    1325          <!ATTLIST h1 myid ID #REQUIRED>
    1326          <!ELEMENT p  (#PCDATA)>
    1327          <!ATTLIST p  someid ID #REQUIRED>
    1328          ]>
    1329          <document>
    1330            <h1 myid="chapter1">...</h1>
    1331            <p id="note1" class="note">...</p>
    1332            <p>Regular paragraph.</p>
    1333            <p xml:id="xmlid">XML:ID paragraph.</p>
    1334            <p someid="warn1" class="warning">...</p>
    1335          </document>
    1336          ''')
    1337
    1338          root, dic = XMLDTDID(xml_text)
    1339          root2 = XML(xml_text)
    1340          self.assertEquals(self._writeElement(root),
    1341                            self._writeElement(root2))
    1342          expected = {
    1343              "chapter1" : root[0],
    1344              "xmlid"    : root[3],
    1345              "warn1"    : root[4]
    1346              }
    1347          self.assert_("chapter1" in dic)
    1348          self.assert_("warn1" in dic)
    1349          self.assert_("xmlid" in dic)
    1350          self._checkIDDict(dic, expected)
    1351
    1352 -    def test_XMLDTDID_empty(self):
    1353          XMLDTDID = self.etree.XMLDTDID
    1354          XML      = self.etree.XML
    1355          xml_text = _bytes('''
    1356          <document>
    1357            <h1 myid="chapter1">...</h1>
    1358            <p id="note1" class="note">...</p>
    1359            <p>Regular paragraph.</p>
    1360            <p someid="warn1" class="warning">...</p>
    1361          </document>
    1362          ''')
    1363
    1364          root, dic = XMLDTDID(xml_text)
    1365          root2 = XML(xml_text)
    1366          self.assertEquals(self._writeElement(root),
    1367                            self._writeElement(root2))
    1368          expected = {}
    1369          self._checkIDDict(dic, expected)
    1370
    1371 -    def _checkIDDict(self, dic, expected):
    1372          self.assertEquals(len(dic),
    1373                            len(expected))
    1374          self.assertEquals(sorted(dic.items()),
    1375                            sorted(expected.items()))
    1376          if sys.version_info < (3,):
    1377              self.assertEquals(sorted(dic.iteritems()),
    1378                                sorted(expected.iteritems()))
    1379          self.assertEquals(sorted(dic.keys()),
    1380                            sorted(expected.keys()))
    1381          if sys.version_info < (3,):
    1382              self.assertEquals(sorted(dic.iterkeys()),
    1383                                sorted(expected.iterkeys()))
    1384          if sys.version_info < (3,):
    1385              self.assertEquals(sorted(dic.values()),
    1386                                sorted(expected.values()))
    1387              self.assertEquals(sorted(dic.itervalues()),
    1388                                sorted(expected.itervalues()))
    1389
    1390 -    def test_namespaces(self):
    1391          etree = self.etree
    1392
    1393          r = {'foo': 'http://ns.infrae.com/foo'}
    1394          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1395          self.assertEquals(
    1396              'foo',
    1397              e.prefix)
    1398          self.assertEquals(
    1399              _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
    1400              self._writeElement(e))
    1401
    1402 -    def test_namespaces_default(self):
    1403          etree = self.etree
    1404
    1405          r = {None: 'http://ns.infrae.com/foo'}
    1406          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1407          self.assertEquals(
    1408              None,
    1409              e.prefix)
    1410          self.assertEquals(
    1411              '{http://ns.infrae.com/foo}bar',
    1412              e.tag)
    1413          self.assertEquals(
    1414              _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
    1415              self._writeElement(e))
    1416
    1417 -    def test_namespaces_default_and_attr(self):
    1418          etree = self.etree
    1419
    1420          r = {None: 'http://ns.infrae.com/foo',
    1421               'hoi': 'http://ns.infrae.com/hoi'}
    1422          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1423          e.set('{http://ns.infrae.com/hoi}test', 'value')
    1424          self.assertEquals(
    1425              _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
    1426              self._writeElement(e))
    1427
    1428 -    def test_namespaces_elementtree(self):
    1429          etree = self.etree
    1430          r = {None: 'http://ns.infrae.com/foo',
    1431               'hoi': 'http://ns.infrae.com/hoi'}
    1432          e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
    1433          tree = etree.ElementTree(element=e)
    1434          etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
    1435          self.assertEquals(
    1436              _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
    1437              self._writeElement(e))
    1438
    1439 -    def test_namespaces_default_copy_element(self):
    1440          etree = self.etree
    1441
    1442          r = {None: 'http://ns.infrae.com/foo'}
    1443          e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1444          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1445
    1446          e1.append(e2)
    1447
    1448          self.assertEquals(
    1449              None,
    1450              e1.prefix)
    1451          self.assertEquals(
    1452              None,
    1453              e1[0].prefix)
    1454          self.assertEquals(
    1455              '{http://ns.infrae.com/foo}bar',
    1456              e1.tag)
    1457          self.assertEquals(
    1458              '{http://ns.infrae.com/foo}bar',
    1459              e1[0].tag)
    1460
    1461 -    def test_namespaces_copy_element(self):
    1462          etree = self.etree
    1463
    1464          r = {None: 'http://ns.infrae.com/BAR'}
    1465          e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
    1466          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1467
    1468          e1.append(e2)
    1469
    1470          self.assertEquals(
    1471              None,
    1472              e1.prefix)
    1473          self.assertNotEquals(
    1474              None,
    1475              e2.prefix)
    1476          self.assertEquals(
    1477              '{http://ns.infrae.com/BAR}bar',
    1478              e1.tag)
    1479          self.assertEquals(
    1480              '{http://ns.infrae.com/foo}bar',
    1481              e2.tag)
    1482
    1483 -    def test_namespaces_reuse_after_move(self):
    1484          ns_href = "http://a.b.c"
    1485          one = self.etree.fromstring(
    1486              _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
    1487          baz = one[0][0]
    1488
    1489          two = self.etree.fromstring(
    1490              _bytes('<root xmlns:ns="%s"/>' % ns_href))
    1491          two.append(baz)
    1492          del one # make sure the source document is deallocated
    1493
    1494          self.assertEquals('{%s}baz' % ns_href, baz.tag)
    1495          self.assertEquals(
    1496              _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
    1497              self.etree.tostring(two))
    1498
    1499 -    def test_namespace_cleanup(self):
    1500          xml = _bytes('<foo xmlns="F" xmlns:x="x"><bar xmlns:ns="NS" xmlns:b="b" xmlns="B"><ns:baz/></bar></foo>')
    1501          root = self.etree.fromstring(xml)
    1502          self.assertEquals(xml,
    1503                            self.etree.tostring(root))
    1504          self.etree.cleanup_namespaces(root)
    1505          self.assertEquals(
    1506              _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
    1507              self.etree.tostring(root))
    1508
    1509 -    def test_element_nsmap(self):
    1510          etree = self.etree
    1511
    1512          r = {None: 'http://ns.infrae.com/foo',
    1513               'hoi': 'http://ns.infrae.com/hoi'}
    1514          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1515          self.assertEquals(
    1516              r,
    1517              e.nsmap)
    1518
    1519 -    def test_subelement_nsmap(self):
    1520          etree = self.etree
    1521
    1522          re = {None: 'http://ns.infrae.com/foo',
    1523               'hoi': 'http://ns.infrae.com/hoi'}
    1524          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
    1525
    1526          rs = {None: 'http://ns.infrae.com/honk',
    1527               'top': 'http://ns.infrae.com/top'}
    1528          s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
    1529
    1530          r = re.copy()
    1531          r.update(rs)
    1532          self.assertEquals(
    1533              re,
    1534              e.nsmap)
    1535          self.assertEquals(
    1536              r,
    1537              s.nsmap)
    1538
    1539 -    def test_getiterator_filter_namespace(self):
    1540          Element = self.etree.Element
    1541          SubElement = self.etree.SubElement
    1542
    1543          a = Element('{a}a')
    1544          b = SubElement(a, '{a}b')
    1545          c = SubElement(a, '{a}c')
    1546          d = SubElement(b, '{b}d')
    1547          e = SubElement(c, '{a}e')
    1548          f = SubElement(c, '{b}f')
    1549
    1550          self.assertEquals(
    1551              [a],
    1552              list(a.getiterator('{a}a')))
    1553          self.assertEquals(
    1554              [],
    1555              list(a.getiterator('{b}a')))
    1556          self.assertEquals(
    1557              [],
    1558              list(a.getiterator('a')))
    1559          self.assertEquals(
    1560              [f],
    1561              list(c.getiterator('{b}*')))
    1562          self.assertEquals(
    1563              [d, f],
    1564              list(a.getiterator('{b}*')))
    1565
    1566 -    def test_getiterator_filter_entities(self):
    1567          Element = self.etree.Element
    1568          Entity = self.etree.Entity
    1569          SubElement = self.etree.SubElement
    1570
    1571          a = Element('a')
    1572          b = SubElement(a, 'b')
    1573          entity_b = Entity("TEST-b")
    1574          b.append(entity_b)
    1575
    1576          self.assertEquals(
    1577              [entity_b],
    1578              list(a.getiterator(Entity)))
    1579
    1580          entity_a = Entity("TEST-a")
    1581          a.append(entity_a)
    1582
    1583          self.assertEquals(
    1584              [entity_b, entity_a],
    1585              list(a.getiterator(Entity)))
    1586
    1587          self.assertEquals(
    1588              [entity_b],
    1589              list(b.getiterator(Entity)))
    1590
    1591 -    def test_getiterator_filter_element(self):
    1592          Element = self.etree.Element
    1593          Comment = self.etree.Comment
    1594          PI = self.etree.PI
    1595          SubElement = self.etree.SubElement
    1596
    1597          a = Element('a')
    1598          b = SubElement(a, 'b')
    1599          a.append(Comment("test"))
    1600          a.append(PI("pi", "content"))
    1601          c = SubElement(a, 'c')
    1602
    1603          self.assertEquals(
    1604              [a, b, c],
    1605              list(a.getiterator(Element)))
    1606
    1607 -    def test_getiterator_filter_all_comment_pi(self):
    1608          # ElementTree iterates over everything here
    1609          Element = self.etree.Element
    1610          Comment = self.etree.Comment
    1611          PI = self.etree.PI
    1612          SubElement = self.etree.SubElement
    1613
    1614          a = Element('a')
    1615          b = SubElement(a, 'b')
    1616          a.append(Comment("test"))
    1617          a.append(PI("pi", "content"))
    1618          c = SubElement(a, 'c')
    1619
    1620          self.assertEquals(
    1621              [a, b, c],
    1622              list(a.getiterator('*')))
    1623
    1624 -    def test_elementtree_find_qname(self):
    1625          XML = self.etree.XML
    1626          ElementTree = self.etree.ElementTree
    1627          QName = self.etree.QName
    1628          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    1629          self.assertEquals(tree.find(QName("c")), tree.getroot()[2])
    1630
    1631 -    def test_elementtree_findall_qname(self):
    1632          XML = self.etree.XML
    1633          ElementTree = self.etree.ElementTree
    1634          QName = self.etree.QName
    1635          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    1636          self.assertEquals(len(list(tree.findall(QName("c")))), 1)
    1637
    1638 -    def test_elementtree_findall_ns_qname(self):
    1639          XML = self.etree.XML
    1640          ElementTree = self.etree.ElementTree
    1641          QName = self.etree.QName
    1642          tree = ElementTree(XML(
    1643                  _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
    1644          self.assertEquals(len(list(tree.findall(QName("b")))), 2)
    1645          self.assertEquals(len(list(tree.findall(QName("X", "b")))), 1)
    1646
    1647 -    def test_findall_ns(self):
    1648          XML = self.etree.XML
    1649          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
    1650          self.assertEquals(len(root.findall(".//{X}b")), 2)
    1651          self.assertEquals(len(root.findall(".//{X}*")), 2)
    1652          self.assertEquals(len(root.findall(".//b")), 3)
    1653
    1654 -    def test_index(self):
    1655          etree = self.etree
    1656          e = etree.Element('foo')
    1657          for i in range(10):
    1658              etree.SubElement(e, 'a%s' % i)
    1659          for i in range(10):
    1660              self.assertEquals(
    1661                  i,
    1662                  e.index(e[i]))
    1663          self.assertEquals(
    1664              3, e.index(e[3], 3))
    1665          self.assertRaises(
    1666              ValueError, e.index, e[3], 4)
    1667          self.assertRaises(
    1668              ValueError, e.index, e[3], 0, 2)
    1669          self.assertRaises(
    1670              ValueError, e.index, e[8], 0, -3)
    1671          self.assertRaises(
    1672              ValueError, e.index, e[8], -5, -3)
    1673          self.assertEquals(
    1674              8, e.index(e[8], 0, -1))
    1675          self.assertEquals(
    1676              8, e.index(e[8], -12, -1))
    1677          self.assertEquals(
    1678              0, e.index(e[0], -12, -1))
    1679
    1680 -    def test_replace(self):
    1681          etree = self.etree
    1682          e = etree.Element('foo')
    1683          for i in range(10):
    1684              el = etree.SubElement(e, 'a%s' % i)
    1685              el.text = "text%d" % i
    1686              el.tail = "tail%d" % i
    1687
    1688          child0 = e[0]
    1689          child1 = e[1]
    1690          child2 = e[2]
    1691
    1692          e.replace(e[0], e[1])
    1693          self.assertEquals(
    1694              9, len(e))
    1695          self.assertEquals(
    1696              child1, e[0])
    1697          self.assertEquals(
    1698              child1.text, "text1")
    1699          self.assertEquals(
    1700              child1.tail, "tail1")
    1701          self.assertEquals(
    1702              child0.tail, "tail0")
    1703          self.assertEquals(
    1704              child2, e[1])
    1705
    1706          e.replace(e[-1], e[0])
    1707          self.assertEquals(
    1708              child1, e[-1])
    1709          self.assertEquals(
    1710              child1.text, "text1")
    1711          self.assertEquals(
    1712              child1.tail, "tail1")
    1713          self.assertEquals(
    1714              child2, e[0])
    1715
    1716 -    def test_replace_new(self):
    1717          etree = self.etree
    1718          e = etree.Element('foo')
    1719          for i in range(10):
    1720              etree.SubElement(e, 'a%s' % i)
    1721
    1722          new_element = etree.Element("test")
    1723          new_element.text = "TESTTEXT"
    1724          new_element.tail = "TESTTAIL"
    1725          child1 = e[1]
    1726          e.replace(e[0], new_element)
    1727          self.assertEquals(
    1728              new_element, e[0])
    1729          self.assertEquals(
    1730              "TESTTEXT",
    1731              e[0].text)
    1732          self.assertEquals(
    1733              "TESTTAIL",
    1734              e[0].tail)
    1735          self.assertEquals(
    1736              child1, e[1])
    1737
    1738 -    def test_setslice_all_empty_reversed(self):
    1739          Element = self.etree.Element
    1740          SubElement = self.etree.SubElement
    1741
    1742          a = Element('a')
    1743
    1744          e = Element('e')
    1745          f = Element('f')
    1746          g = Element('g')
    1747
    1748          s = [e, f, g]
    1749          a[::-1] = s
    1750          self.assertEquals(
    1751              [g, f, e],
    1752              list(a))
    1753
    1754 -    def test_setslice_step(self):
    1755          Element = self.etree.Element
    1756          SubElement = self.etree.SubElement
    1757
    1758          a = Element('a')
    1759          b = SubElement(a, 'b')
    1760          c = SubElement(a, 'c')
    1761          d = SubElement(a, 'd')
    1762          e = SubElement(a, 'e')
    1763
    1764          x = Element('x')
    1765          y = Element('y')
    1766
    1767          a[1::2] = [x, y]
    1768          self.assertEquals(
    1769              [b, x, d, y],
    1770              list(a))
    1771
    1772 -    def test_setslice_step_negative(self):
    1773          Element = self.etree.Element
    1774          SubElement = self.etree.SubElement
    1775
    1776          a = Element('a')
    1777          b = SubElement(a, 'b')
    1778          c = SubElement(a, 'c')
    1779          d = SubElement(a, 'd')
    1780          e = SubElement(a, 'e')
    1781
    1782          x = Element('x')
    1783          y = Element('y')
    1784
    1785          a[1::-1] = [x, y]
    1786          self.assertEquals(
    1787              [y, x, d, e],
    1788              list(a))
    1789
    1790 -    def test_setslice_step_negative2(self):
    1791          Element = self.etree.Element
    1792          SubElement = self.etree.SubElement
    1793
    1794          a = Element('a')
    1795          b = SubElement(a, 'b')
    1796          c = SubElement(a, 'c')
    1797          d = SubElement(a, 'd')
    1798          e = SubElement(a, 'e')
    1799
    1800          x = Element('x')
    1801          y = Element('y')
    1802
    1803          a[::-2] = [x, y]
    1804          self.assertEquals(
    1805              [b, y, d, x],
    1806              list(a))
    1807
    1808 -    def test_setslice_step_overrun(self):
    1809          Element = self.etree.Element
    1810          SubElement = self.etree.SubElement
    1811          try:
    1812              slice
    1813          except NameError:
    1814              print("slice() not found")
    1815              return
    1816
    1817          a = Element('a')
    1818          b = SubElement(a, 'b')
    1819          c = SubElement(a, 'c')
    1820          d = SubElement(a, 'd')
    1821          e = SubElement(a, 'e')
    1822
    1823          x = Element('x')
    1824          y = Element('y')
    1825          z = Element('z')
    1826
    1827          self.assertRaises(
    1828              ValueError,
    1829              operator.setitem, a, slice(1,None,2), [x, y, z])
    1830
    1831          self.assertEquals(
    1832              [b, c, d, e],
    1833              list(a))
    1834
    1835 -    def test_sourceline_XML(self):
    1836          XML = self.etree.XML
    1837          root = XML(_bytes('''<?xml version="1.0"?>
    1838          <root><test>
    1839
    1840          <bla/></test>
    1841          </root>
    1842          '''))
    1843
    1844          self.assertEquals(
    1845              [2, 2, 4],
    1846              [ el.sourceline for el in root.getiterator() ])
    1847
    1848 -    def test_sourceline_parse(self):
    1849          parse = self.etree.parse
    1850          tree = parse(fileInTestDir('include/test_xinclude.xml'))
    1851
    1852          self.assertEquals(
    1853              [1, 2, 3],
    1854              [ el.sourceline for el in tree.getiterator() ])
    1855
    1856 -    def test_sourceline_iterparse_end(self):
    1857          iterparse = self.etree.iterparse
    1858          lines = [ el.sourceline for (event, el) in
    1859                    iterparse(fileInTestDir('include/test_xinclude.xml')) ]
    1860
    1861          self.assertEquals(
    1862              [2, 3, 1],
    1863              lines)
    1864
    1865 -    def test_sourceline_iterparse_start(self):
    1866          iterparse = self.etree.iterparse
    1867          lines = [ el.sourceline for (event, el) in
    1868                    iterparse(fileInTestDir('include/test_xinclude.xml'),
    1869                              events=("start",)) ]
    1870
    1871          self.assertEquals(
    1872              [1, 2, 3],
    1873              lines)
    1874
    1875 -    def test_sourceline_element(self):
    1876          Element = self.etree.Element
    1877          SubElement = self.etree.SubElement
    1878          el = Element("test")
    1879          self.assertEquals(None, el.sourceline)
    1880
    1881          child = SubElement(el, "test")
    1882          self.assertEquals(None, el.sourceline)
    1883          self.assertEquals(None, child.sourceline)
    1884
    1885 -    def test_XML_base_url_docinfo(self):
    1886          etree = self.etree
    1887          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    1888          docinfo = root.getroottree().docinfo
    1889          self.assertEquals(docinfo.URL, "http://no/such/url")
    1890
    1891 -    def test_XML_set_base_url_docinfo(self):
    1892          etree = self.etree
    1893          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    1894          docinfo = root.getroottree().docinfo
    1895          self.assertEquals(docinfo.URL, "http://no/such/url")
    1896          docinfo.URL = "https://secret/url"
    1897          self.assertEquals(docinfo.URL, "https://secret/url")
    1898
    1899 -    def test_parse_stringio_base_url(self):
    1900          etree = self.etree
    1901          tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
    1902          docinfo = tree.docinfo
    1903          self.assertEquals(docinfo.URL, "http://no/such/url")
    1904
    1905 -    def test_parse_base_url_docinfo(self):
    1906          etree = self.etree
    1907          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    1908                             base_url="http://no/such/url")
    1909          docinfo = tree.docinfo
    1910          self.assertEquals(docinfo.URL, "http://no/such/url")
    1911
    1912 -    def test_HTML_base_url_docinfo(self):
    1913          etree = self.etree
    1914          root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
    1915          docinfo = root.getroottree().docinfo
    1916          self.assertEquals(docinfo.URL, "http://no/such/url")
    1917
    1918 -    def test_docinfo_public(self):
    1919          etree = self.etree
    1920          xml_header = '<?xml version="1.0" encoding="ascii"?>'
    1921          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    1922          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    1923          doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
    1924
    1925          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    1926
    1927          tree = etree.parse(BytesIO(xml))
    1928          docinfo = tree.docinfo
    1929          self.assertEquals(docinfo.encoding,    "ascii")
    1930          self.assertEquals(docinfo.xml_version, "1.0")
    1931          self.assertEquals(docinfo.public_id,   pub_id)
    1932          self.assertEquals(docinfo.system_url,  sys_id)
    1933          self.assertEquals(docinfo.root_name,   'html')
    1934          self.assertEquals(docinfo.doctype, doctype_string)
    1935
    1936 -    def test_docinfo_system(self):
    1937          etree = self.etree
    1938          xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
    1939          sys_id = "some.dtd"
    1940          doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
    1941          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    1942
    1943          tree = etree.parse(BytesIO(xml))
    1944          docinfo = tree.docinfo
    1945          self.assertEquals(docinfo.encoding,    "UTF-8")
    1946          self.assertEquals(docinfo.xml_version, "1.0")
    1947          self.assertEquals(docinfo.public_id,   None)
    1948          self.assertEquals(docinfo.system_url,  sys_id)
    1949          self.assertEquals(docinfo.root_name,   'html')
    1950          self.assertEquals(docinfo.doctype, doctype_string)
    1951
    1952 -    def test_docinfo_empty(self):
    1953          etree = self.etree
    1954          xml = _bytes('<html><body></body></html>')
    1955          tree = etree.parse(BytesIO(xml))
    1956          docinfo = tree.docinfo
    1957          self.assertEquals(docinfo.encoding,    "UTF-8")
    1958          self.assertEquals(docinfo.xml_version, "1.0")
    1959          self.assertEquals(docinfo.public_id,   None)
    1960          self.assertEquals(docinfo.system_url,  None)
    1961          self.assertEquals(docinfo.root_name,   'html')
    1962          self.assertEquals(docinfo.doctype, '')
    1963
    1964 -    def test_xml_base(self):
    1965          etree = self.etree
    1966          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    1967          self.assertEquals(root.base, "http://no/such/url")
    1968          self.assertEquals(
    1969              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    1970          root.base = "https://secret/url"
    1971          self.assertEquals(root.base, "https://secret/url")
    1972          self.assertEquals(
    1973              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    1974              "https://secret/url")
    1975
    1976 -    def test_xml_base_attribute(self):
    1977          etree = self.etree
    1978          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    1979          self.assertEquals(root.base, "http://no/such/url")
    1980          self.assertEquals(
    1981              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    1982          root.set('{http://www.w3.org/XML/1998/namespace}base',
    1983                   "https://secret/url")
    1984          self.assertEquals(root.base, "https://secret/url")
    1985          self.assertEquals(
    1986              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    1987              "https://secret/url")
    1988
    1989 -    def test_html_base(self):
    1990          etree = self.etree
    1991          root = etree.HTML(_bytes("<html><body></body></html>"),
    1992                            base_url="http://no/such/url")
    1993          self.assertEquals(root.base, "http://no/such/url")
    1994
    1995 -    def test_html_base_tag(self):
    1996          etree = self.etree
    1997          root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
    1998          self.assertEquals(root.base, "http://no/such/url")
    1999
    2000 -    def test_parse_fileobject_unicode(self):
    2001          # parse from a file object that returns unicode strings
    2002          f = LargeFileLikeUnicode()
    2003          tree = self.etree.parse(f)
    2004          root = tree.getroot()
    2005          self.assert_(root.tag.endswith('root'))
    2006
    2007 -    def test_dtd_io(self):
    2008          # check that DTDs that go in also go back out
    2009          xml = _bytes('''\
    2010          <!DOCTYPE test SYSTEM "test.dtd" [
    2011            <!ENTITY entity "tasty">
    2012            <!ELEMENT test (a)>
    2013            <!ELEMENT a (#PCDATA)>
    2014          ]>
    2015          <test><a>test-test</a></test>\
    2016          ''')
    2017          tree = self.etree.parse(BytesIO(xml))
    2018          self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
    2019                           xml.replace(_bytes(" "), _bytes("")))
    2020
    2021 -    def test_byte_zero(self):
    2022          Element = self.etree.Element
    2023
    2024          a = Element('a')
    2025          self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
    2026          self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
    2027
    2028          self.assertRaises(ValueError, Element, 'ha\0ho')
    2029
    2030 -    def test_unicode_byte_zero(self):
    2031          Element = self.etree.Element
    2032
    2033          a = Element('a')
    2034          self.assertRaises(ValueError, setattr, a, "text",
    2035                            _str('ha\0ho'))
    2036          self.assertRaises(ValueError, setattr, a, "tail",
    2037                            _str('ha\0ho'))
    2038
    2039          self.assertRaises(ValueError, Element,
    2040                            _str('ha\0ho'))
    2041
    2042 -    def test_byte_invalid(self):
    2043          Element = self.etree.Element
    2044
    2045          a = Element('a')
    2046          self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
    2047          self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
    2048
    2049          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
    2050          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
    2051
    2052          self.assertRaises(ValueError, Element, 'ha\x07ho')
    2053          self.assertRaises(ValueError, Element, 'ha\x02ho')
    2054
    2055 -    def test_unicode_byte_invalid(self):
    2056          Element = self.etree.Element
    2057
    2058          a = Element('a')
    2059          self.assertRaises(ValueError, setattr, a, "text",
    2060                            _str('ha\x07ho'))
    2061          self.assertRaises(ValueError, setattr, a, "text",
    2062                            _str('ha\x02ho'))
    2063
    2064          self.assertRaises(ValueError, setattr, a, "tail",
    2065                            _str('ha\x07ho'))
    2066          self.assertRaises(ValueError, setattr, a, "tail",
    2067                            _str('ha\x02ho'))
    2068
    2069          self.assertRaises(ValueError, Element,
    2070                            _str('ha\x07ho'))
    2071          self.assertRaises(ValueError, Element,
    2072                            _str('ha\x02ho'))
    2073
    2074 -    def test_encoding_tostring_utf16(self):
    2075          # ElementTree fails to serialize this
    2076          tostring = self.etree.tostring
    2077          Element = self.etree.Element
    2078          SubElement = self.etree.SubElement
    2079
    2080          a = Element('a')
    2081          b = SubElement(a, 'b')
    2082          c = SubElement(a, 'c')
    2083
    2084          result = tostring(a, encoding='UTF-16')
    2085          self.assertEquals(_bytes('<a><b></b><c></c></a>'),
    2086                            canonicalize(result))
    2087
    2088 -    def test_tostring_none(self):
    2089          # ElementTree raises an AssertionError here
    2090          tostring = self.etree.tostring
    2091          self.assertRaises(TypeError, self.etree.tostring, None)
    2092
    2093 -    def test_tostring_pretty(self):
    2094          tostring = self.etree.tostring
    2095          Element = self.etree.Element
    2096          SubElement = self.etree.SubElement
    2097
    2098          a = Element('a')
    2099          b = SubElement(a, 'b')
    2100          c = SubElement(a, 'c')
    2101
    2102          result = tostring(a)
    2103          self.assertEquals(result, _bytes("<a><b/><c/></a>"))
    2104
    2105          result = tostring(a, pretty_print=False)
    2106          self.assertEquals(result, _bytes("<a><b/><c/></a>"))
    2107
    2108          result = tostring(a, pretty_print=True)
    2109          self.assertEquals(result, _bytes("<a>\n  <b/>\n  <c/>\n</a>\n"))
    2110
    2111 -    def test_tostring_with_tail(self):
    2112          tostring = self.etree.tostring
    2113          Element = self.etree.Element
    2114          SubElement = self.etree.SubElement
    2115
    2116          a = Element('a')
    2117          a.tail = "aTAIL"
    2118          b = SubElement(a, 'b')
    2119          b.tail = "bTAIL"
    2120          c = SubElement(a, 'c')
    2121
    2122          result = tostring(a)
    2123          self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    2124
    2125          result = tostring(a, with_tail=False)
    2126          self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>"))
    2127
    2128          result = tostring(a, with_tail=True)
    2129          self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    2130
    2131 -    def test_tostring_method_text_encoding(self):
    2132          tostring = self.etree.tostring
    2133          Element = self.etree.Element
    2134          SubElement = self.etree.SubElement
    2135
    2136          a = Element('a')
    2137          a.text = "A"
    2138          a.tail = "tail"
    2139          b = SubElement(a, 'b')
    2140          b.text = "B"
    2141          b.tail = _str("Søk på nettet")
    2142          c = SubElement(a, 'c')
    2143          c.text = "C"
    2144
    2145          result = tostring(a, method="text", encoding="UTF-16")
    2146
    2147          self.assertEquals(_str('ABSøk på nettetCtail').encode("UTF-16"),
    2148                            result)
    2149
    2150 -    def test_tostring_method_text_unicode(self):
    2151          tostring = self.etree.tostring
    2152          Element = self.etree.Element
    2153          SubElement = self.etree.SubElement
    2154
    2155          a = Element('a')
    2156          a.text = _str('Søk på nettetA')
    2157          a.tail = "tail"
    2158          b = SubElement(a, 'b')
    2159          b.text = "B"
    2160          b.tail = _str('Søk på nettetB')
    2161          c = SubElement(a, 'c')
    2162          c.text = "C"
    2163
    2164          self.assertRaises(UnicodeEncodeError,
    2165                            tostring, a, method="text")
    2166
    2167          self.assertEquals(
    2168              _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
    2169              tostring(a, encoding="UTF-8", method="text"))
    2170
    2171 -    def test_tounicode(self):
    2172          tounicode = self.etree.tounicode
    2173          Element = self.etree.Element
    2174          SubElement = self.etree.SubElement
    2175
    2176          a = Element('a')
    2177          b = SubElement(a, 'b')
    2178          c = SubElement(a, 'c')
    2179
    2180          self.assert_(isinstance(tounicode(a), _unicode))
    2181          self.assertEquals(_bytes('<a><b></b><c></c></a>'),
    2182                            canonicalize(tounicode(a)))
    2183
    2184 -    def test_tounicode_element(self):
    2185          tounicode = self.etree.tounicode
    2186          Element = self.etree.Element
    2187          SubElement = self.etree.SubElement
    2188
    2189          a = Element('a')
    2190          b = SubElement(a, 'b')
    2191          c = SubElement(a, 'c')
    2192          d = SubElement(c, 'd')
    2193          self.assert_(isinstance(tounicode(b), _unicode))
    2194          self.assert_(isinstance(tounicode(c), _unicode))
    2195          self.assertEquals(_bytes('<b></b>'),
    2196                            canonicalize(tounicode(b)))
    2197          self.assertEquals(_bytes('<c><d></d></c>'),
    2198                            canonicalize(tounicode(c)))
    2199
    2200 -    def test_tounicode_none(self):
    2201          tounicode = self.etree.tounicode
    2202          self.assertRaises(TypeError, self.etree.tounicode, None)
    2203
    2204 -    def test_tounicode_element_tail(self):
    2205          tounicode = self.etree.tounicode
    2206          Element = self.etree.Element
    2207          SubElement = self.etree.SubElement
    2208
    2209          a = Element('a')
    2210          b = SubElement(a, 'b')
    2211          c = SubElement(a, 'c')
    2212          d = SubElement(c, 'd')
    2213          b.tail = 'Foo'
    2214
    2215          self.assert_(isinstance(tounicode(b), _unicode))
    2216          self.assert_(tounicode(b) == '<b/>Foo' or
    2217                       tounicode(b) == '<b />Foo')
    2218
    2219 -    def test_tounicode_pretty(self):
    2220          tounicode = self.etree.tounicode
    2221          Element = self.etree.Element
    2222          SubElement = self.etree.SubElement
    2223
    2224          a = Element('a')
    2225          b = SubElement(a, 'b')
    2226          c = SubElement(a, 'c')
    2227
    2228          result = tounicode(a)
    2229          self.assertEquals(result, "<a><b/><c/></a>")
    2230
    2231          result = tounicode(a, pretty_print=False)
    2232          self.assertEquals(result, "<a><b/><c/></a>")
    2233
    2234          result = tounicode(a, pretty_print=True)
    2235          self.assertEquals(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    2236
    2237 -    def test_tostring_unicode(self):
    2238          tostring = self.etree.tostring
    2239          Element = self.etree.Element
    2240          SubElement = self.etree.SubElement
    2241
    2242          a = Element('a')
    2243          b = SubElement(a, 'b')
    2244          c = SubElement(a, 'c')
    2245
    2246          self.assert_(isinstance(tostring(a, encoding=_unicode), _unicode))
    2247          self.assertEquals(_bytes('<a><b></b><c></c></a>'),
    2248                            canonicalize(tostring(a, encoding=_unicode)))
    2249
    2250 -    def test_tostring_unicode_element(self):
    2251          tostring = self.etree.tostring
    2252          Element = self.etree.Element
    2253          SubElement = self.etree.SubElement
    2254
    2255          a = Element('a')
    2256          b = SubElement(a, 'b')
    2257          c = SubElement(a, 'c')
    2258          d = SubElement(c, 'd')
    2259          self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
    2260          self.assert_(isinstance(tostring(c, encoding=_unicode), _unicode))
    2261          self.assertEquals(_bytes('<b></b>'),
    2262                            canonicalize(tostring(b, encoding=_unicode)))
    2263          self.assertEquals(_bytes('<c><d></d></c>'),
    2264                            canonicalize(tostring(c, encoding=_unicode)))
    2265
    2266 -    def test_tostring_unicode_none(self):
    2267          tostring = self.etree.tostring
    2268          self.assertRaises(TypeError, self.etree.tostring,
    2269                            None, encoding=_unicode)
    2270
    2271 -    def test_tostring_unicode_element_tail(self):
    2272          tostring = self.etree.tostring
    2273          Element = self.etree.Element
    2274          SubElement = self.etree.SubElement
    2275
    2276          a = Element('a')
    2277          b = SubElement(a, 'b')
    2278          c = SubElement(a, 'c')
    2279          d = SubElement(c, 'd')
    2280          b.tail = 'Foo'
    2281
    2282          self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
    2283          self.assert_(tostring(b, encoding=_unicode) == '<b/>Foo' or
    2284                       tostring(b, encoding=_unicode) == '<b />Foo')
    2285
    2286 -    def test_tostring_unicode_pretty(self):
    2287          tostring = self.etree.tostring
    2288          Element = self.etree.Element
    2289          SubElement = self.etree.SubElement
    2290
    2291          a = Element('a')
    2292          b = SubElement(a, 'b')
    2293          c = SubElement(a, 'c')
    2294
    2295          result = tostring(a, encoding=_unicode)
    2296          self.assertEquals(result, "<a><b/><c/></a>")
    2297
    2298          result = tostring(a, encoding=_unicode, pretty_print=False)
    2299          self.assertEquals(result, "<a><b/><c/></a>")
    2300
    2301          result = tostring(a, encoding=_unicode, pretty_print=True)
    2302          self.assertEquals(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    2303
    2304      # helper methods
    2305
    2306 -    def _writeElement(self, element, encoding='us-ascii'):
    2307          """Write out element for comparison.
    2308          """
    2309          ElementTree = self.etree.ElementTree
    2310          f = BytesIO()
    2311          tree = ElementTree(element=element)
    2312          tree.write(f, encoding=encoding)
    2313          data = f.getvalue()
    2314          return canonicalize(data)
    2315
    2316
    2317 -class XIncludeTestCase(HelperTestCase):
    2318 -    def test_xinclude_text(self):
    2319          filename = fileInTestDir('test_broken.xml')
    2320          root = etree.XML(_bytes('''\
    2321          <doc xmlns:xi="http://www.w3.org/2001/XInclude">
    2322            <xi:include href="%s" parse="text"/>
    2323          </doc>
    2324          ''' % filename))
    2325          old_text = root.text
    2326          content = open(filename).read()
    2327          old_tail = root[0].tail
    2328
    2329          self.include( etree.ElementTree(root) )
    2330          self.assertEquals(old_text + content + old_tail,
    2331                            root.text)
    2332
    2333 -    def test_xinclude(self):
    2334          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
    2335          self.assertNotEquals(
    2336              'a',
    2337              tree.getroot()[1].tag)
    2338          # process xincludes
    2339          self.include( tree )
    2340          # check whether we find it replaced with included data
    2341          self.assertEquals(
    2342              'a',
    2343              tree.getroot()[1].tag)
    2344
    2345 -    def test_xinclude_resolver(self):
    2346          class res(etree.Resolver):
    2347              include_text = open(fileInTestDir('test.xml')).read()
    2348              called = {}
    2349              def resolve(self, url, id, context):
    2350                  if url.endswith(".dtd"):
    2351                      self.called["dtd"] = True
    2352                      return self.resolve_filename(
    2353                          fileInTestDir('test.dtd'), context)
    2354                  elif url.endswith("test_xinclude.xml"):
    2355                      self.called["input"] = True
    2356                      return None # delegate to default resolver
    2357                  else:
    2358                      self.called["include"] = True
    2359                      return self.resolve_string(self.include_text, context)
    2360
    2361          res_instance = res()
    2362          parser = etree.XMLParser(load_dtd = True)
    2363          parser.resolvers.add(res_instance)
    2364
    2365          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    2366                             parser = parser)
    2367
    2368          self.include(tree)
    2369
    2370          called = list(res_instance.called.items())
    2371          called.sort()
    2372          self.assertEquals(
    2373              [("dtd", True), ("include", True), ("input", True)],
    2374              called)
    2375
    2376 -class ETreeXIncludeTestCase(XIncludeTestCase):
    2377 -    def include(self, tree):
    2378          tree.xinclude()
    2379
    2380
    2381 -class ElementIncludeTestCase(XIncludeTestCase):
    2382      from lxml import ElementInclude
    2383 -    def include(self, tree):
    2384          self.ElementInclude.include(tree.getroot())
    2385
    2386
    2387 -class ETreeC14NTestCase(HelperTestCase):
    2388 -    def test_c14n(self):
    2389          tree = self.parse(_bytes('<a><b/></a>'))
    2390          f = BytesIO()
    2391          tree.write_c14n(f)
    2392          s = f.getvalue()
    2393          self.assertEquals(_bytes('<a><b></b></a>'),
    2394                            s)
    2395
    2396 -def test_suite():
    2397      suite = unittest.TestSuite()
    2398      suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
    2399      suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
    2400      suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
    2401      suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
    2402      suite.addTests(
    2403          [make_doctest('../../../doc/tutorial.txt')])
    2404      suite.addTests(
    2405          [make_doctest('../../../doc/api.txt')])
    2406      suite.addTests(
    2407          [make_doctest('../../../doc/FAQ.txt')])
    2408      suite.addTests(
    2409          [make_doctest('../../../doc/parsing.txt')])
    2410      suite.addTests(
    2411          [make_doctest('../../../doc/resolvers.txt')])
    2412      return suite
    2413
    2414  if __name__ == '__main__':
    2415      print('to test use test.py %s' % __file__)
    2416