我在python中使用LXML库进行XML解析。
在XML文件中,我有一些错误字符,导致python中的错误:
lxml.etree.XMLSyntaxError: CharRef
在打开和获取python中的XML文件内容之前,我必须从两个标记中删除坏字符:
1:<essid cloaked="true">....</essid>或<essid cloaked="false">....</essid>。
2:<client-manuf>....</client-manuf>
XML文件的大小很大。所以我想用sed或者awk或者类似的工具来做。
<crypt>0</crypt>
<total>20 50</total>
<fragments>0</fragments>
<retries>0</retries>
</packets>
<datasize>0</datasize>
<wireless-client number="1" type="established" first-time="Thu Feb 15 16:45:43 2018" last-time="Thu Feb 15 16:45:43 2018">
<client-mac>08:EA:40:D0:55:43</client-mac>
<client-manuf>SHENZHEN BILIAN ELECTRONIC CO.&#x ef;&#x bc;&#x 8c;LTD</client-manuf>
<essid cloaked="true">&#x 0;&#x 0;&#x 0;&#x 0;&#x 0;</essid>
<channel>8</channel>
<maxseenrate>1.000000</maxseenrate>
<carrier>IEEE 802.11b+</carrier>
<encoding>CCK</encoding>
<packets>
<LLC>0</LLC>
<data>0</data>
<crypt>0</crypt>我想从这些标记(client-manuf和essid)中删除坏字符。
来自:<client-manuf>SHENZHEN BILIAN ELECTRONIC CO.&#x ef;&#x bc;&#x 8c;LTD</client-manuf>
To (或此):<client-manuf>SHENZHEN BILIAN ELECTRONIC CO. LTD</client-manuf>
To (或此):<client-manuf>SHENZHEN BILIAN ELECTRONIC CO</client-manuf>
来自:<essid cloaked="true">&#x 0;&#x 0;&#x 0;&#x 0;&#x 0;</essid>
来自:<essid cloaked="false">&#x 0;&#x WiFi 0;&#x MTN 0;&#x 0;&#x 0;</essid>
To (或此):<essid cloaked="true"></essid>
To (或此):<essid cloaked="true">N/A SSID</essid>
To (或此):<essid cloaked="false">WiFi MTN</essid>
for example, two bad chars:
1: 0;
2: &#x这是我的解决方案。但它对我的需求不起作用:
sed -e '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/ s/\(&#x\|0;\)//g' a.txt
发布于 2018-02-17 20:59:41
您的sed命令看起来并没有那么糟糕,它只是留下了许多空白。
因为sed通常是贪婪的,所以您可以使用“*”指定任意数量的空间。
cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/ s/ *\(&#x\|0;\) *//g'另一方面,如果有一些有效的文本,您可能不想将它粘在一起,因此可以在每个移除的模式中添加一个空格:
cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/ s/ *\(&#x\|0;\) */ /g'最后,您可能会将多个空格压缩为一个:
cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/{s/ *\(&#x\|0;\) */ /g;s/ */ /g}'请注意,构造{foo;bar}将这两个命令绑定到一个命令块,仅在“前抓取”模式上操作。第二种模式将影响整个文件。
加上另一对蒙面圆括号和一个蒙面加上:
cat bad.xml | sed '/<essid cloaked="\(true\|false"\)>*.*<\/essid>/{s/\( *\(&#x\|0;\) *\)\+/ missing essid /g;s/ */ /g}'你可以用一件事来代替反复出现的模式。
s/\( *\(&#x\|0;\) *\)\+/ missing essid /;
^ ( (pattern1) )+ / replacement /(g now obsolete
(pattern .......2)内部模式是一个可选的&#x或0;。外部模式是内部模式,可以选择地由空格(如
"0;"
"0; "
" 0; "
" 0;"
" 0; "
" &#x"诸若此类。
您希望内部模式,让我们称之为X,被重复一次或多次,因此+。但是没有父母,+只处理最后一个字符,而不是整个模式。
你必须学会这种正则语言。找个教程。你不能要求你生活中需要的每一个可能的变化。
有了良好的基本理解,很快就会有回报。你不需要知道所有的一切,但基本的东西,应该有一个很好的估计,什么是可能的,什么不是。然后再做个回购,去寻找东西,很少用。然后你可能只会问那些困难/复杂的事情。
发布于 2018-02-16 14:51:52
使用etree.XMLParser对象的正确方法(仅限lxml.etree):
import re
from lxml import etree
tags_to_fix = ['clientssss-manuf', 'client-manuf', 'essid']
parser = etree.XMLParser(recover=True) # recovery mode !
tree = etree.parse("input.xml", parser)
for el in tree.xpath('//*[name()="clientssss-manuf" or name()="client-manuf" or name()="essid"]'):
el.text = re.sub(r'\w{1,2};\s*', '', el.text).strip()
tree.write("output.xml", encoding="utf-8", pretty_print=True)产生的output.xml中的关键片段
...
<packets>
<crypt>0</crypt>
<total>20 50</total>
<fragments>0</fragments>
<retries>0</retries>
</packets>
<datasize>0</datasize>
<wireless-client number="1" type="established" first-time="Thu Feb 15 16:45:43 2018" last-time="Thu Feb 15 16:45:43 2018">
<client-mac>08:EA:40:D0:55:43</client-mac>
<clientssss-manuf>SHENZHEN BILIAN ELECTRONIC CO. LTD</clientssss-manuf>
<client-manuf>SHENZHEN BILIAN ELECTRONIC CO. LTD</client-manuf>
<essid cloaked="true"></essid>
<channel>8</channel>
<maxseenrate>1.000000</maxseenrate>
<carrier>IEEE 802.11b+</carrier>
<encoding>CCK</encoding>
<packets>
<LLC>0</LLC>
<data>0</data>
<crypt>0</crypt>
</packets></wireless-client>
...https://stackoverflow.com/questions/48826469
复制相似问题