2013-10-17 3 views
2

여기에 총 멍청한 놈이 있으므로 미리 알려지지 않아서 죄송합니다.Perl을 사용하여 XML 구문 분석

내가 검색하고 골치를 쳐본 대부분은 XML::LibXML을 XPath와 함께 사용하는 것을 중심으로하고 있습니다.

내가 가지고있는 문제는 태그 사이에 텍스트를 캡처하는 것이 아니라는 것입니다. 태그 값이 필요합니다.

이 내가 (따옴표없이) 이름 속성을 잡고이 사람이 수퍼 유저 또는 superreader 여부를 결정하기 위해 노력하고

<users> 
    <entry name="asd"> 
    <permissions> 
     <role-based> 
     <superuser>yes</superuser> 
     </role-based> 
    </permissions> 
    </entry> 
    <entry name="fgh"> 
    <permissions> 
     <role-based> 
     <superuser>yes</superuser> 
     </role-based> 
    </permissions> 
    <authentication-profile>RSA Two-Factor</authentication-profile> 
    </entry> 
    <entry name="jkl"> 
    <permissions> 
     <role-based> 
     <superreader>yes</superreader> 
     </role-based> 
    </permissions> 
    <authentication-profile>RSA Two-Factor</authentication-profile> 
    </entry> 
</users> 

내 XML 구조입니다.

노드를 인쇄하는 것 이외에 많은 작업을 수행 할 수 없다는 점에서 저는 막혔습니다. 나는 이것을 username의 구조에서 CSV 파일로 바꾸어야한다; 역할

답변

5

XML::LibXML으로 XML 문서에서 정보를 추출하는 가장 쉬운 방법은 find 패밀리 메소드를 사용하는 것입니다. 이 메소드는 XPath 표현식을 사용하여 문서에서 노드와 값을 선택합니다. 다음 스크립트는 데이터가 필요한 추출 :

use XML::LibXML; 

my $doc = XML::LibXML->load_xml(location => 'so.xml'); 

for my $entry ($doc->findnodes('//entry')) { 
    my $name = $entry->getAttribute('name'); 
    my $role = $entry->findvalue(
     'local-name(permissions/role-based/*[.="yes"])' 
    ); 
    print("$name;$role\n"); 
} 

asd;superuser 
fgh;superuser 
jkl;superreader 

내가 역할 요소의 이름을 얻기 위해 local-name의 XPath 기능을 사용하여 인쇄합니다.

보다 강력한 방법으로 CSV 파일을 만들려면 Text::CSV을 사용하는 것이 좋습니다.

+0

빠른 응답을 주셔서 감사합니다. 나는 이것을 시험해야 할 것이다. getAttribute 호출을 사용하려고 시도하기 전에 그것이 제 패키지에서 알려지지 않았다고 말하고있었습니다. 나는 XML을 사용하고 있었다 : LibXML, 어딘가에 의존성 문제가있을 수 있을까? – user2891632

+2

@ user2891632, 여전히 문제가있는 경우 사용중인 실제 코드와 오류가 표시되는 새로운 질문을 게시하십시오. – friedo

1

나는 이런 프로젝트에 XML::Simple을 사용합니다.

:

use XML::Simple; 

my $su = $ARGV[0]; 
die unless (-e $su); 

my $su_xml = XMLin($su, ForceArray => [ 'entry' ]); 
my $suref = $su_xml->{entry}; 

foreach my $key (keys %{$suref}) { 
    $rb = ${$suref}{$key}->{permissions}->{'role-based'}; 
    foreach my $rbkey (keys %{$rb}) { 
     print "$key\t$rbkey\t${$rb}{$rbkey}\n"; 
    } 
} 

인쇄 :

fgh  superuser  yes 
asd  superuser  yes 
jkl  superreader  yes 
+0

'XML :: Simple'은 종종 너무 간단합니다. 예를 들어, ''이 ''내에있는 경우 스크립트가 중단됩니다. –

+0

@SlavenRezic 잘 잡으세요! 다행스럽게도'XML :: Simple'은 설정이 쉽고 ForceArray를 사용하여이 케이스를 쉽게 설명합니다. 솔루션이 업데이트되었습니다. – David

3

다른 모듈과 다른 방법, XML::Twig :

#!/usr/bin/env perl 

use warnings; 
use strict; 
use XML::Twig; 

my ($name, $role); 

my $twig = XML::Twig->new(
    twig_handlers => { 
     'entry' => sub { 
      $name = $_->att('name'); 
      if (defined $name && defined $role) { 
       printf qq|%s;%s\n|, $name, $role; 
      } 
      map { undef $_ } ($name, $role); 
     }, 
     'role-based' => sub { $role = $_->first_child->tag }, 
    }, 
)->parsefile(shift); 

실행은 그것이 같은

perl script.pl xmlfile 

그 수율 :

asd;superuser 
fgh;superuser 
jkl;superreader 
2

사용하여 XML :: 규칙 :

use XML::Rules; 

print "name is_superuser is_superreader\n"; 
my @rules = (
    entry => sub { 
    my $entry = $_[1]; 
    $_ ||= 'no' for @$entry{qw(superuser superreader)}; 
    print "$entry->{name} $entry->{superuser} $entry->{superreader}\n"; 
    }, 
    'permissions,role-based' => 'pass no content', 
    'superuser,superreader' => 'content', 
    _default => undef, 
); 

my $p = XML::Rules->new(rules => \@rules); 
my $s = $p->parse(doc()); 

sub doc { 
return <<XML; 
<users> 
    <entry name="asd"> 
     <permissions> 
      <role-based> 
       <superuser>yes</superuser> 
      </role-based> 
     </permissions> 
    </entry> 
    <entry name="fgh"> 
     <permissions> 
      <role-based> 
       <superuser>yes</superuser> 
      </role-based> 
     </permissions> 
     <authentication-profile>RSA Two-Factor</authentication-profile> 
    </entry> 
    <entry name="jkl"> 
     <permissions> 
      <role-based> 
       <superreader>yes</superreader> 
      </role-based> 
     </permissions> 
     <authentication-profile>RSA Two-Factor</authentication-profile> 
    </entry> 
</users> 
XML 
} 

또는 모든 컨텐츠를 가정 규칙의 선택적 세트입니다 '예'(그리고 다른 가정) 키 필드 :

my $name; 
my @rules = (
    '^entry' => sub { 
    $name = $_[1]->{name}; 
    }, 
    'superuser,superreader' => sub { 
    print "$name,$_[0]\n"; 
    }, 
    _default => undef, 
);