@@ -337,3 +337,126 @@ def test_rejects_names_with_quotes_and_equals(self):
337
337
for prefix in ['a"b' , "a'b" , "a=b" ]:
338
338
with self .assertRaises (ValueError ):
339
339
unparse ({"a" : {"@xmlns" : {prefix : "http://e/" }}}, full_document = False )
340
+
341
+ def test_pretty_print_and_short_empty_elements_consistency (self ):
342
+ """Test that pretty and compact modes produce equivalent results when stripped.
343
+
344
+ This test covers issue #352: Edge case with pretty_print and short_empty_elements.
345
+ When short_empty_elements=True, empty elements should be written as <tag/>
346
+ regardless of whether pretty printing is enabled.
347
+ """
348
+ # Test case from issue #352: empty list child
349
+ input_dict = {"Foos" : {"Foo" : []}}
350
+
351
+ compact = unparse (
352
+ input_dict , pretty = False , short_empty_elements = True , full_document = False
353
+ )
354
+ pretty = unparse (
355
+ input_dict , pretty = True , short_empty_elements = True , full_document = False
356
+ )
357
+ pretty_compacted = pretty .replace ("\n " , "" ).replace ("\t " , "" )
358
+
359
+ # They should be equal when pretty formatting is stripped
360
+ self .assertEqual (pretty_compacted , compact )
361
+ self .assertEqual (compact , "<Foos/>" )
362
+ self .assertEqual (pretty_compacted , "<Foos/>" )
363
+
364
+ def test_empty_list_filtering (self ):
365
+ """Test that empty lists are filtered out and don't create empty child elements."""
366
+ # Test various cases with empty lists
367
+ test_cases = [
368
+ # Case 1: Single empty list child
369
+ ({"Foos" : {"Foo" : []}}, "<Foos/>" ),
370
+ # Case 2: Multiple empty list children
371
+ ({"Foos" : {"Foo" : [], "Bar" : []}}, "<Foos/>" ),
372
+ # Case 3: Mixed empty and non-empty children
373
+ ({"Foos" : {"Foo" : [], "Bar" : "value" }}, "<Foos><Bar>value</Bar></Foos>" ),
374
+ # Case 4: Nested empty lists
375
+ ({"Foos" : {"Foo" : {"Bar" : []}}}, "<Foos><Foo/></Foos>" ),
376
+ # Case 5: Empty list with attributes
377
+ ({"Foos" : {"@attr" : "value" , "Foo" : []}}, '<Foos attr="value"/>' ),
378
+ ]
379
+
380
+ for input_dict , expected_compact in test_cases :
381
+ with self .subTest (input_dict = input_dict ):
382
+ # Test compact mode
383
+ compact = unparse (
384
+ input_dict ,
385
+ pretty = False ,
386
+ short_empty_elements = True ,
387
+ full_document = False ,
388
+ )
389
+ self .assertEqual (compact , expected_compact )
390
+
391
+ # Test pretty mode
392
+ pretty = unparse (
393
+ input_dict ,
394
+ pretty = True ,
395
+ short_empty_elements = True ,
396
+ full_document = False ,
397
+ )
398
+ pretty_compacted = pretty .replace ("\n " , "" ).replace ("\t " , "" )
399
+ self .assertEqual (pretty_compacted , expected_compact )
400
+
401
+ def test_empty_list_filtering_with_short_empty_elements_false (self ):
402
+ """Test that empty lists are still filtered when short_empty_elements=False."""
403
+ input_dict = {"Foos" : {"Foo" : []}}
404
+
405
+ # With short_empty_elements=False, empty elements should be <tag></tag>
406
+ compact = unparse (
407
+ input_dict , pretty = False , short_empty_elements = False , full_document = False
408
+ )
409
+ pretty = unparse (
410
+ input_dict , pretty = True , short_empty_elements = False , full_document = False
411
+ )
412
+ pretty_compacted = pretty .replace ("\n " , "" ).replace ("\t " , "" )
413
+
414
+ # They should be equal when pretty formatting is stripped
415
+ self .assertEqual (pretty_compacted , compact )
416
+ self .assertEqual (compact , "<Foos></Foos>" )
417
+ self .assertEqual (pretty_compacted , "<Foos></Foos>" )
418
+
419
+ def test_non_empty_lists_are_not_filtered (self ):
420
+ """Test that non-empty lists are not filtered out."""
421
+ # Test with non-empty lists
422
+ input_dict = {"Foos" : {"Foo" : ["item1" , "item2" ]}}
423
+
424
+ compact = unparse (
425
+ input_dict , pretty = False , short_empty_elements = True , full_document = False
426
+ )
427
+ pretty = unparse (
428
+ input_dict , pretty = True , short_empty_elements = True , full_document = False
429
+ )
430
+ pretty_compacted = pretty .replace ("\n " , "" ).replace ("\t " , "" )
431
+
432
+ # The lists should be processed normally
433
+ self .assertEqual (pretty_compacted , compact )
434
+ self .assertEqual (compact , "<Foos><Foo>item1</Foo><Foo>item2</Foo></Foos>" )
435
+ self .assertEqual (
436
+ pretty_compacted , "<Foos><Foo>item1</Foo><Foo>item2</Foo></Foos>"
437
+ )
438
+
439
+ def test_empty_dict_vs_empty_list_behavior (self ):
440
+ """Test the difference between empty dicts and empty lists."""
441
+ # Empty dict should create a child element
442
+ input_dict_dict = {"Foos" : {"Foo" : {}}}
443
+ compact_dict = unparse (
444
+ input_dict_dict ,
445
+ pretty = False ,
446
+ short_empty_elements = True ,
447
+ full_document = False ,
448
+ )
449
+ self .assertEqual (compact_dict , "<Foos><Foo/></Foos>" )
450
+
451
+ # Empty list should be filtered out
452
+ input_dict_list = {"Foos" : {"Foo" : []}}
453
+ compact_list = unparse (
454
+ input_dict_list ,
455
+ pretty = False ,
456
+ short_empty_elements = True ,
457
+ full_document = False ,
458
+ )
459
+ self .assertEqual (compact_list , "<Foos/>" )
460
+
461
+ # They should be different
462
+ self .assertNotEqual (compact_dict , compact_list )
0 commit comments