Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何动态生成XML?_Xml_Perl_Xml Simple - Fatal编程技术网

如何动态生成XML?

如何动态生成XML?,xml,perl,xml-simple,Xml,Perl,Xml Simple,我以前问过。我确实得到了一个很好的答案,但我认为我需要更多的澄清,所以我再次以完整的形式提问 用户将编写如下脚本: $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

我以前问过。我确实得到了一个很好的答案,但我认为我需要更多的澄清,所以我再次以完整的形式提问

用户将编写如下脚本:

$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>

但这些都是固定结构。如何使其动态化以满足用户的需求?

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


把你的问题分解,一次解决一点。

考虑下面对你的驱动程序代码进行一些小的调整

#! /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>
下面是将您带到那里的TestResult模块。确保将其放入模块搜索路径中名为
TestResult.pm
的文件中。它从熟悉的样板开始

package TestResult;

use strict;
use warnings;

use XML::Simple;
在编译时,我们针对所需的XML格式设置了一个子类XML::Simple,它将以适当的顺序输出元素

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;
}
注释
结果
的实现很简单,因为它们生成的XML很简单。这些方法毫无意外地将位填充到适当的插槽中

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

sub result {
  my($self,$result) = @_;
  $self->{_xml}{Result} = { content => $result };
}
我们必须小心使用
图像
参数
,因为它们包含多个子项。盲目地覆盖
$self->{uXML}{Images}
$self->{uXML}{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
参数声明嵌套关系,例如,
包含
。(起初,我尝试对
之间的关系以及
之间的关系进行类似的处理,但XML输出与您想要的不同。)
KeyAttr
参数告诉XML::Simple使用Perl哈希键作为XML属性。如果您曾经使用
XMLin
读取其他工具生成的测试结果,那么
+
前缀将产生更好的结果

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" ?>',
  );
}

我已经编辑了这个问题,其中提到了我所做的尝试。。请看一看Hi ikegami。。请看一看我试过的东西非常感谢Greg.它非常有效。。解释也很好。。再次感谢..嗨,格雷格..我一直在试图使参数看起来像某个进程A发生了某个进程B发生了某个进程A发生了这样的事情,通过将getparameter中的这一行更改为$self->{{u xml}{Parameters}{Parameters}{groupid}{parameter}{$keyid}{content=>$value};似乎不起作用。。有什么建议吗?@MarsMax谢谢你的bug报告,看看我更新的修复答案!谢谢。。抱歉..我不太熟悉复杂的perl数据结构..我也不太懂XML..谢谢Greg。。因此,您将与参数相关的标记作为关键属性。。还有一点需要澄清..当您设置XML::Simple的子类时,您已经将元素定义为“结果注释参数..等等,以防脚本不发送图像元素..我将获得输出XML,因为有任何方法可以避免打印没有传递值的元素的名称。。
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 };
}
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;