将XML文件分成多个XML文件

时间:2013-02-22 10:47:27

标签: perl wsman

我想将WSMAN提供的XML输出分解为多个XML文件,以便我可以解析输出。

WSMAN为我提供如下输出,它基本上有两个不同的XML文件,每个文件都有自己的根节点:

<?xml version="1.0" encoding="UTF-8"?>
  <s:Body>
    <wsen:PullResponse>
      <wsen:Items>
        <n1:DCIM_SoftwareIdentity>
          <n1:ComponentType>BIOS</n1:ComponentType>
          <n1:InstanceID>DCIM:CURRENT#741__BIOS.Setup.1-1</n1:InstanceID>
          <n1:VersionString>1.3.6</n1:VersionString>
        </n1:DCIM_SoftwareIdentity>
      </wsen:Items>
    </wsen:PullResponse>
  </s:Body>
<?xml version="1.0" encoding="UTF-8"?>
  <s:Body>
    <wsen:PullResponse>
      <wsen:Items>
        <n1:DCIM_SoftwareIdentity>
          <n1:ComponentType>BIOS</n1:ComponentType>
          <n1:InstanceID>DCIM:INSTALLED#741__BIOS.Setup.1-1</n1:InstanceID>
          <n1:VersionString>1.3.6</n1:VersionString>
        </n1:DCIM_SoftwareIdentity>
      </wsen:Items>
    </wsen:PullResponse>
  </s:Body>

我无法使用XML::Simple解析上面的输出,因为上面的输出包含2个根元素,就XML而言是“垃圾”

问题/说明:

我想将输出分解为两个不同的XML文件,每个文件都包含自己的根元素,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
  <s:Body>
    <wsen:PullResponse>
      <wsen:Items>
        <n1:DCIM_SoftwareIdentity>
          <n1:ComponentType>BIOS</n1:ComponentType>
          <n1:InstanceID>DCIM:CURRENT#741__BIOS.Setup.1-1</n1:InstanceID>
          <n1:VersionString>1.3.6</n1:VersionString>
        </n1:DCIM_SoftwareIdentity>
      </wsen:Items>
    </wsen:PullResponse>
  </s:Body>

...

<?xml version="1.0" encoding="UTF-8"?>
  <s:Body>
    <wsen:PullResponse>
      <wsen:Items>
        <n1:DCIM_SoftwareIdentity>
          <n1:ComponentType>BIOS</n1:ComponentType>
          <n1:InstanceID>DCIM:INSTALLED#741__BIOS.Setup.1-1</n1:InstanceID>
          <n1:VersionString>1.3.6</n1:VersionString>
        </n1:DCIM_SoftwareIdentity>
      </wsen:Items>
    </wsen:PullResponse>
  </s:Body>

我的逻辑:

1)逐行解析输出

2)如果遇到?xml version模式,则创建一个新的XML文件并将?xml version行和更多行写入此新文件,直到再次遇到?xml version模式。

3)每次遇到?xml version模式

时,请按照步骤2进行操作

这是我的代码:

#!/usr/bin/perl -w
use strict;
use XML::Simple;
use Data::Dumper;

my $counter = 0;
my $fileName;

while (my $line = <DATA>)
{
    if ( $line =~ /\?xml version/ )
    {   
        $counter++;
        print "Creating the BIOS file \n";
        $fileName = "BIOS"."_".$counter;
    }   
    open (my $sub_xml_file, ">" , $fileName) or die "Canot create $fileName: $!\n";
    print $sub_xml_file $line;
}

__DATA__
## omitting this part as this contains the XML info listed above.

现在,我的脚本确实创建了文件BIOS_1BIOS_2,但它只将上面XML输出的最后一行写入其中:

# cat BIOS_1
  </s:Body>
# cat BIOS_2
  </s:Body>

你能帮我修改我的脚本以创建两个不同的XML文件......

1 个答案:

答案 0 :(得分:0)

您永远不会为将来的循环传递保留$line

将所有内容加载到内存中:

my $count;
my $file; { local $/; $file = <>; }
for my $xml (split /^(?=<\?xml)/m, $file) {
   my $fn = sprintf("BIOS_%d.xml", ++$count);
   open(my $fh, '>', $fn) or die $!;
   print $fh $xml;
}

一次排队:

my $fh;
my $count;
while (<>) {
   if (/^<\?xml/) {
      my $fn = sprintf("BIOS_%d.xml", ++$count);
      open($fh, '>', $fn) or die $!;
   }

   print $fh $_;
}