Почему этот синтаксический анализатор не находит содержимое тега XML, который использует префикс пространства имен? - PullRequest
2 голосов
/ 12 октября 2019

У меня есть этот XML-код, взятый из этой ссылки :

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:nyt="http://www.nytimes.com/namespaces/rss/2.0" version="2.0">
  <channel>
    <item>
      <title>‘This Did Not Go Well’: Inside PG&amp;E’s Blackout Control Room</title>
      <dc:creator>Ivan Penn</dc:creator>
      <pubDate>Sat, 12 Oct 2019 17:03:11 +0000</pubDate>
    </item>
  </channel>
</rss>

Когда я пытаюсь проанализировать его, используя lxml и следуя документации для xpath и XMLпространства имен , синтаксический анализатор находит заголовок (который не использует пространство имен), но не авторы / создатели, что делает:

from lxml import html

xml = """
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:nyt="http://www.nytimes.com/namespaces/rss/2.0" version="2.0">
  <channel>
    <item>
      <title>‘This Did Not Go Well’: Inside PG&amp;E’s Blackout Control Room</title>
      <dc:creator>Ivan Penn</dc:creator>
      <pubDate>Sat, 12 Oct 2019 17:03:11 +0000</pubDate>
    </item>
  </channel>
</rss>
"""


rss = html.fromstring(xml)
items = rss.xpath("//item")
for item in items:
    title = item.xpath("title")[0].text_content().strip()
    print(title)

    ns = {"dc" : "http://purl.org/dc/elements/1.1/"}
    authors = item.xpath("dc:creator", namespaces = ns)
    print(authors)

Этот код печатает:

Это не сработало »: в комнате управления затемнением PG & E []

Так как он правильно находит содержимое тега title, я думаю, что он находит отдельные теги <item>. Что-то не так с тем, как я передаю пространство имен в xpath?

РЕДАКТИРОВАТЬ: Результат одинаков независимо от того, использую ли я косую черту, т. Е.

ns = {"dc" : "http://purl.org/dc/elements/1.1/"}
ns = {"dc" : "http://purl.org/dc/elements/1.1"}

1 Ответ

2 голосов
/ 13 октября 2019

Анализатор HTML игнорирует пространства имен. Это последнее предложение в разделе Запуск HTML doctests в документации lxml:

Анализатор HTML, в частности, игнорирует пространства имен и некоторые другие XMLism.

Другая часть документации гласит:

Также обратите внимание, что анализатор HTML предназначен для анализа документов HTML. Для документов XHTML используйте синтаксический анализатор XML, который поддерживает пространство имен.

Это будет работать, если вы измените

authors = item.xpath("dc:creator", namespaces = ns)

на

authors = item.xpath("creator")

Но так какRSS - это не HTML, рассмотрите возможность использования анализатора XML (from lxml import etree).

...