def test_nested_processing_instructions(self): element = Element("<Element><?Target1?><?Target2 data?></Element>") element.parse_to_end({}) self.assertEqual("Target1", element.content[0].target) self.assertEqual("Target1", element.processing_instructions[0].target) self.assertEqual("Target2", element.content[1].target) self.assertEqual("Target2", element.processing_instructions[1].target)
def test_ends_parse_on_close(self): with self.subTest("Self-closing"): element = Element("<Element/> some text") unparsed_xml = element.parse_to_end({}) self.assertEqual(" some text", unparsed_xml) with self.subTest("Open"): element = Element("<Element>some text</Element> some more text") unparsed_xml = element.parse_to_end({}) self.assertEqual(" some more text", unparsed_xml)
def test_name_parsing(self): with self.subTest("Self-closing"): element = Element("<Element/> some text") element.parse_to_end({}) self.assertEqual("Element", element.name) with self.subTest("Open"): element = Element("<Element>some text</Element> some more text") element.parse_to_end({}) self.assertEqual("Element", element.name)
def test_nested_elements(self): element = Element("<Element><SubElement><SubSubElement></SubSubElement></SubElement></Element>") element.parse_to_end({}) self.assertEqual("SubElement", element.content[0].name) self.assertEqual("SubElement", element.children[0].name) self.assertEqual("SubSubElement", element.content[0].content[0].name) self.assertEqual("SubSubElement", element.children[0].children[0].name)
def test_disallowed_xml_name(self): with self.subTest("xml"): element = Element("<xmlElement/>") with self.assertRaises(XMLError): element.parse_to_end({}) with self.subTest("XmL"): element = Element("<XmLElement/>") with self.assertRaises(XMLError): element.parse_to_end({})
def test_disallowed_attribute_entity_replacement_character(self): with self.subTest("Disallow <"): entity = MockEntity("entity", expansion_text="<") element = Element("<Element attr='blah&entity;blah'/>") with self.assertRaises(XMLError): element.parse_to_end({"entity": entity}) with self.subTest("Allow <"): lt = MockEntity("lt", "<") element = Element("<Element attr='blah<blah'/>") element.parse_to_end({"lt": lt})
def test_nested_mixed(self): element = Element( "<Element>Some text<SubElement>More text</SubElement> <!-- comment --><?Target data?></Element>") element.parse_to_end({}) self.assertEqual("Some text", element.content[0].text) self.assertEqual("Some text", element.text[0].text) self.assertEqual("SubElement", element.content[1].name) self.assertEqual("SubElement", element.children[0].name) self.assertEqual("More text", element.content[1].text[0].text) self.assertEqual(" ", element.content[2].text) self.assertEqual(" ", element.text[1].text) self.assertEqual("Target", element.content[3].target) self.assertEqual("Target", element.processing_instructions[0].target) self.assertEqual(4, len(element.content))
def test_attribute_parsing(self): with self.subTest("Self-closing - \' delimiters"): element = Element("<Element attr='Value'/> some text") element.parse_to_end({}) self.assertEqual({"attr": "Value"}, element.attributes) with self.subTest("Self-closing - \" delimiters"): element = Element("<Element attr=\"Value\"/> some text") element.parse_to_end({}) self.assertEqual({"attr": "Value"}, element.attributes) with self.subTest("Self-closing - with whitespace"): element = Element("<Element attr = \"Value\"/> some text") element.parse_to_end({}) self.assertEqual({"attr": "Value"}, element.attributes) with self.subTest("Open"): element = Element("<Element attr='Value'>some text</Element> some more text") element.parse_to_end({}) self.assertEqual({"attr": "Value"}, element.attributes)
def test_attribute_ignores_parameter_entity(self): element = Element("<Element attr='Entity %entity; text'/>") element.parse_to_end({}) self.assertEqual("Entity %entity; text", element.attributes["attr"])
def test_attribute_missing_general_entity(self): element = Element("<Element attr='Entity &entity; text'/>") with self.assertRaises(XMLError): element.parse_to_end({})
def test_attribute_general_entity_replacement(self): entity = MockEntity("entity", expansion_text="ENTITY TEXT") element = Element("<Element attr='Entity &entity; text'/>") element.parse_to_end({"entity": entity}) self.assertEqual("Entity ENTITY TEXT text", element.attributes["attr"])
def test_multiple_attribute_parsing(self): element = Element("<Element attr1='Value1' attr2='Value2'/> some text") element.parse_to_end({}) self.assertEqual({"attr1": "Value1", "attr2": "Value2"}, element.attributes)
def test_disallowed_name_characters(self): for char in ["\u0001", "\u0003", "\u0010", "\ufffe", "\uffff"]: with self.subTest(char): element = Element(f"<{char}xmlElement/>") with self.assertRaises(XMLError): element.parse_to_end({})
def test_disallowed_name_start_characters(self): for char in ["-", ".", "0", "7", "\u0305"]: with self.subTest(char): element = Element(f"<{char}xmlElement/>") with self.assertRaises(XMLError): element.parse_to_end({})
def test_disallowed_attribute_characters(self): for char in ["<", "&", "\u0001", "\u0003", "\u0010", "\ufffe", "\uffff"]: with self.subTest(char): element = Element(f"<Element attr='Blah{char}'/>") with self.assertRaises(XMLError): element.parse_to_end({})
def test_attribute_decimal_character_reference_replacement(self): for num, char in [(118, "v"), (279, "ė"), (632, "ɸ"), (986, "Ϛ"), (1948, "ޜ")]: with self.subTest(f"&#{num}; -> {char}"): element = Element(f"<Element attr='Entity &#{num}; text'/>") element.parse_to_end({}) self.assertEqual(f"Entity {char} text", element.attributes["attr"])
def test_nested_text(self): element = Element("<Element>Some text here</Element>") element.parse_to_end({}) self.assertEqual("Some text here", element.content[0].text) self.assertEqual("Some text here", element.text[0].text)
def test_mismatched_tags(self): element = Element("<Element1>some text</Element2> some more text") with self.assertRaises(XMLError): element.parse_to_end({})
def test_attribute_hexadecimal_character_reference_replacement(self): for num, char in [("76", "v"), ("117", "ė"), ("278", "ɸ"), ("3da", "Ϛ"), ("79c", "ޜ")]: with self.subTest(f"&#{num}; -> {char}"): element = Element(f"<Element attr='Entity &#x{num}; text'/>") element.parse_to_end({}) self.assertEqual(f"Entity {char} text", element.attributes["attr"])
def test_repeated_attribute(self): element = Element("<Element attr='value' attr='value'/>") with self.assertRaises(XMLError): element.parse_to_end({})