@@ -1358,6 +1358,192 @@ def test_attlist_default(self):
13581358 {'{http://www.w3.org/XML/1998/namespace}lang' : 'eng' })
13591359
13601360
1361+ class XMLValidationTest (unittest .TestCase ):
1362+
1363+ def check (self , elem , expected = None ):
1364+ self .assertRaises (ValueError ,
1365+ ET .tostring , elem , validate = True )
1366+ ET .tostring (elem ) # no exception
1367+
1368+ def test_invalid_comment (self ):
1369+ self .check (ET .Comment ('a--b' ))
1370+ self .check (ET .Comment (' B+, B, or B-' ))
1371+
1372+ def test_invalid_processing_instruction (self ):
1373+ self .check (ET .PI ('' ))
1374+ self .check (ET .PI ('0' ))
1375+ self .check (ET .PI ('a/b' ))
1376+ self .check (ET .PI ('foo\xa0 bar' ))
1377+ self .check (ET .PI ('xml' ))
1378+ self .check (ET .PI ('xml' , 'encoding="UTF-8"' ))
1379+ self .check (ET .PI ('foo' , 'a?>b' ))
1380+ self .check (ET .PI ('foo' , '\x00 ' ))
1381+ self .check (ET .PI ('foo' , '\ud8ff ' ))
1382+ self .check (ET .PI ('foo' , '\ufffe ' ))
1383+
1384+ def test_invalid_tag (self ):
1385+ self .check (ET .Element ('' ))
1386+ self .check (ET .Element ('0' ))
1387+ self .check (ET .Element ('a/b' ))
1388+ self .check (ET .Element (ET .QName ('' )))
1389+ self .check (ET .Element (ET .QName ('0' )))
1390+ self .check (ET .Element (ET .QName ('a/b' )))
1391+
1392+ def test_invalid_attr_name (self ):
1393+ self .check (ET .Element ('tag' , attrib = {'' : 'value' }))
1394+ self .check (ET .Element ('tag' , attrib = {'0' : 'value' }))
1395+ self .check (ET .Element ('tag' , attrib = {'a/b' : 'value' }))
1396+ self .check (ET .Element ('tag' , attrib = {ET .QName ('' ): 'value' }))
1397+ self .check (ET .Element ('tag' , attrib = {ET .QName ('0' ): 'value' }))
1398+ self .check (ET .Element ('tag' , attrib = {ET .QName ('a/b' ): 'value' }))
1399+
1400+ def test_invalid_attr_value (self ):
1401+ self .check (ET .Element ('tag' , attrib = {'key' : '\x00 ' }))
1402+ self .check (ET .Element ('tag' , attrib = {'key' : '\ud8ff ' }))
1403+ self .check (ET .Element ('tag' , attrib = {'key' : '\ufffe ' }))
1404+ self .check (ET .Element ('tag' , attrib = {'key' : ET .QName ('\x00 ' )}))
1405+ self .check (ET .Element ('tag' , attrib = {'key' : ET .QName ('\ud8ff ' )}))
1406+ self .check (ET .Element ('tag' , attrib = {'key' : ET .QName ('\ufffe ' )}))
1407+
1408+ def test_invalid_text (self ):
1409+ elem = ET .Element ('tag' )
1410+ elem .text = '\x00 '
1411+ self .check (elem )
1412+ elem .text = '\ud8ff '
1413+ self .check (elem )
1414+ elem .text = '\ufffe '
1415+ self .check (elem )
1416+
1417+ def test_invalid_tail (self ):
1418+ elem = ET .Element ('tag' )
1419+ elem .tail = '\x00 '
1420+ self .check (elem )
1421+ elem .tail = '\ud8ff '
1422+ self .check (elem )
1423+ elem .tail = '\ufffe '
1424+ self .check (elem )
1425+
1426+ def test_invalid_text_without_tag (self ):
1427+ elem = ET .Element (None )
1428+ elem .text = '\x00 '
1429+ self .check (elem )
1430+ elem .text = '\ud8ff '
1431+ self .check (elem )
1432+ elem .text = '\ufffe '
1433+ self .check (elem )
1434+
1435+ def test_invalid_subelements (self ):
1436+ elem = ET .Element ('tag' )
1437+ subelem = ET .SubElement (elem , 'subtag' )
1438+ ET .SubElement (subelem , '\x00 ' )
1439+ self .check (elem )
1440+ elem .tag = None
1441+ self .check (elem )
1442+
1443+ def test_invalid_namespace_uri (self ):
1444+ self .check (ET .Element ('{\x00 }tag' ))
1445+ self .check (ET .Element ('{\ud8ff }tag' ))
1446+ self .check (ET .Element ('{\ufffe }tag' ))
1447+ self .check (ET .Element (ET .QName ('\x00 ' , 'tag' )))
1448+ self .check (ET .Element (ET .QName ('\ud8ff ' , 'tag' )))
1449+ self .check (ET .Element (ET .QName ('\ufffe ' , 'tag' )))
1450+
1451+ class HTMLValidationTest (unittest .TestCase ):
1452+
1453+ def check (self , elem , expected = None ):
1454+ self .assertRaises (ValueError ,
1455+ ET .tostring , elem , method = 'html' , validate = True )
1456+ ET .tostring (elem , method = 'html' ) # no exception
1457+
1458+ def test_invalid_comment (self ):
1459+ self .check (ET .Comment ('>' ))
1460+ self .check (ET .Comment ('->' ))
1461+ self .check (ET .Comment ('a-->b' ))
1462+ self .check (ET .Comment ('a--!>b' ))
1463+ self .check (ET .Comment ('a\x00 b' ))
1464+
1465+ def test_invalid_processing_instruction (self ):
1466+ self .check (ET .PI ('a>b' ))
1467+ self .check (ET .PI ('a\x00 b' ))
1468+
1469+ def test_invalid_tag (self ):
1470+ self .check (ET .Element ('' ))
1471+ self .check (ET .Element ('?' ))
1472+ self .check (ET .Element ('!' ))
1473+ self .check (ET .Element ('0' ))
1474+ self .check (ET .Element (' a' ))
1475+ self .check (ET .Element ('a b' ))
1476+ self .check (ET .Element ('a\n b' ))
1477+ self .check (ET .Element ('a/b' ))
1478+ self .check (ET .Element ('a>b' ))
1479+ self .check (ET .Element ('a\x00 b' ))
1480+ self .check (ET .Element (ET .QName ('' )))
1481+ self .check (ET .Element (ET .QName ('0' )))
1482+ self .check (ET .Element (ET .QName ('a/b' )))
1483+
1484+ def test_invalid_attr_name (self ):
1485+ self .check (ET .Element ('tag' , attrib = {'' : 'value' }))
1486+ self .check (ET .Element ('tag' , attrib = {'a/b' : 'value' }))
1487+ self .check (ET .Element ('tag' , attrib = {'a=b' : 'value' }))
1488+ self .check (ET .Element ('tag' , attrib = {ET .QName ('' ): 'value' }))
1489+ self .check (ET .Element ('tag' , attrib = {ET .QName ('a/b' ): 'value' }))
1490+
1491+ def test_invalid_attr_value (self ):
1492+ self .check (ET .Element ('tag' , attrib = {'key' : '\x00 ' }))
1493+ self .check (ET .Element ('tag' , attrib = {'key' : ET .QName ('\x00 ' )}))
1494+ self .check (ET .Element ('tag' , attrib = {'key' : ET .QName ('a"b' )}))
1495+ self .check (ET .Element ('tag' , attrib = {'key' : ET .QName ('a&b' )}))
1496+
1497+ def test_invalid_text (self ):
1498+ elem = ET .Element ('tag' )
1499+ elem .text = '\x00 '
1500+ self .check (elem )
1501+
1502+ def test_invalid_tail (self ):
1503+ elem = ET .Element ('tag' )
1504+ elem .tail = '\x00 '
1505+ self .check (elem )
1506+
1507+ def test_invalid_text_without_tag (self ):
1508+ elem = ET .Element (None )
1509+ elem .text = '\x00 '
1510+ self .check (elem )
1511+
1512+ def test_invalid_subelements (self ):
1513+ elem = ET .Element ('tag' )
1514+ subelem = ET .SubElement (elem , 'subtag' )
1515+ ET .SubElement (subelem , '\x00 ' )
1516+ self .check (elem )
1517+ elem .tag = None
1518+ self .check (elem )
1519+
1520+ def test_invalid_namespace_uri (self ):
1521+ self .check (ET .Element ('{\x00 }tag' ))
1522+ self .check (ET .Element (ET .QName ('\x00 ' , 'tag' )))
1523+
1524+ @support .subTests ('tag' , ("script" , "style" , "xmp" , "iframe" , "noembed" , "noframes" ))
1525+ def test_invalid_cdata_content (self , tag ):
1526+ elem = ET .Element (tag .upper ())
1527+ elem .text = 'a</%s>b' % tag .title ()
1528+ self .check (elem )
1529+ elem .text = 'a</%s b' % tag .title ()
1530+ self .check (elem )
1531+ elem .text = 'a</%s/b' % tag .title ()
1532+ self .check (elem )
1533+ elem .text = 'a\x00 b'
1534+ self .check (elem )
1535+
1536+ @support .subTests ('tag' , ("script" , "style" , "xmp" , "iframe" , "noembed" , "noframes" ))
1537+ def test_cdata_subelements (self , tag ):
1538+ elem = ET .Element (tag )
1539+ ET .SubElement (elem , 'subtag' )
1540+ self .check (elem )
1541+
1542+ def test_invalid_plaintext_content (self ):
1543+ elem = ET .Element ('plaintext' )
1544+ elem .text = 'a\x00 b'
1545+ self .check (elem )
1546+
13611547class IterparseTest (unittest .TestCase ):
13621548 # Test iterparse interface.
13631549
0 commit comments