【问题标题】:Parsing an XML file with invalid xml:id values (starting with a number)解析具有无效 xml:id 值的 XML 文件(以数字开头)
【发布时间】:2020-10-11 18:29:29
【问题描述】:

如果我有如下的 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 标记中获取所有文本

第一种方法可以使用此处的答案来完成: lxml xpath expression for selecting all text under a given child node including his children(我自己的问题)

但是在这个新的 XML(与提到的问题相比)中,xml:id 以数字开头,并且正如其中一个答案所指出的那样,使用代码时会出现以下错误:

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

我怎样才能仍然用“XML non compliance xml:id”解析 XML?

到目前为止,我能想到的唯一解决方案是将 xml 传递给字符串,并在每个 xml:ids 的开头添加一个字母,例如:

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)

但是我还是不知道怎么解决这个问题

谢谢。

【问题讨论】:

  • 最好不要使用 BS,因为团队中的其他人都使用 lxml,团队中没有人使用 BS,而且想法是坚持一个库。
  • 显然“BeautifulSoup 本身不支持 XPath 表达式。”。我们需要 xpath,因为我们使用的 xml 非常复杂且嵌套。不过谢谢你的回答
  • 有了bs4你可以使用CSS选择器+bs4自己的api。
  • 糟糕的 XML 从何而来?这应该由创建它的任何人/任何人来解决。

标签: python xml xml-parsing lxml


【解决方案1】:

在您提供的文档的链接中可以找到一个选项 (https://lxml.de/parsing.html)。

特别是parser options 中列出的“恢复”选项。

示例...

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",因此您相关问题中来自my other answer 的XPath 仍然有效。

【讨论】:

  • lxml 的recover=Truecleaning up "bad" XML 很有用,但要提醒读者,id 以数字开头的问题违反了格式正确的规则,因此确实应该在源头上修复.否则,“XML”的每个消费者都必须遭受这些问题,从而失去使用标准的好处。
猜你喜欢
  • 2016-04-14
  • 1970-01-01
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
  • 2014-09-12
相关资源
最近更新 更多