用转义字符串替换xml中的保留字符

时间:2019-01-23 08:35:05

标签: regex xml perl sed

我有一个包含字符<>&的xml文件。例如:

<?xml version="1.0" encoding="utf-8"?>
<test>
  <medi>bla bla >12 bla</medi>
  <diag>bla & bla <12</diag>
</test>

这些字符保留用于xml表示法,应替换为转义字符串&lt;&gt;&amp;。这同样适用于引号(“-> &quot;)和撇号('-> &apos;)。

这就是我想要得到的:

<?xml version="1.0" encoding="utf-8"?>
<test>
  <medi>bla bla &gt;12 bla</medi>
  <diag>bla &amp; bla &lt;12</diag>
</test>

通常,我对perl或sed使用正则表达式。但是,诚挚的,我没有成功。困难在于避免替换xml相关字符,例如转义字符串的<>&

为了弄清楚我的意思,我用perl提出了一个无效的解决方案:

use strict;
use warnings;

my $input  = $ARGV[0];
my $output = $ARGV[1];

open INPUT,  $input or die "Couldn't open file $input, $!";
open OUTPUT, ">$output" or die "Couldn't open file $output, $!";

my $rec;

while (<INPUT>) {

    $rec = $_;
    print $rec;

    $rec =~ s/(<medi>.*)<(.*<\/medi>)/$1&lt;$2/g;    
    $rec =~ s/(<medi>.*)>(.*<\/medi>)/$1&gt;$2/g;    
    $rec =~ s/(<medi>.*)&(.*<\/medi>)/$1&amp;$2/g;
    $rec =~ s/(<medi>.*)'(.*<\/medi>)/$1&apos;$2/g;
    $rec =~ s/(<medi>.*)"(.*<\/medi>)/$1&quot;$2/g;

    $rec =~ s/(<diag>.*)<(.*<\/diag>)/$1&lt;$2/g;    
    $rec =~ s/(<diag>.*)>(.*<\/diag>)/$1&gt;$2/g;    
    $rec =~ s/(<diag>.*)&(.*<\/diag>)/$1&amp;$2/g;
    $rec =~ s/(<diag>.*)'(.*<\/diag>)/$1&apos;$2/g;
    $rec =~ s/(<diag>.*)"(.*<\/diag>)/$1&quot;$2/g;

    print $rec;
    print OUTPUT $rec;
}
close INPUT;
close OUTPUT;

这给了我

<?xml version="1.0" encoding="utf-8"?>
<test>
  <medi>bla bla &amp;gt;12 bla</medi>
  <diag>bla & bla &amp;lt;12</diag>
</test>

会发生什么:

  • &gt;的与号被&amp;取代了,
  • <diag> bla & bla ...的“&”号未被替换

我确定有一个正则表达式可以解决此问题。但是,如果还有其他方法可以使xml格式正确,则可以接受。

2 个答案:

答案 0 :(得分:1)

如果您的文件中的文本节点中包含诸如'<','>'和'&'之类的字符,则您没有XML文件。

为了解决此问题,您需要使用XML解析器来解析文件。但是大多数XML解析器很可能会拒绝解析这些文件,因为它们不是格式正确的XML。像XML::Lenient这样的东西在这里可能很有用。

正确的方法是返回这些文件的来源并修复该过程,以便它生成格式正确的XML文件。如果要创建文件,则需要修复创建它们的代码。如果有人向您提供文件,那么您需要回到他们那里,要求他们提供有效的XML文件。

答案 1 :(得分:0)

如果您的数据在“ d”中,则由gnu sed

sed -E 's/&/&amp\;/g;s/</&lt\;/g;s/>/&gt\;/g;s/\x27/&apos\;/g;/xml ver/!s/\"/&quot\;/g' d

或“是\ x22
如果可以的话