특정 필드만 필터링하려는 대규모(수십만 개의 레코드 포함) 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>
하시겠습니까 ? B
C
D
그러나 일반적으로 말하면 사용 및 재구축이 매우 쉽습니다 XML
.XML::Twig
perl
예를 들면 다음과 같습니다.
#!/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
.D
B
그러면 다음이 생성됩니다.
<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/