50 lines
1.5 KiB
Python
50 lines
1.5 KiB
Python
from typing import Iterator
|
|
import xml.etree.ElementTree as ET
|
|
|
|
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 escape_text_for_xml(text: str) -> str:
|
|
"""
|
|
Convert any text value to a properly escaped XML string.
|
|
|
|
Args:
|
|
text: Text to escape, can be string, number, or None
|
|
|
|
Returns:
|
|
str: XML-escaped string representation
|
|
"""
|
|
if text is None:
|
|
return ''
|
|
|
|
# Convert numbers to strings
|
|
text_str = str(text)
|
|
|
|
# Standard XML escaping if string contains CDATA end sequence
|
|
if ']]>' in text_str:
|
|
return text_str.replace('&', '&') \
|
|
.replace('<', '<') \
|
|
.replace('>', '>') \
|
|
.replace('"', '"') \
|
|
.replace("'", ''')
|
|
|
|
# Otherwise wrap in CDATA
|
|
return f'<![CDATA[{text_str}]]>' |