Я использовал LXML и был очень впечатлен. Гибкость, обеспечиваемая интерфейсами типа etree-like и objectify, довольно удобна. Мне также нравится тот факт, что у меня не должно быть отдельных текстовых узлов.
Что касается замены сущностей, у меня тоже было несколько проблем, но для меня это было вопросом предоставления парсеру правильных опций при его создании.
Например, если вы пытаетесь загрузить объекты из удаленного DTD, вы можете попробовать что-то вроде:
parser = etree.XMLParser(load_dtd=True, no_network=False)
Флаг no_network
по умолчанию равен True
и, на мой взгляд, немного нелогичен, но это единственное препятствие, с которым я столкнулся.