필터 텍스트 XML 파일

필터 텍스트 XML 파일

특정 필드만 필터링하려는 대규모(수십만 개의 레코드 포함) XML 파일이 있습니다. 파일 구성 예:

<A>
<id>123</id>
<B>
   <C>value1</C>
   <D>value2</D>
   ....
   <E></E>
</B>
<Z></Z>
...
<Y></Y>
<A>

이 XML 파일을 필터링하고 C 및 D 필드에 포함된 ID와 데이터만 포함하고 싶습니다.

어떻게 해야 하나요?

답변1

이것xmlstarlet이 도구는 다음을 수행합니다.

xmlstarlet sel -t -m /A -o ID, -v id -n -o C, -v //C -n -o D, -v //D -n test.xml 

루트 요소( ) -m /A아래의 각 A 에 대해 문자열 "ID"( -o ID,), id의 내용( ) -v id, 줄 바꿈( )을 인쇄하고 하위 요소 C( ) 및 D( ) 및 해당 항목 -n에 대해서도 마찬가지입니다. 헤더. 이중 슬래시는 "노드 아래 어디든 일치"를 의미하는 XPath입니다.-v //C-v //D

테스트 파일을 사용하여 내 시스템에서 테스트한 결과는 쉼표로 구분된 출력입니다.

ID,123
C,value1
D,value2

헤더가 필요하지 않으면 -o <whatever>매개변수를 생략하세요.

감사해요이 기사설명하다.

답변2

이 질문에 제대로 대답하려면 이상적으로는 더 나은 예가 필요합니다.효과적인xml은 좋은 시작입니다.

또한 - 원하는 출력의 예입니다. 예를 들어 생성된 XML에서 <C><D>요소가 끝나는 위치를 지정할 필요가 없습니다 . 그들은이미하위 항목 - 루트 뿐만 아니라 상위 항목도 유지하거나 다시 부모로 지정 <B>하시겠습니까 ? BCD

그러나 일반적으로 말하면 사용 및 재구축이 매우 쉽습니다 XML.XML::Twigperl

예를 들면 다음과 같습니다.

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my @wanted = qw ( C D id );


my %wanted = map { $_ => 1 } @wanted; 

sub delete_unwanted_tags {
   my ( $twig, $element ) = @_;
   my $tag = $element -> tag;
   if ( not $wanted{$tag} ) {
        $element -> delete;
   }
}

my $twig = XML::Twig -> new ( twig_handlers => { _all_ => \&delete_unwanted_tags } );
$twig -> parse ( \*DATA );
$twig -> print;

__DATA__
<A>
<id>123</id>
<B>
   <C>value1</C>
   <D>value2</D>
   <E></E>
</B>
<Z></Z>
<Y></Y>
</A>

"유지"라고 말하지 않았으므로 <B>결과는 다음과 같습니다.

<A>
  <id>123</id>
</A>

<B>목록 에 추가 wanted:

<A>
  <id>123</id>
  <B>
    <C>value1</C>
    <D>value2</D>
  </B>
</A>

그러나 원하는 작업이 부모를 다시 지정 C하고 D다음을 입력하는 경우 A:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my @wanted   = qw ( id);
my @reparent = qw ( C D );

#turn the above into hashes, so we can do "if $wanted{$tag}"
my %wanted   = map { $_ => 1 } @wanted;
my %reparent = map { $_ => 1 } @reparent;

sub delete_unwanted_tags {
    my ( $twig, $element ) = @_;
    my $tag = $element->tag;
    if ( not $wanted{$tag} ) {
        $element->delete;
    }
    if ( $reparent{$tag} ) {
        $element->move( 'last_child', $twig->root );
    }
}

my $twig = XML::Twig->new(
    pretty_print  => 'indented_a',
    twig_handlers => { _all_ => \&delete_unwanted_tags }
);
$twig->parse( \*DATA );
$twig->print;

__DATA__
<A>
<id>123</id>
<B>
   <C>value1</C>
   <D>value2</D>
   <E></E>
</B>
<Z></Z>
<Y></Y>
</A>

참고 - "나뭇가지 처리기"가각 요소의 값(닫는 태그가 발견될 때)이 작동하는 이유입니다. 처리(및 삭제)를 완료하기 전에 재귀적으로 합계를 찾습니다 C.DB

그러면 다음이 생성됩니다.

<A>
  <id>123</id>
  <C>value1</C>
  <D>value2</D>
</A>

__DATA__위에서 는 XML과 기술을 설명할 수 있는 를 \*DATA사용 했습니다 . parse아마도 를 parsefile('my_file.xml')사용해야 할 것입니다 parse(\*DATA).

답변3

ltXML2 툴킷(에딘버러 대학교)의 lxgrep을 사용하세요.

$ lxgrep -w A '(id|C|D)' test.xml
<A>
<id>123</id>
<C>value1</C>
<D>value2</D>
</A>

이러한 유형의 도구를 사용하는 것은멀리직접 하는 것보다 빠르고 안정적입니다.


XML FAQ:http://xml.silmaril.ie/

관련 정보