在从一个程序(htlatex)生成的XML到另一个程序(ArborText Editor)的快速转换中,我需要替换以下形式的所有XML
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mn>
....
</mn>
</math>
与
<m:math xmlns:m="http://www.w3.org/1998/Math/MathML">
<m:mn xmlns:m="http://www.w3.org/1998/Math/MathML">
....
</m:mn>
</m:math>
是否有更简洁的简单方法来实现这一目标,而不是搜索代码<math
,<mn>
等并替换它们?或者这可以通过xslt完成吗?
答案 0 :(得分:1)
免责声明:我将使用正则表达式!如果你害怕他们可能会得到你,请立即停止阅读。
因为这是一个非常有限的问题,我相信使用XML解析器来查找我们想要更改的内容然后使用正则表达式就可以了。我们不是试图用正则表达式解析任何东西,只是替换简单的文本模式。
我使用XML::Twig查找所有math
个节点,将其XML作为字符串抓取,替换名称空间并将XML放回,这使得XML :: Twig解析更改后的字符串。如果正则表达式操作破坏了它无效的范围,我们会注意到这里因为解析会失败。
当然,假设math
元素中没有其他名称空间。
use strict;
use warnings;
use XML::Twig;
my $xml = <<XML;
<container>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mn>
<foo>asdf</foo>
<bar>fdsa</bar>
</mn>
</math>
</container>
XML
my $t = XML::Twig->new(
pretty_print => 'indented',
twig_handlers => {
math => sub {
my $new_xml = $_->outer_xml;
$new_xml =~ s{ xmlns="http://www.w3.org/1998/Math/MathML"}{};
$new_xml =~ s{<([a-zA-Z]+)}{<m:$1 xmlns:m="http://www.w3.org/1998/Math/MathML"}g;
$new_xml =~ s{</}{</m:}g;
$_->set_outer_xml($new_xml);
},
}
);
$t->parse($xml);
$t->print;
输出包含从math
开始的每个元素中的命名空间。
<container>
<m:math xmlns:m="http://www.w3.org/1998/Math/MathML">
<m:mn xmlns:m="http://www.w3.org/1998/Math/MathML">
<m:foo xmlns:m="http://www.w3.org/1998/Math/MathML">asdf</m:foo>
<m:bar xmlns:m="http://www.w3.org/1998/Math/MathML">fdsa</m:bar>
</m:mn>
</m:math>
</container>
我确认它适用于更深层次的嵌套结构和多个math
元素。