我的XML文件看起来像这样:
<doc>
<RU1>
<conf>
<prop name="a" val="http://a.org/a.html>
</conf>
</RU1>
<RAU1>
<conf>
<prop name="a" val="http://a.org/a.html>
</conf>
</RAU1>
<RU2>
<conf>
<prop name="a" val="http://a.org/a.html>
</conf>
</RU2>
</doc>
我想在prop字段的值中替换“a.org”,在perl中以RU开头的所有父标记下,用“b.com”替换。如何将更改作为xml文件获取?< / p>
答案 0 :(得分:8)
假设您的XML格式正确(事实并非如此),您可以使用a number of CPAN modules来完成工作。大多数将涉及解析文档,使用XPath查询找到您的位,并再次打印文档。
以下是XML :: Twig的示例。我不得不修复XML以使其解析。
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new(
twig_handlers => {
'conf/prop' => sub { $_->{att}{val} =~ s/a.org/b.org/; }
},
pretty_print => "indented"
);
$twig->parse(join "", <DATA>);
$twig->print;
__END__
<foo>
<RU1>
<conf>
<prop name="a" val="http://a.org/a.html" />
</conf>
</RU1>
<RAU1>
<conf>
<prop name="a" val="http://a.org/a.html" />
</conf>
</RAU1>
<RU2>
<conf>
<prop name="a" val="http://a.org/a.html" />
</conf>
</RU2>
</foo>
答案 1 :(得分:4)
从CPAN中获取XML解析器并使用它。他们是有原因的。
一旦你完成了它,它就是一些相当简单的XPath表达式来获取你想要的节点,然后在特定属性本身上进行一些快速文本替换。
答案 2 :(得分:3)
使用以下样式表
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="//*[starts-with(local-name(), 'RU')]//prop/@val">
<xsl:call-template name="replace-aorg" />
</xsl:template>
<xsl:template name="replace-aorg">
<xsl:param name="text" select="." />
<xsl:choose>
<xsl:when test="contains($text, 'a.org')">
<xsl:value-of select="substring-before($text, 'a.org')"/>
<xsl:text>b.com</xsl:text>
<xsl:call-template name="replace-aorg">
<xsl:with-param name="text" select="substring-after($text, 'a.org')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
并将XML文档调整为
<doc>
<RU1>
<conf>
<prop name="a" val="http://a.org/a.html" />
</conf>
</RU1>
<RAU1>
<conf>
<prop name="a" val="http://a.org/a.html" />
</conf>
</RAU1>
<RU2>
<conf>
<prop name="a" val="http://a.org/a.html" />
</conf>
</RU2>
</doc>
输出:
$ xsltproc sty.xml doc.xml
<?xml version="1.0"?>
<doc>
<RU1>
<conf>
<prop name="a">http://b.com/a.html</prop>
</conf>
</RU1>
<RAU1>
<conf>
<prop name="a" val="http://a.org/a.html"/>
</conf>
</RAU1>
<RU2>
<conf>
<prop name="a">http://b.com/a.html</prop>
</conf>
</RU2>
</doc>
所以从Perl开始,就像
那样system("xsltproc", "style.xsl", "doc.xml") == 0
or warn "$0: xsltproc exited " . ($? >> 8);