使用数字解析破碎的XML作为标记名称

时间:2017-12-26 18:26:27

标签: python regex xml string xml-parsing

我有很多xml文件,其密钥是数字格式,即<12345>Golly</12345>

使用ElementTree解析时出现错误not well-formed (invalid token)。我假设这是因为键是数字格式而不是单词。当我尝试通过使用正则表达式添加双引号来将键更改/替换为字符串时

xmlstr = re.sub('<([\d]+)>','<"' + str(re.search('<([\d]+)>', xmlstr).group(1))+ '">',xmlstr)
xmlstr = re.sub('</([\d]+)>','</"' + str(re.search('</([\d]+)>', xmlstr).group(1))+ '">',xmlstr)

使用第一个找到的密钥替换所有其他密钥。(所有密钥最终都是相同的。而原始文件中的密钥本身在每个文档中都是唯一的。)我想这些文件直接从json转换为xml。键应代表id号,值是与id号

相关的名称

我想知道是否有办法将数字作为键,或者如果有办法我可以逐个替换键而不是用一个找到的字符串替换所有匹配。 .group(1)返回导致问题的第一个匹配项。 请帮助。

2 个答案:

答案 0 :(得分:2)

我认为您需要同时拥有数字标记名称和在不同保存组中捕获的内容,然后在替换字符串中引用它们:

In [2]: data = "<content><12345>Golly</12345><67890>Jelly</67890></content>"

In [3]: re.sub(r"<(\d+)>(.*?)</\d+>", r'<item id="\1">\2</item>', data)
Out[3]: '<content><item id="12345">Golly</item><item id="67890">Jelly</item></content>'

但是,如果没有访问输入XML数据的可能变体,很难找到100%可靠的东西。例如,我不确定这个表达式是否能很好地处理嵌套的数字标记。

您可能还想探索在lxml's "recovery" mode中解析文档的可能性。

另一个可能有助于解决这种情况的工具是BeautifulSoup - 您可以尝试使用非传统方法 - 使用 lenient html5lib解析器解析XML数据:

In [1]: from bs4 import BeautifulSoup

In [2]: data = "<content><12345>Golly</12345><67890>Jelly</67890></content>"

In [3]: soup = BeautifulSoup(data, "html5lib")
In [3]: print(soup.prettify())
<html>
 <head>
 </head>
 <body>
  <content>
   &lt;12345&gt;Golly
   <!--12345-->
   &lt;67890&gt;Jelly
   <!--67890-->
  </content>
 </body>
</html>

当然,它不是理想的输出,但可能是你可以使用的东西,并提取键和单词。

答案 1 :(得分:0)

lxml 套餐会让你的生活更轻松,而不是与正则表达式斗争。

查看documentation page

  

pip install lxml

file_path = 'your/xml/file.xml'
parser_obj = lxml.etree.XMLParser(recover=True)
lxml.etree.parse(file_path, parser=parser_obj)