Perl 小树枝-搜索并添加一行
我是Perl新手,这是我的第一个Perl程序,我有一个XML文件,需要通过某种类型的自动化进行编辑:Perl 小树枝-搜索并添加一行,perl,xml-twig,Perl,Xml Twig,我是Perl新手,这是我的第一个Perl程序,我有一个XML文件,需要通过某种类型的自动化进行编辑: <Host appBase="webapps" unpackWARs="true" autoDeploy="true" deployOnStartup="true" deployXML="true" name="localhost" xmlValidation="false" x
<Host appBase="webapps"
unpackWARs="true"
autoDeploy="true"
deployOnStartup="true"
deployXML="true"
name="localhost"
xmlValidation="false"
xmlNamespaceAware="false">
</Host>
我没有使用XML::Twig,但我使用了XML::Simple。如果属性必须保持有序,那么您可能必须坚持字符串处理
use XML::Simple;
my $xml = '<Host appBase="webapps" unpackWARs="true" autoDeploy="true" deployOnStartup="true" deployXML="true" name="localhost" xmlValidation="false" xmlNamespaceAware="false"></Host>';
my $ref = XMLin($xml);
$ref->{Alias} = { content => 'User Input' };
my $newxml = XMLout($ref, RootName => 'Host');
print $newxml;
使用XML::Simple;
我的$xml='';
my$ref=XMLin($xml);
$ref->{Alias}={content=>'User Input'};
我的$newxml=XMLout($ref,RootName=>'Host');
打印$newxml;
这不是一个容易的问题。如果希望保持属性顺序,并且可能不指定它,其余的格式化,那么就没有真正将XML视为XML。大多数XML解析器都没有提供执行所需的数据的详细信息
处理XML的软件不应该关心属性顺序或不重要的空白。因此,使用或任何其他方式添加属性应该很简单
但是,由于希望保持完全相同的属性顺序,您对代码施加了一个约束,使其发生了根本性的变化。您将离开XML领域,将数据视为纯文本。这可能很好,也没什么大不了的,可能你只需要为它编写一个简单的解析器,一个可以让你访问原始格式的解析器。除了输入可能被指定为“XML”之外,它将来可能会以破坏代码的方式更改,但不会破坏XML解析器
好的,现在这已经不存在了,实际上它允许您保持属性顺序;--),创建细枝时,请使用keep\u atts\u order
选项。所以这很容易
不过,保留格式要复杂一些。在您的例子中,对于您提供的有限的数据样本,我可以通过对返回元素开始标记的方法进行子分类来让它工作。不过,让它正常工作要复杂得多
这是一个你可以使用的框架
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use XML::Twig;
# get the input and the expected result
my( $in, $expected)= do { $/="\n\n"; <DATA>};
chomp $in; chomp $expected;
my $xna= 'false'; # represents the user inpput
my $t= XML::Twig->new( twig_handlers => { Host => sub { $_->set_att( xmlNamespaceAware => $xna); }
},
keep_atts_order => 1, # the bit you were looking for
elt_class => 'XML::Twig::MyElt', # to use the element sub-class
)
->parse( $in);
is( $t->sprint, $expected, 'one test for now');
done_testing();
package XML::Twig::MyElt;
use XML::Twig;
use base 'XML::Twig::Elt';
sub start_tag
{ my( $elt)= @_;
if( $elt->tag ne 'Host')
{ return $elt->SUPER::start_tag }
else
{ return '<' . $elt->tag . ' '
. join( "\n ",
map { qq{$_="} . $elt->att( $_) . qq{"} }
keys %{$elt->atts} # the keys are in the right order
)
. '>';
}
}
package main;
__DATA__
<Host appBase="webapps"
unpackWARs="true"
autoDeploy="true"
deployOnStartup="true"
deployXML="true"
name="localhost"
xmlValidation="false">
**<Alias>HOST.com</Alias>**
</Host>
<Host appBase="webapps"
unpackWARs="true"
autoDeploy="true"
deployOnStartup="true"
deployXML="true"
name="localhost"
xmlValidation="false"
xmlNamespaceAware="false">
**<Alias>HOST.com</Alias>**
</Host>
#/usr/bin/perl
严格使用;
使用警告;
使用测试::更多;
使用XML::Twig;
#获取输入和预期结果
my($in,$expected)=do{$/=“\n\n”;};
大吃一块;预计将有600万美元;
我的$xna='false'#表示用户输入
my$t=XML::Twig->new(Twig_handlers=>{Host=>sub{$\->set_att(xmlNamespaceAware=>$xna);}
},
保持_atts_order=>1,#您正在寻找的位
elt_class=>XML::Twig::MyElt',#使用元素子类
)
->(单位:元);
是($t->sprint,$expected,'one test for now');
完成测试();
包XML::Twig::MyElt;
使用XML::Twig;
使用基本'XML::Twig::Elt';
子启动标签
{my($elt)=@;
如果($elt->标记ne“主机”)
{return$elt->SUPER::start_tag}
其他的
{返回“”;
}
}
主包装;
__资料__
**HOST.com**
**HOST.com**
但实际上,保持格式不变是疯狂的。或者,如果你喜欢这种挑战,那就很有趣;--) 感谢您的快速响应,但属性需要保持有序。无论如何,它可能会工作,我没有真正测试它。根据,库试图保持属性与接收属性的顺序相同。xml文件中的数据比一节中的数据多,因此无法使用用户输入创建新的xml。我需要搜索该节并以某种方式写入用户输入。当我将您的节加载到$xml中时,我非常简短。您可以通过文件读取或其他方式将整个文档放入该变量中。XMLin将把整个XML文档映射到一个hashref中,您可以做任何您想做的事情。非常确定,您可以将XMLin指向一个文件名,它也可以做到这一点!感谢您在与应用程序所有者交谈后提供的帮助。您是正确的。数据顺序无关紧要。一开始我并不清楚。抱歉,没问题,强迫模块做一些不自然的事情很有趣。我知道有些工具要求属性按特定顺序排列,因此有了keep\u atts\u order
选项。
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use XML::Twig;
# get the input and the expected result
my( $in, $expected)= do { $/="\n\n"; <DATA>};
chomp $in; chomp $expected;
my $xna= 'false'; # represents the user inpput
my $t= XML::Twig->new( twig_handlers => { Host => sub { $_->set_att( xmlNamespaceAware => $xna); }
},
keep_atts_order => 1, # the bit you were looking for
elt_class => 'XML::Twig::MyElt', # to use the element sub-class
)
->parse( $in);
is( $t->sprint, $expected, 'one test for now');
done_testing();
package XML::Twig::MyElt;
use XML::Twig;
use base 'XML::Twig::Elt';
sub start_tag
{ my( $elt)= @_;
if( $elt->tag ne 'Host')
{ return $elt->SUPER::start_tag }
else
{ return '<' . $elt->tag . ' '
. join( "\n ",
map { qq{$_="} . $elt->att( $_) . qq{"} }
keys %{$elt->atts} # the keys are in the right order
)
. '>';
}
}
package main;
__DATA__
<Host appBase="webapps"
unpackWARs="true"
autoDeploy="true"
deployOnStartup="true"
deployXML="true"
name="localhost"
xmlValidation="false">
**<Alias>HOST.com</Alias>**
</Host>
<Host appBase="webapps"
unpackWARs="true"
autoDeploy="true"
deployOnStartup="true"
deployXML="true"
name="localhost"
xmlValidation="false"
xmlNamespaceAware="false">
**<Alias>HOST.com</Alias>**
</Host>