Perl with XML::LibXML Dom(全局查找和替换 XML)
Perl with XML::LibXML Dom (Globally Find and Replace XML)
我是 DOM
和 XML-LibXML
的新手。
这是我的示例 mathml (XML) 文件。我的 XML 文件名为 in.xml
,我需要最终输出 XML 文件名为 out.xml
。我想找到<mi>bcde</mi>
,需要全局修改<mtext>pqsd</mtext>
,存入out.xml
。如何实现。
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mi>a</mi>
<mrow>
<mi>bcde</mi>
</mrow>
</mfrac>
<msqrt>
<mi>s</mi>
<mi>e</mi>
<mi>f</mi>
</msqrt>
</math>
#!/usr/bin/perl
use strict;
use warnings 'all';
use XML::LibXML;
my $mediaIdFrom = "MEDIAID_TEST";
my $VodItemIdFrom = "VODITEM_ID_TEST";
my $mediaId="";
my $vodItemId="";
my $filename = 'sample1.xml';
my $out_filename = "sample2.xml";
my $dom = XML::LibXML -> load_xml(location => $filename);
foreach $mediaId ($dom->findnodes('/ScheduleProvider/Episode/Media/@id')) {
$mediaId->setValue("xx " . $mediaIdFrom . " yy");
}
foreach $vodItemId ($dom->findnodes('/ScheduleProvider/VoidItem/@id')) {
$vodItemId->setValue($VodItemIdFrom);
}
#### for storing the output separate XML file
$dom->toFile($out_filename);`
您的 XML 有命名空间,但您的 XPath 查询没有,请参阅 man XML::LibXML::Node
中 findnodes
下的注释。此代码应该有效:
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
use XML::LibXML::XPathContext;
my $dom = XML::LibXML->load_xml(string => <<'END_OF_XML');
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mi>a</mi>
<mrow>
<mi>bcde</mi>
</mrow>
</mfrac>
<msqrt>
<mi>s</mi>
<mi>e</mi>
<mi>f</mi>
</msqrt>
</math>
END_OF_XML
my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs('math', 'http://www.w3.org/1998/Math/MathML');
foreach my $node ($xpc->findnodes('/math:math/math:mfrac/math:mrow/math:mi', $dom)) {
my $newNode = XML::LibXML::Element->new('mtext');
$newNode->appendText('pqsd');
$node->replaceNode($newNode);
}
print $dom->toString();
输出:
$ perl dummy.pl
<?xml version="1.0"?>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mi>a</mi>
<mrow>
<mtext>pqsd</mtext>
</mrow>
</mfrac>
<msqrt>
<mi>s</mi>
<mi>e</mi>
<mi>f</mi>
</msqrt>
</math>
编辑 也许我误解了你的问题,你想替换所有出现的 <mi>bcde</mi>
?然后 foreach
将更改为
foreach my $node ($xpc->findnodes('//math:mi[text()="bcde"]', $dom)) {
EDIT 2 找到多个 <mi>xyz</mi>
并替换它们你可以使用 text=replacement
命令行参数,即
foreach my $argv (@ARGV) {
next
unless my($find, $replace) = ($argv =~ /^([^=]+)=(.*)$/);
foreach my $node ($xpc->findnodes(qq{//math:mi[text()="${find}"]}, $dom)) {
my $newNode = XML::LibXML::Element->new('mtext');
$newNode->appendText($replace);
$node->replaceNode($newNode);
}
}
你的替换示例是
$ perl dummy.pl bcde=pqsd
编辑 3 将 xxx 具有多个字符的所有 <mi>xxx</mi>
替换为 mtext
:
foreach my $node ($xpc->findnodes('//math:mi', $dom)) {
my $text = $node->textContent();
# strip surrounding white space from text
$text =~ s/^\s+//;
$text =~ s/\s+$//;
# if text has more than one character then replace "mi" with "mtext"
if (length($text) > 1) {
my $newNode = XML::LibXML::Element->new('mtext');
$newNode->appendText($text);
$node->replaceNode($newNode);
}
}
我是 DOM
和 XML-LibXML
的新手。
这是我的示例 mathml (XML) 文件。我的 XML 文件名为 in.xml
,我需要最终输出 XML 文件名为 out.xml
。我想找到<mi>bcde</mi>
,需要全局修改<mtext>pqsd</mtext>
,存入out.xml
。如何实现。
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mi>a</mi>
<mrow>
<mi>bcde</mi>
</mrow>
</mfrac>
<msqrt>
<mi>s</mi>
<mi>e</mi>
<mi>f</mi>
</msqrt>
</math>
#!/usr/bin/perl
use strict;
use warnings 'all';
use XML::LibXML;
my $mediaIdFrom = "MEDIAID_TEST";
my $VodItemIdFrom = "VODITEM_ID_TEST";
my $mediaId="";
my $vodItemId="";
my $filename = 'sample1.xml';
my $out_filename = "sample2.xml";
my $dom = XML::LibXML -> load_xml(location => $filename);
foreach $mediaId ($dom->findnodes('/ScheduleProvider/Episode/Media/@id')) {
$mediaId->setValue("xx " . $mediaIdFrom . " yy");
}
foreach $vodItemId ($dom->findnodes('/ScheduleProvider/VoidItem/@id')) {
$vodItemId->setValue($VodItemIdFrom);
}
#### for storing the output separate XML file
$dom->toFile($out_filename);`
您的 XML 有命名空间,但您的 XPath 查询没有,请参阅 man XML::LibXML::Node
中 findnodes
下的注释。此代码应该有效:
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
use XML::LibXML::XPathContext;
my $dom = XML::LibXML->load_xml(string => <<'END_OF_XML');
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mi>a</mi>
<mrow>
<mi>bcde</mi>
</mrow>
</mfrac>
<msqrt>
<mi>s</mi>
<mi>e</mi>
<mi>f</mi>
</msqrt>
</math>
END_OF_XML
my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs('math', 'http://www.w3.org/1998/Math/MathML');
foreach my $node ($xpc->findnodes('/math:math/math:mfrac/math:mrow/math:mi', $dom)) {
my $newNode = XML::LibXML::Element->new('mtext');
$newNode->appendText('pqsd');
$node->replaceNode($newNode);
}
print $dom->toString();
输出:
$ perl dummy.pl
<?xml version="1.0"?>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mi>a</mi>
<mrow>
<mtext>pqsd</mtext>
</mrow>
</mfrac>
<msqrt>
<mi>s</mi>
<mi>e</mi>
<mi>f</mi>
</msqrt>
</math>
编辑 也许我误解了你的问题,你想替换所有出现的 <mi>bcde</mi>
?然后 foreach
将更改为
foreach my $node ($xpc->findnodes('//math:mi[text()="bcde"]', $dom)) {
EDIT 2 找到多个 <mi>xyz</mi>
并替换它们你可以使用 text=replacement
命令行参数,即
foreach my $argv (@ARGV) {
next
unless my($find, $replace) = ($argv =~ /^([^=]+)=(.*)$/);
foreach my $node ($xpc->findnodes(qq{//math:mi[text()="${find}"]}, $dom)) {
my $newNode = XML::LibXML::Element->new('mtext');
$newNode->appendText($replace);
$node->replaceNode($newNode);
}
}
你的替换示例是
$ perl dummy.pl bcde=pqsd
编辑 3 将 xxx 具有多个字符的所有 <mi>xxx</mi>
替换为 mtext
:
foreach my $node ($xpc->findnodes('//math:mi', $dom)) {
my $text = $node->textContent();
# strip surrounding white space from text
$text =~ s/^\s+//;
$text =~ s/\s+$//;
# if text has more than one character then replace "mi" with "mtext"
if (length($text) > 1) {
my $newNode = XML::LibXML::Element->new('mtext');
$newNode->appendText($text);
$node->replaceNode($newNode);
}
}