2011-04-24 88 views
1

我其实问过this question in a different form之前。我确实得到了一个很好的答案,但我认为我需要更多的澄清,所以我再次以整个形式提问。如何动态生成XML?

用户将脚本是这样的:

$ABC->Command(100, 100); 
my $group = "1"; 
my $id  = "1"; 
my $value1 = "Some Process A Happened"; 
$rep->getParameter($group, $id, $value1); 
$ABC->Command(100, 100); 
my $group = "1"; 
my $id  = "2"; 
my $value1 = "Some Process B Happened"; 
$rep->getParameter($group, $id, $value1); 
$ABC->Command(100, 100); 
my $group = "2"; 
my $id  = "1"; 
my $value1 = "Some Process A Happened"; 
$rep->getParameter($group, $id, $value1); 
$ABC->Command(100, 100); 
my $group = "2"; 
my $id  = "1"; 
my $value1 = "Some Process Happened"; 
$rep->getParameter($group, $id, $value1); 
$ABC->Command(100, 100); 
my $group = "3"; 
my $id  = "1"; 
my $value1 = "Some Process Happened"; 
$rep->getParameter($group, $id, $value1); 
$ABC->SomeImage($image) $desc = "Some info"; 
$rep->getImage($image, $desc); 
$rep->getResult("Pass") 

这必须生成一个XML,如:

<?xml version="1.0" encoding="UTF-8" ?> 
<TestResult xmlns="http://test.com/automate" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://test.com/automate"> 
    <Result>Pass</Result> 
    <Comments>Executed Successfully</Comments> 
    <Parameters> 
     <ParameterGroup ID="Group1"> 
      <Parameter key="Key1">Some Value</Parameter> 
      <Parameter key="Key2">Some Value</Parameter> 
      <Parameter key="Key3">Some Value</Parameter> 
     </ParameterGroup> 
     <ParameterGroup ID="Group2"> 
      <Parameter key="Key1">Some Value</Parameter> 
      <Parameter key="Key2">Some Value</Parameter> 
      <Parameter key="Key3">Some Value</Parameter> 
     </ParameterGroup> 
     <ParameterGroup ID="Group3"> 
      <Parameter key="Key1">Some Value</Parameter> 
      <Parameter key="Key2">Some Value</Parameter> 
      <Parameter key="Key3">Some Value</Parameter> 
     </ParameterGroup> 
    </Parameters> 
    <Images> 
     <Image key="ImageTag1">info</Image> 
     <Image key="ImageTag2">info</Image> 
     <Image key="ImageTag3">info</Image> 
    </Images> 
</TestResult> 

图像值和参数值将在不同的时间点的输入。但是他们必须收集并放置在Images元素内,类似地Parameters。我应该在这里遵循什么方法?请提供一些代码示例。


编辑

我有类似

$xml = { 
    ParameterGroup => [ 
     { 
      ID  => 'Group1', 
      Parameter => { 
       Key1 => {content => 'Some Value'}, 
       Key2 => {content => 'Some Value'}, 
       Key3 => {content => 'Some Value'}, 
      }, 
     }, 
     { 
      ID  => 'Group2', 
      Parameter => { 
       Key1 => {content => 'Some Value'}, 
       Key2 => {content => 'Some Value'}, 
       Key3 => {content => 'Some Value'}, 
      }, 
     }, 
    ] 
}; 
print XMLout(
    $xml, 
    RootName => 'Parameters', 
    KeyAttr => 'value', 
); 

的结构,但这些都是固定的结构。我怎样才能使这种动态适合用户的需求?

+0

喜池上..请看看我已经试过 – MarsMax 2011-04-24 18:57:37

回答

2

考虑一下你的驱动代码的一些小调整。

#! /usr/bin/env perl 

use warnings; 
use strict; 

use TestResult; 

my $tr = TestResult->new; 

$tr->parameter(1, 1, "Some Process A Happened"); 
$tr->parameter(1, 2, "Some Process B Happened"); 
$tr->parameter(2, 1, "Some Process A Happened"); 
$tr->parameter(3, 1, "Some Process Happened"); 

$tr->image(1, "Some info"); 

$tr->result("Pass"); 
$tr->comments("Executed Successfully"); 

print $tr->as_xml; 

XML输出是

<?xml version="1.0" encoding="UTF-8" ?> 
<TestResult xmlns="http://test.com/automate" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://test.com/automate"> 
    <Result>Pass</Result> 
    <Comments>Executed Successfully</Comments> 
    <Parameters> 
    <ParameterGroup ID="Group1"> 
     <Parameter key="Key1">Some Process A Happened</Parameter> 
     <Parameter key="Key2">Some Process B Happened</Parameter> 
    </ParameterGroup> 
    <ParameterGroup ID="Group2"> 
     <Parameter key="Key1">Some Process A Happened</Parameter> 
    </ParameterGroup> 
    <ParameterGroup ID="Group3"> 
     <Parameter key="Key1">Some Process Happened</Parameter> 
    </ParameterGroup> 
    </Parameters> 
    <Images> 
    <Image key="ImageTag1">Some info</Image> 
    </Images> 
</TestResult> 

看到的$self->{_xml}内容的转储可以帮助您的理解。

{ 
    'Comments' => { 'content' => 'Executed Successfully' }, 
    'Parameters' => { 
    'ParameterGroup' => { 
     'Group1' => { 
     'Parameter' => { 
      'Key2' => { 'content' => 'Some Process B Happened' }, 
      'Key1' => { 'content' => 'Some Process A Happened' } 
     } 
     }, 
     'Group3' => { 
     'Parameter' => { 
      'Key1' => { 'content' => 'Some Process Happened' } 
     } 
     }, 
     'Group2' => { 
     'Parameter' => { 
      'Key1' => { 'content' => 'Some Process A Happened' } 
     } 
     } 
    } 
    }, 
    'xmlns' => 'http://test.com/automate', 
    'Result' => { 'content' => 'Pass' }, 
    'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 
    'xsi:schemaLocation' => 'http://test.com/automate', 
    'Images' => { 
    'ImageTag1' => { 'content' => 'Some info' } 
    } 
} 

TestResult模块让你在那里下面。一定要将它放在模块搜索路径中某个名为TestResult.pm的文件中。它从熟悉的样板开始。

package TestResult; 

use strict; 
use warnings; 

use XML::Simple; 

在编译的时候,我们成立了XML ::简单具体的子类到你想要的XML格式,在适当的顺序将输出内容。

BEGIN { 
    @__PACKAGE__::XML::ISA = qw/ XML::Simple /; 

    my %order = (
    TestResult => [qw/ 
     xmlns xmlns:xsi xsi:schemaLocation 
     Result Comments Parameters Images 
    /], 
); 

    *__PACKAGE__::XML::sorted_keys = sub { 
    my($self,$name,$h) = @_; 
    return @{ $order{$name} } if $order{$name}; 
    sort keys %$h; 
    }; 
} 

每个实例将携带输出文档的内容。硬编码的键 - 值对成为TestResult元素的属性。

sub new { 
    my($class) = @_; 
    my $self = { 
    _xml => { 
     "xmlns"    => "http://test.com/automate", 
     "xmlns:xsi"   => "http://www.w3.org/2001/XMLSchema-instance", 
     "xsi:schemaLocation" => "http://test.com/automate", 
    }, 
    }; 

    bless $self => $class; 
} 

commentsresult的实施非常简单,因为它们产生的XML很简单。这些方法在合适的插槽中填充比特并不意外。

sub comments { 
    my($self,$comments) = @_; 
    $self->{_xml}{Comments} = { content => $comments }; 
} 

sub result { 
    my($self,$result) = @_; 
    $self->{_xml}{Result} = { content => $result }; 
} 

我们必须要小心imageparameter,因为它们含有多个孩子。盲目覆盖$self->{_xml}{Images}$self->{_xml}{Parameter}会破坏已经累积的任何内容,因此相反,我们会增量添加新元素。

sub image { 
    my($self,$image,$desc) = @_; 

    my $imageid = "ImageTag" . $image; 
    $self->{_xml}{Images}{$imageid} = { content => $desc }; 
} 

sub parameter { 
    my($self,$group,$key,$value) = @_; 

    my $groupid = "Group" . $group; 
    my $keyid = "Key" . $key; 

    $self->{_xml}{Parameters}{ParameterGroup}{$groupid}{Parameter}{$keyid} = 
    { content => $value }; 
} 

最后,我们使用TestResult :: XML对XML进行编码。 GroupTags参数声明嵌套关系,例如<Images>包含<Image>。 (起初,我试图对<Parameters><ParameterGroup>之间的关系以及<ParameterGroup><Parameter>之间的关系给予类似的处理,但XML输出与您想要的不同。)KeyAttr参数告诉XML :: Simple将Perl哈希键用作XML属性。如果您曾使用XMLin来读取由其他工具生成的TestResults,则前缀+将产生更好的结果。

sub as_xml { 
    my($self) = @_; 

    my $serialize = __PACKAGE__::XML->new; 

    $serialize->XMLout(
    $self->{_xml}, 
    GroupTags => { 
     Images => "Image", 
    }, 
    KeyAttr => { 
     ParameterGroup => "+ID", 
     Parameter  => "+key", 
     Image   => "+key", 
    }, 
    RootName => "TestResult", 
    XMLDecl => '<?xml version="1.0" encoding="UTF-8" ?>', 
); 
} 

返回一个真值,表明模块加载成功。

1; 
+0

谢谢你这么多Greg..it完美的作品..解释也很好..再次感谢.. – MarsMax 2011-04-26 05:30:40

+0

嗨格雷格..我一直在努力使参数看起来像发生了一些进程发生了某个过程B发生了一些过程A MarsMax 2011-04-29 06:26:26

+0

通过更改此行来完成此操作getparameter to $ self - > {_ xml} {Parameters} {ParameterGroup} {$ groupid} {Parameter} {$ keyid} = {content => $ value};似乎没有工作..任何指针? – MarsMax 2011-04-29 06:28:24

1

XML :: Simple期望您将输出组装成perl数据结构,然后将其转换为XML;你是否在实际调用XML的时候遇到了麻烦,弄清楚数据结构应该是什么样子,或者用数据填充它们? (或者完全不同的东西?)

解决你的问题,一次解决它一点。

+0

我已经编辑,其中提到什么,我已经试过了问题..请看看 – MarsMax 2011-04-24 18:55:22