我有格式良好的xml(开放标签已关闭等),但没有dtd,名称空间并不总是正确的,并且有随机实体。
我在某些xml文件中发现了一个错误,并希望自动修复此错误。基本上,xml文件如下所示:
<foo>
<bar> hi </bar>
<!-- ... -->
<math><sometag><another>bar</another></sometag></math>
<!-- ... -->
</foo>
我想将此更改为
<foo>
<bar> hi </bar>
<!-- ... -->
<m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math>
<!-- ... -->
</foo>
我查看了Python elementtree,但根据diveintopython,它不会喜欢它不验证xml的事实?此外,除了使用m:
添加前缀外,不应更改任何内容。
由于我正在编写一堆shell脚本来修复文件,所以我并不关心这种语言,尽管我目前选择的武器是Python。
澄清:
<math>
和</math>
m:
答案 0 :(得分:6)
在Perl中,您可以使用XML::Twig,例如:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new( twig_roots => { math => \&add_prefix },
twig_print_outside_roots => 1,
)
->parse( \*DATA);
sub add_prefix
{ my( $t, $math)= @_;
foreach my $m ( $math, $math->descendants( '#ELT'))
{ $m->set_tag( "m:" . $m->tag); }
$t->flush;
}
__DATA__
<foo>
<bar> hi </bar>
<!-- ... -->
<math><sometag><another>bar</another></sometag></math>
<!-- ... -->
</foo>
答案 1 :(得分:4)
Perl中的单行确定吗?
$ perl -lne'm!<math>.*</math>! and s!<(/)?([^>]+)>!<$1m:$2>!gm;print' 5351382.txt
<foo>
<bar> hi </bar>
<!-- ... -->
<m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math>
<!-- ... -->
</foo>
你不应该以这种方式真正解析XML ......但如果上述内容足以让你......;)
答案 2 :(得分:2)
在Ruby中,使用Nokogiri来按摩XML:
xml = <<EOT
<foo>
<bar> hi </bar>
<!-- ... -->
<math><sometag><another>bar</another></sometag></math>
<!-- ... -->
</foo>
EOT
NAMESPACE = %w[m http://host.com/m]
require 'nokogiri'
doc = Nokogiri::XML::DocumentFragment.parse(xml)
ns = doc.at('foo').add_namespace_definition(*NAMESPACE)
doc.xpath('foo/math | foo/math//*').each { |n| n.namespace = ns }
puts doc.to_xml
输出如下:
>> <foo xmlns:m="http://host.com/m">
>> <bar> hi </bar>
>> <!-- ... -->
>> <m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math>
>> <!-- ... -->
>> </foo>
如果命名空间无法添加到<foo>
,那么您可以直接删除标记名称而不会弄乱命名空间:
xml = <<EOT
<foo>
<bar> hi </bar>
<!-- ... -->
<math><sometag><another>bar</another></sometag></math>
<!-- ... -->
</foo>
EOT
NAMESPACE = %w[m http://host.com/m]
require 'nokogiri'
doc = Nokogiri::XML::DocumentFragment.parse(xml)
doc.xpath('foo/math | foo/math//*').each { |n| n.name = "m:" << n.name }
puts doc.to_xml
# >> <foo>
# >> <bar> hi </bar>
# >> <!-- ... -->
# >> <m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math>
# >> <!-- ... -->
# >> </foo>
答案 3 :(得分:1)
您最好的选择可能是找到一个非验证的XSLT处理器并传递给它:
<xsl:template match="math">
<m:math>
<xsl:apply-templates select="@*|node()"/>
</m:math>
</xsl:template>
答案 4 :(得分:1)
也许BeautifulSoup会比Python内置的东西更好地为你服务。它主要是为HTML设计的,但也可以做XML,虽然......
BeautifulSoup类充满了类似Web浏览器的启发式方法,用于划分HTML作者的意图。但XML没有固定的标记集,因此这些启发式方法不适用。所以BeautifulSoup不能很好地完成XML。
它可能不完美,但可能在未指定或无效的XML上比严格的解析器更好。有利于它的另一点是gives you Unicode, dammit。