首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用XML的Perl::LibXML(全局查找和替换XML)

使用XML的Perl::LibXML(全局查找和替换XML)
EN

Stack Overflow用户
提问于 2018-12-14 05:46:09
回答 1查看 135关注 0票数 1

我是DOMXML-LibXML的新手。

这是我的示例mathml (XML)文件。我的XML文件名是in.xml,我需要最后的输出XML文件名是out.xml。我想找到<mi>bcde</mi>,需要全局修改<mtext>pqsd</mtext>并存储在out.xml中。如何实现这一目标。

代码语言:javascript
复制
<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);`
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-14 14:20:12

您的XML有一个名称空间,但是您的XPath查询没有,请参见findnodes in man XML::LibXML::Node中的注释。这一守则应适用于:

代码语言:javascript
复制
#!/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();

输出:

代码语言:javascript
复制
$ 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将更改为

代码语言:javascript
复制
foreach my $node ($xpc->findnodes('//math:mi[text()="bcde"]', $dom)) {

编辑2查找多个<mi>xyz</mi>并替换它们您可以使用text=replacement命令行参数,即

代码语言:javascript
复制
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);
    }
}

你的替代例子应该是

代码语言:javascript
复制
$ perl dummy.pl bcde=pqsd

编辑3mtext替换xxx有多个字符的所有<mi>xxx</mi>

代码语言:javascript
复制
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);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53774095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档