2015-11-11 24 views
0

将我的头靠在墙上试图弄清楚这一点。只是试图拼凑一个脚本,最终将这些游戏文件的各种组件(如维基)连接在一起。我确信这是一个简单的问题,不能做出正确的解释权,但我无法想象出我的生活。使用xml :: simple在perl中引用xml对象的顶层级别

这里是XML的一个样本:

<?xml version="1.0" encoding="UTF-8"?> 
<items> 
     <!-- ??????????????????????????????????????????????????????????????????????????????? --> 
    <!-- ?????????? Die Till Day 7 ?????????? Guns (Gun Parts) ????????????????????????? --> 
    <!-- ??????????????????????????????????????????????????????????????????????????????? --> 
     <item id="1" name="pistol"> 
     <property name="Meshfile" value="Items/Weapons/Ranged/Pistol/PistolPrefab" /> 
     <property name="Material" value="metal" /> 
     <property name="HoldType" value="1" /> 
     <property name="Stacknumber" value="1" /> 
     <property name="RepairTools" value="repairKit,repairKit2ndGeneration,repairKit3rdGeneration" /> 
     <property name="Degradation" value="175" param1="false" /> 
     <property name="DegradationBreaksAfter" value="false" /> 
     <property name="SoundJammed" value="Weapons/weapon_jam" /> 
       <property name="Attachments" value="flashlight02" /> 
     <property class="Parts"> 
      <property name="Stock" value="pistol_grip" /> 
      <property name="Receiver" value="pistol_receiver" /> 
      <property name="Pump" value="pistol_parts" /> 
      <property name="Barrel" value="pistol_barrel" /> 
     </property> 
     <property class="Action0"> 
      <property name="Class" value="Ranged" /> 
      <property name="Delay" value="0.15" /> 
      <property name="Range" value="120" /> 
      <property name="DamageBlock" value="1" /> 
      <property name="Magazine_size" value="15" /> 
      <property name="Magazine_items" value="9mmBullet, incendiary9mmBullet" /> 
      <property name="Reload_time" value="2" /> 
      <property name="Bullet_icon" value="pistol" /> 
      <property name="Sound_start" value="Weapons/Ranged/Pistol/pistol_fire" /> 
      <property name="Sound_repeat" value="" /> 
      <property name="Sound_end" value="" /> 
      <property name="Sound_empty" value="Weapons/weapon_empty" /> 
      <property name="Sound_reload" value="Weapons/Ranged/Pistol/pistol_reload" /> 
      <property name="Particles_muzzle_fire" value="nozzleflash" /> 
      <property name="Particles_muzzle_smoke" value="nozzlesmoke" /> 
      <property name="DamageBonus.head" value="6" /> 
      <property name="DamageBonus.glass" value="25" /> 
     </property> 
     <property class="Action1"> 
      <property name="Class" value="Zoom" /> 
      <property name="Zoom_max_out" value="35" /> 
      <property name="Zoom_max_in" value="35" /> 
     </property> 
       <property name="LightSource" value="lightSource" /> 
       <property name="ActivateObject" value="Attachments/flashlight/lightSource" /> 
       <property name="AttachmentFlashlight" value="flashlight02" /> 
     <property name="Group" value="Ammo/Weapons" /> 
     <property class="Preview"> 
      <property name="Zoom" value="14" /> 
      <property name="Pos" value="0.1,-0.1" /> 
      <property name="Rot" value="0,-45,0" /> 
     </property> 
    </item> 
</items> 

下面是实际的程序

#!/usr/local/bin/perl 
use warnings; 
#use strict; 
use XML::Simple qw(:strict); 
use Data::Dumper; 

my $xml = new XML::Simple; 

my $data = $xml->XMLin(undef, KeyAttr => { item => 'name' }, ForceArray => ['item', 'property', 'property']); 
#my $data = XMLin ($xml, forcearray => [ qw (item property property) ], keyattr = +> []); 



#print Dumper($data); 

#my @itemlist = @{$data->{name}}; 
#print Dumper(\@itemlist); 

my $items = $data->{item}; 

for my $item_name (keys %$items) { 
my $item = $items->{$item_name}; 
my $item_id = $item->{id}; 
my $props = $item->{property}; 

print "Name: " . $item_name . " ID: " . $item_id; 

for my $prop (@$props) 
{ 
my $prop_name = $prop->{name}; 
my $prop_value = $prop->{value}; 

print $prop_name ": " . $prop_value . "\n"; 
} 

} 

真的只是在寻找像我如何访问实际的项目名称(在这种情况下的几件事情pistol)从一个foreach,我将如何下降到财产或财产的财产。我敢肯定,我只是搞砸了什么是哈希与数组,还是没有设置项目,但我还没有发现任何足够接近我的XML数据的例子。

(数据自卸车给我这个)

$VAR1 = { 
      'item' => { 
        'pistol' => { 
           'id' => '1', 
           'property' => [ 
               { 
               'value' => 'Items/Weapons/Ranged/Pistol/PistolPrefab', 
               'name' => 'Meshfile' 
               }, 
               { 
               'value' => 'metal', 
               'name' => 'Material' 
               }, 
               { 
               'value' => '1', 
               'name' => 'HoldType' 
               }, 
               { 
               'value' => '1', 
               'name' => 'Stacknumber' 
               }, 
               { 
               'value' => 'repairKit,repairKit2ndGeneration,repairKit3rdGeneration', 
               'name' => 'RepairTools' 
               }, 
               { 
               'value' => '175', 
               'name' => 'Degradation', 
               'param1' => 'false' 
               }, 
                etc 

错误:

没有更多的错误!

+1

参见:[?为什么XML ::简单的“劝阻”(http://stackoverflow.com/q/33267765/589924) – ikegami

+0

给我们一些样品XML,我们可以给你一个更好的答案。能够使用基于XML的构造意味着代码不会让人头疼。 – Sobrique

回答

1
my $items = $data->{item}; 
for my $item_name (keys %$items) { 
    my $item = $items->{$item_name}; 
    my $item_id = $item->{id}; 
    my $props = $item->{property}; 
    for my $prop (@$props) { 
     my $prop_name = $prop->{name}; 
     my $prop_value = $prop->{value}; 
     ... 
    } 
} 

你,因为更新已经表明,一些属性是这样的:

{ 
    'name' => '...' 
    'value' => '...', 
} 

和一些看起来像

{ 
    'class' => '...', 
    'property' => [ ... ], 
} 

,但你的代码只处理第一类。你可能想要类似if ($prop->{class})


print $prop_name ": " . $prop_value . "\n"; 

对待$prop_name的文件句柄。它应该是

print $prop_name . ": " . $prop_value . "\n"; 
+0

非常感谢。我试着解决这个问题,其实是通读了你之前的几个答案。我敢肯定,我可以回溯你所做的事情,弄清楚如何获得身份证或房产价值。非常感谢! – Calbrenar

+0

添加到我的答案。 – ikegami

+0

我在$ name $ id和$ props上添加了一个简单的打印。 $ name的作品,但我使用未初始化的值使用id和道具和打印语句的id和提示行。我认为道具将会是另一个散列或数组引用,并且可能有另一个数组/散列在里面? – Calbrenar

0

这并不直接回答你的问题,但我希望能表现出另一种方法 - 我坚信,XML::Simple ...不是。它使你的代码远比它所需要的复杂。因此,在您的解析XML的几个例子:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use XML::Twig; 

#parse the file  
my $twig = XML::Twig -> new(); 
    $twig -> parsefile ('sample.xml'); 

#iterate 'item' elements - note '//' means anywhere in document. 
#you can use './' to denote only things under the current node. 
foreach my $item ($twig -> get_xpath ('//item')) { 

    #item attributes: 
    print "ID: ", $item -> att('id'),"\n"; 
    print "name: ", $item -> att('name'),"\n"; 

    #subelement with a specific attribute name: 
    print "Material: ", $item -> get_xpath("./property[\@name='Material']", 0) -> att('value'),"\n"; 

    #grab a nested property: 
    print "Action0 Range:"; 
    #nb - errors on item 2, because it doesn't exist. This is illustrative. 
    print $item -> get_xpath(q{./property[@class='Action0']/property[@name='Range']},0) -> att('value'),"\n"; 


    #iterate children: 
    print "Properties:\n"; 
    #note - children only iterates beneath current node. 
    foreach my $property ($item -> children('property')) { 
     print $property -> att('name'),"\n" if defined $property->att('name'); 
    } 

} 
+0

我看到了Twig,真的很想使用它,但不幸的是,我为我的网站提供的服务器主机没有Twig或Lib:XML因此被卡住,并且XML简单。我打算与他们打开一张票来尝试安装它。不知道需要多长时间,但肯定会尝试你的代码。 – Calbrenar

+0

它通常在默认存储库。我已经在我的Linux版本上安装了'yum install'。但我真的认为这是值得的 - 'XML :: Simple' ...实际上并不比使用[正则表达式解析]更好(http://stackoverflow.com/questions/1732348/regex-match-open- tags-except-xhtml-self-contained-tags/1732454#1732454) – Sobrique

+0

我试过了,阅读更容易。感谢您展示这种替代方法 – Calbrenar

相关问题