Разбор XML-файла с недопустимыми значениями xml:id (начиная с числа)

При условии, что у меня есть XML следующим образом: обратите внимание, что атрибуты xml:id являются строками, НАЧИНАЮЩИМИСЯ ЦИФРАМИ

<node1>
    <text xml:id='7865ft6zh67'>
       <div chapter='0'>
          <div id='theNode'>
              <p xml:id="40">
               A House that has:
                   <p xml:id="45">- a window;</p>
                   <p xml:id="46">- a door</p>
                   <p xml:id="46">- a door</p>
               its a beuatiful house
               </p>
          </div>
       </div>
    </text>
</node1>

Я хотел бы найти заголовок текста и получить весь текст из первого тега p, появляющегося внутри узла книги заголовка текста.

Первый подход можно сделать, используя ответы здесь: node-включая">выражение lxml xpath для выбора всего текста в заданном дочернем узле, включая его дочерние элементы (мой собственный вопрос)

Но в этом новом XML (по сравнению с упомянутым вопросом) xml:id начинаются с числа, и, как указано в одном из этих ответов, при использовании кода возникает следующая ошибка:

 xml:id : attribute value 7865ft6zh67 is not an NCName, line 3, column 31

Как я могу по-прежнему анализировать XML с этим несоответствием XML xml:id?

Пока единственное решение, которое я могу придумать, это передать xml в строку и добавить букву в начале каждого из этих xml:id, например:

newXML = '...hange><change xml:id="6f58f74883d55b...'
newXML_repared = newXML.replace('xml:id="','xml:id="XXid')
newXML_repared

from lxml import etree
XML_tree = etree.fromstring(newXML_repared,parser=parser)

но при этом я получаю:

 ValueError: Unicode strings with encoding declaration are not supported. Please use bytes input or XML fragments without declaration.

Любое предложение?

примечание: я заметил, что сама строка начинается с:

<?xml version="1.0" encoding="UTF-8"?>
<teiCorpus subtype="simple"  ...etc

В учебнике lxml можно прочитать: Однако для этого требуется, чтобы строки Unicode сами не указывали конфликтующую кодировку и, таким образом, лгали об их реальной кодировке: (https://lxml.de/parsing.html)

Но я до сих пор не знаю, как решить проблему тогда

Спасибо.


person JFerro    schedule 21.06.2020    source источник
comment
Желательно не использовать BS, потому что вся остальная команда использует lxml, никто в команде не использует BS, и идея заключается в том, чтобы придерживаться одной библиотеки.   -  person JFerro    schedule 22.06.2020
comment
И, по-видимому, BeautifulSoup сам по себе не поддерживает выражения XPath. Нам нужен xpath, потому что XML-файлы, с которыми мы работаем, чрезвычайно сложны и вложены друг в друга. Но спасибо за ответ   -  person JFerro    schedule 22.06.2020
comment
С bs4 вы можете использовать селекторы CSS + собственный API bs4.   -  person Andrej Kesely    schedule 22.06.2020
comment
Откуда берется плохой XML? Это должно быть исправлено кем бы то ни было.   -  person mzjn    schedule 22.06.2020


Ответы (1)


Один вариант находится в ссылке на предоставленные вами документы (https://lxml.de/parsing.html).

В частности, параметр восстановления, указанный в параметрах парсера.

Пример...

from lxml import etree

XML_content = """
<node1>
    <text xml:id='7865ft6zh67' title="book">
       <div chapter='0'>
          <div id='theNode'>
              <p xml:id="40">
               A House that has:
                   <p xml:id="45">- a window;</p>
                   <p xml:id="46">- a door</p>
                   <p xml:id="46">- a door</p>
               its a beuatiful house
               </p>
          </div>
       </div>
    </text>
</node1>
"""

parser = etree.XMLParser(recover=True)

XML_tree = etree.fromstring(XML_content, parser=parser)
text = XML_tree.xpath('normalize-space(//text[@title="book"]/div/div/p)')
# text = XML_tree.xpath('string(//text[@title="book"]/div/div/p)')
print(text)

Примечание. Я добавил title="book", поэтому XPath из другого моего ответа в вашем связанном вопросе все еще работал.

person Daniel Haley    schedule 21.06.2020
comment
recover=True в lxml может быть полезен для очистки плохого XML, но следует напомнить читателям, что такие проблемы, как запуск идентификаторов с цифр, нарушают правила правильности, и поэтому действительно должны быть зафиксированы в источнике. В противном случае каждому потребителю XML придется столкнуться с этими проблемами, сводя на нет преимущества использования стандартов. - person kjhughes; 22.06.2020