Это непростая задача. Желая сохранить порядок атрибутов, и, возможно, вы не укажете его, остальную часть форматирования, вы не рассматриваете 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>
Но на самом деле, сохраняя формат нетронутыми безумие. Или весело, если вам нравится этот вызов; -)
Спасибо за ваш быстрый ответ, но атрибуты должны быть в порядке. – Badboy
В любом случае это может сработать, я его не испытал. Согласно http://search.cpan.org/~grantm/XML-Simple-2.18/lib/XML/Simple.pm, библиотека пытается сохранить атрибуты в том порядке, в котором они были получены. –
В файле xml есть больше данных, чем одна строфа, создание нового xml с помощью пользовательского ввода не является вариантом. Мне нужно найти строфу и как-то написать вход пользователя. – Badboy