Files
SIA/sia/util.py
2024-11-11 14:23:08 +01:00

69 lines
2.4 KiB
Python

import xml.dom.minidom
import xml.etree.ElementTree as ET
from typing import Iterator, Optional
def stop_before_value(iterator: Iterator[str], stop_value: str) -> Iterator[str]:
"""
Creates an iterator that yields values from the input iterator
until it encounters the stop_value (exclusive).
Args:
iterator: The source iterator
stop_value: The value to stop before
Yields:
Values from the iterator until stop_value is encountered
If stop_value is part of an item, yields the part before stop_value
"""
for item in iterator:
if stop_value in item:
split_point = item.index(stop_value)
if split_point > 0:
yield item[:split_point]
break
yield item
def pretty_print_element(elem: ET.Element, level: int = 0, max_line: int = 80) -> str:
"""Convert ElementTree element to pretty-printed string with custom formatting."""
indent = ' ' * level
# Handle empty elements
if not elem.text and not elem.tail and not elem.attrib and len(elem) == 0:
return f'{indent}<{elem.tag}/>'
# Build opening tag with attributes
tag = elem.tag
attrs = elem.attrib
if attrs:
attr_strings = [f'{k}="{v}"' for k, v in sorted(attrs.items())]
attr_str = ' ' + ' '.join(attr_strings)
if len(indent) + len(tag) + len(attr_str) + 2 > max_line:
attr_indent = indent + ' '
attr_str = '\n' + '\n'.join(f'{attr_indent}{a}' for a in attr_strings)
else:
attr_str = ''
parts = [f'{indent}<{tag}{attr_str}>']
# Handle text content
if elem.text and elem.text.strip():
text = elem.text
if ']]>' in text:
escaped = text.replace('&', '&amp;') \
.replace('<', '&lt;') \
.replace('>', '&gt;') \
.replace('"', '&quot;') \
.replace("'", '&apos;')
parts.append(f'{indent} {escaped}')
else:
parts.append(f'{indent} <![CDATA[{text}]]>')
# Handle children
for child in elem:
parts.append(pretty_print_element(child, level + 1, max_line))
if child.tail and child.tail.strip():
parts.append(f'{indent} {child.tail}')
parts.append(f'{indent}</{tag}>')
return '\n'.join(parts)