这不是一个容易的问题。通过想要保持属性顺序,也许,您没有指定它,其余的格式,您并没有真正将 XML 视为 XML。大多数 XML 解析器都没有为您提供执行所需数据的详细信息。
处理 XML 的软件不应该关心属性顺序或不重要的空白。因此,使用XML::Twig或任何其他方式添加属性应该很简单。
但是,通过想要保持完全相同的属性顺序,您对代码施加了一个约束,从而彻底改变了它。您将离开 XML 领域并将数据视为纯文本。这可能很好而且没什么大不了的,可能您只需要为它编写一个简单的解析器,一个可以让您访问原始格式的解析器。除了输入可能被指定为“XML”并且将来它可能会以会破坏您的代码但不会破坏 XML 解析器的方式发生变化。
好的,现在已经不碍事了,XML::Twig实际上确实让您保持属性顺序 ;--),keep_atts_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>
但实际上,保持格式完整是疯狂的。或者如果你喜欢这种挑战就很有趣;--)