我刚才写了这个正则表达式修复了无效/损坏的XML,但它真的很慢,我该怎么做才能让它更快?
s/(.*?>)([^>.]*?&[^\#a].*?)</$1<!\[CDATA\[$2\]\]></ismg;
示例输入数据显示其修复的部分,请注意整个XML包含其他元素并且其中包含更多数据。
<?xml version="1.0" encoding="UTF-8"?><sample>
<test id="123" data="text">Ñucastle & Tyne</test>
<test id="123" data="text">Rock & Roll</test>
<test id="123" data="text">Peanut & Butter</test>
<test id="123" data="text">Ice & Cream</test></sample>
示例输出数据:
<?xml version="1.0" encoding="UTF-8"?><sample>
<test id="123" data="text"><![CDATA[Ñucastle & Tyne]]></test>
<test id="123" data="text"><![CDATA[Rock & Roll]]></test>
<test id="123" data="text"><![CDATA[Peanut & Butter]]></test>
<test id="123" data="text"><![CDATA[Ice & Cream]]></test></sample>
答案 0 :(得分:2)
Newcastle <![CDATA[&]]> Tyne
或仅Newcastle & Tyne
将是等效的。这意味着我们不需要找到文本节点的开头和结尾。我们甚至不需要检查我们是否在文本节点中,因为&
也应该在属性值中进行转义。所以你需要的只是:
s/&(?!#|[a-zA-Z]+;)/&/g;
没有回溯。没有捕获。没有什么可以放慢它的速度。
反对您的测试数据:
$ cat >file.xml
<?xml version="1.0" encoding="UTF-8"?><sample>
<test id="123" data="text">Newcastle & Tyne</test>
<test id="123" data="text">Rock & Roll</test>
<test id="123" data="text">Peanut & Butter</test>
<test id="123" data="text">Ice & Cream</test></sample>
$ perl -pe's/&(?!#|[a-zA-Z]+;)/&/g' file.xml
<?xml version="1.0" encoding="UTF-8"?><sample>
<test id="123" data="text">Newcastle & Tyne</test>
<test id="123" data="text">Rock & Roll</test>
<test id="123" data="text">Peanut & Butter</test>
<test id="123" data="text">Ice & Cream</test></sample>
用法:
perl -pe's/&(?!#|[a-zA-Z]+;)/&/g' in.xml >out.xml
perl -i~ -pe's/&(?!#|[a-zA-Z]+;)/&/g' file.xml # In-place, with backup
perl -i -pe's/&(?!#|[a-zA-Z]+;)/&/g' file.xml # In-place, no backup