@@ -617,32 +617,76 @@ def testAltNewline(self):
617617 self .assertEqual (domstr , str .replace ("\n " , "\r \n " ))
618618
619619 def test_toprettyxml_with_text_nodes (self ):
620- # see issue #4147, text nodes are not indented
620+ # see gh-48397 and gh-81623,
621+ # the content of an element with text is not changed
621622 decl = '<?xml version="1.0" ?>\n '
622623 self .assertEqual (parseString ('<B>A</B>' ).toprettyxml (),
623624 decl + '<B>A</B>\n ' )
624625 self .assertEqual (parseString ('<C>A<B>A</B></C>' ).toprettyxml (),
625- decl + '<C>\n \t A \n \t <B>A</B>\n </C>\n ' )
626+ decl + '<C>A <B>A</B></C>\n ' )
626627 self .assertEqual (parseString ('<C><B>A</B>A</C>' ).toprettyxml (),
627- decl + '<C>\n \t <B>A</B>\n \t A \n </C>\n ' )
628+ decl + '<C><B>A</B>A </C>\n ' )
628629 self .assertEqual (parseString ('<C><B>A</B><B>A</B></C>' ).toprettyxml (),
629630 decl + '<C>\n \t <B>A</B>\n \t <B>A</B>\n </C>\n ' )
630631 self .assertEqual (parseString ('<C><B>A</B>A<B>A</B></C>' ).toprettyxml (),
631- decl + '<C>\n \t <B>A</B>\n \t A\n \t <B>A</B>\n </C>\n ' )
632+ decl + '<C><B>A</B>A<B>A</B></C>\n ' )
633+ # toprettyxml treats whitespace between elements as insignificant
634+ self .assertEqual (parseString ('<C> <B>A</B> </C>' ).toprettyxml (),
635+ decl + '<C>\n \t \n \t <B>A</B>\n \t \n </C>\n ' )
632636
633637 def test_toprettyxml_with_adjacent_text_nodes (self ):
634- # see issue #4147 , adjacent text nodes are indented normally
638+ # see gh-81623 , adjacent text nodes are not separated
635639 dom = Document ()
636640 elem = dom .createElement ('elem' )
637641 elem .appendChild (dom .createTextNode ('TEXT' ))
638642 elem .appendChild (dom .createTextNode ('TEXT' ))
639643 dom .appendChild (elem )
640644 decl = '<?xml version="1.0" ?>\n '
641- self .assertEqual (dom .toprettyxml (),
642- decl + '<elem>\n \t TEXT\n \t TEXT\n </elem>\n ' )
645+ self .assertEqual (dom .toprettyxml (), decl + '<elem>TEXTTEXT</elem>\n ' )
646+
647+ def test_toprettyxml_preserve (self ):
648+ decl = '<?xml version="1.0" ?>\n '
649+ # xml:space="preserve" applies to the whole subtree
650+ self .assertEqual (
651+ parseString ('<C xml:space="preserve"><B>A</B><B>A</B></C>'
652+ ).toprettyxml (),
653+ decl + '<C xml:space="preserve"><B>A</B><B>A</B></C>\n ' )
654+ self .assertEqual (
655+ parseString ('<C xml:space="preserve"><B><D/></B></C>'
656+ ).toprettyxml (),
657+ decl + '<C xml:space="preserve"><B><D/></B></C>\n ' )
658+ # other values do not preserve whitespace
659+ self .assertEqual (
660+ parseString ('<C xml:space="default"><B>A</B></C>' ).toprettyxml (),
661+ decl + '<C xml:space="default">\n \t <B>A</B>\n </C>\n ' )
662+
663+ def test_toprettyxml_with_non_xml_whitespace (self ):
664+ # only " \t\r\n" are whitespace in XML (see XML 1.0, 2.3)
665+ decl = '<?xml version="1.0" ?>\n '
666+ self .assertEqual (parseString ('<C>\xa0 <B>A</B></C>' ).toprettyxml (),
667+ decl + '<C>\xa0 <B>A</B></C>\n ' )
668+
669+ def test_toprettyxml_with_dtd (self ):
670+ decl = '<?xml version="1.0" ?>\n '
671+ # only whitespace in element content is ignorable
672+ doctype = ('<!DOCTYPE C [<!ELEMENT C (#PCDATA|B)*>'
673+ '<!ELEMENT B (#PCDATA)>]>' )
674+ self .assertEqual (
675+ parseString (doctype + '<C><B>A</B><B>A</B></C>' ).toprettyxml (),
676+ decl + doctype + '\n <C><B>A</B><B>A</B></C>\n ' )
677+ doctype = '<!DOCTYPE C [<!ELEMENT C (B)*><!ELEMENT B (#PCDATA)>]>'
678+ self .assertEqual (
679+ parseString (doctype + '<C><B>A</B><B>A</B></C>' ).toprettyxml (),
680+ decl + doctype + '\n <C>\n \t <B>A</B>\n \t <B>A</B>\n </C>\n ' )
681+
682+ def test_toprettyxml_with_cdata_section (self ):
683+ decl = '<?xml version="1.0" ?>\n '
684+ self .assertEqual (
685+ parseString ('<C><![CDATA[A]]><B>A</B></C>' ).toprettyxml (),
686+ decl + '<C><![CDATA[A]]><B>A</B></C>\n ' )
643687
644688 def test_toprettyxml_preserves_content_of_text_node (self ):
645- # see issue #4147
689+ # see gh-48397
646690 for str in ('<B>A</B>' , '<A><B>C</B></A>' ):
647691 dom = parseString (str )
648692 dom2 = parseString (dom .toprettyxml ())
0 commit comments