首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >xml::简单地将xml转换为perl哈希警告“非唯一值”。

xml::简单地将xml转换为perl哈希警告“非唯一值”。
EN

Stack Overflow用户
提问于 2018-09-23 13:34:11
回答 1查看 440关注 0票数 0

我有一个格式良好的XML,我正试图用perl模块XML::Simple将其转换为哈希。该文件中有一些部分无法正确解析。是否有任何方法(或解决办法)能够正确解析xml并获得所需的结果?

代码语言:javascript
复制
D:\tmp>perl parse_dns2.pl dns_problem_public.xml
Warning: <dns_entry> element has non-unique value in 'domain' key attribute: 
0 at parse_dns2.pl line 9.
Warning: <dns_entry> element has non-unique value in 'domain' key attribute: 
example.com at parse_dns2.pl line 9.
Warning: <dns_entry> element has non-unique value in 'domain' key attribute: 
test.com at parse_dns2.pl line 9.
$VAR1 = {
  'dns_timeout' => '20',
  'local_dns' => {
    'dns_entry' => {
      '0' => {
        'content' => '192.168.120.32'
      },
      'domain.example.com' => {
        'content' => '172.16.113.13'
      },
      'example.com' => {
        'content' => '172.16.113.13'
      },
      'test.com' => {
        'content' => '172.17.0.113'
      }
    }
  }
};

我的代码是清晰的:

代码语言:javascript
复制
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use XML::Simple;
use Data::Dumper;

my $ref = XMLin(
    $ARGV[0],
    ForceArray => ['dns_entry'],
    KeyAttr    => { 'dns_entry' => 'priority' },
    KeyAttr    => { 'dns_entry' => 'domain' },
    ForceContent => 0
);

print Dumper $ref;

xml文件(相关部分)包含我需要用作键的属性:

代码语言:javascript
复制
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE config SYSTEM "config.dtd"> 
<dns>
    <local_dns>
        <dns_entry priority="0">192.168.120.31</dns_entry>
        <dns_entry priority="0">192.168.120.32</dns_entry>
        <dns_entry domain="example.com">172.16.103.20</dns_entry>
        <dns_entry domain="example.com">172.16.113.13</dns_entry>
        <dns_entry domain="test.com">172.17.0.111</dns_entry>
        <dns_entry domain="test.com">172.17.0.113</dns_entry>
        <dns_entry domain="domain.example.com">172.16.103.20</dns_entry>
        <dns_entry domain="domain.example.com">172.16.113.13</dns_entry>
    </local_dns>
    <dns_timeout>20</dns_timeout>
</dns>

XML::Simple不能接受具有相同属性的相似元素(尽管值不同)的第一个问题。第二个问题是,我只能在同一个XML块中使用一个属性作为关键属性。

预期结果:

代码语言:javascript
复制
$VAR1 = {
  'local_dns' => {
    'dns_entry' => {
      'domain' => {
        'domain.example.com' => {
          'content' => [
            '172.16.113.20',
            '172.16.113.13'
          ]
        },
        'example.com' => {
          'content' => [
            '172.16.113.20',
            '172.16.113.13'
          ]
        },
        'test.com' => {
          'content' => [
            '172.17.0.111',
            '172.17.0.111'
          ]
        }
      },
      'priority' => {
        '0' => {
          'content' => [
            '192.168.120.31',
            '192.168.120.32'
          ]
        }
      }
    }
  },
  'dns_timeout' => '20'
};
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-23 20:54:52

节点不能有多个内容,因此需要进行一些转换。

您应该借此机会避免使用XML解析器的most complicated。很难使用自己的文档,建议不要使用它。

这里有一个XML::LibXML解决方案:

代码语言:javascript
复制
use XML::LibXML qw( );

my $doc = XML::LibXML->new->parse_file('dns.xml');

my %data;
{
   $data{dns_timeout} = $doc->findvalue('/dns/dns_timeout/text()');

   for my $dns_entry_node ($doc->findnodes('/dns/local_dns/dns_entry')) {
      my $addr = $dns_entry_node->textContent();

      if (defined( my $priority = $dns_entry_node->getAttribute('priority') )) {
         push @{ $data{local_dns}{dns_entry}{priority}{$priority} }, $addr;
      }

      if (defined( my $domain = $dns_entry_node->getAttribute('domain') )) {
         push @{ $data{local_dns}{dns_entry}{domain}{$domain} }, $addr;
      }
   }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52466620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档