2012-03-21 3 views
0

부모 노드에서 하위 노드의 순서를 반대로해야합니다. 이것은 XML입니다 :perl에서 XML 노드를 반전

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE tv SYSTEM "xmltv.dtd"> 

<tv source-info-name="BDS" generator-info-name="mc2xml" generator- info-url="mailto:[email protected]"> 
<channel id="I2.751784.microsoft.com"> 
    <display-name>2 1Xtra BBC</display-name> 
    <display-name>2</display-name> 
    <display-name>1Xtra BBC</display-name> 
    <display-name>BBC R1X</display-name> 
</channel> 

난 단지 이들 항목 해당 번호로 각색이기 때문에 짜증나 이름으로 첫 display-name 노드를 필요로이 XML 피드 프로그램.

그래서 가장 마지막 노드가 먼저 오길 원합니다.

이 스크립트를 사용하여 channel 개의 노드를 가져옵니다. 이것은 2 xml을 병합하는 코드의 일부입니다. 그러나 나는에 거기에서 붙어 :

foreach my $chan ( $t2->findnodes('//channel')) { 
    $root->insertAfter($chan, $last_chan); 
    $last_chan = $chan; 
} 

답변

0
for my $channel_node ($root->findnodes('//channel')) { 
    for my $child_node (reverse $channel_node->childNodes()) { 
     $channel_node->removeChild($child_node); 
     $channel_node->appendChild($child_node); 
    } 
} 

appendChild 노드가 부모의 이미 아이, removeChild의 따라서 사용하는 경우가 작동하지 않습니다 말한다. 그러나 테스트 결과 removeChild은 실제로 필요하지 않습니다.

+0

첨부 된 노드에서 'appendChild'를 사용하면 DOM을 사용할 수 있습니다. 내 솔루션을 참조하십시오. 코드에서'removeChild' 행을 꺼내면 모두 잘 될 것입니다. – Borodin

+0

@ Borodin, 나는 이미'removeChild'를 호출하지 않고 작동한다고 말했다. 왜 내 노드의 내용을 주석으로 계속 반복합니까? 그리고 그 함의에도 불구하고, 모두 거기에'replaceChild'를 잘 사용하고 있습니다. 그래서 문서를 따라갈 수도 있습니다. – ikegami

+0

내 잘못 - 귀하의 게시물을 잘못 읽었습니다. 당신의 * 노드들에 의해 당신은 무엇을 의미합니까? 당신은 의도했던 것보다 훨씬 더 많은 의견을 읽고 있습니다. 나는 당신에게 잘못을 고르려는 것이 아닙니다.하지만 당신이 대답을 올린 사람이 누구인지 알았다면 당신의 반응을 언급하지 않았을 것입니다. – Borodin

1

이 예는 가능한 해결책을 보여줍니다.

use strict; 
use warnings; 

use XML::LibXML; 

my $xml = XML::LibXML->load_xml(string => <<'END'); 
<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE tv SYSTEM "xmltv.dtd"> 

<tv source-info-name="BDS" generator-info-name="mc2xml" generator-info-url="mailto:[email protected]"> 
<channel id="I2.751784.microsoft.com"> 
    <display-name>2 1Xtra BBC</display-name> 
    <display-name>2</display-name> 
    <display-name>1Xtra BBC</display-name> 
    <display-name>BBC R1X</display-name> 
</channel> 
</tv> 
END 

for my $chan ($xml->findnodes("/tv/channel")) { 
    $chan->appendChild($_) for reverse $chan->childNodes; 
} 

print $xml->toString(1); 

출력

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE tv SYSTEM "xmltv.dtd"> 
<tv source-info-name="BDS" generator-info-name="mc2xml" generator-info-url="mailto:[email protected]"> 
<channel id="I2.751784.microsoft.com"> 
<display-name>BBC R1X</display-name> 
    <display-name>1Xtra BBC</display-name> 
    <display-name>2</display-name> 
    <display-name>2 1Xtra BBC</display-name> 
    </channel> 
</tv> 

편집

나는 당신의 요구 사항을 오해하고 각 <channel> 내에서 역전 <display-name> 요소를 원한다고 생각. 다음은 <channel> 요소를 <tv> 번으로 바꿔 코드의 핵심 부분입니다.

my @channels = $xml->find('/tv/channel'); 
my $tv = $channels[0]->parentNode; 
$tv->appendChild($_) for reverse @channels; 

지금 나는 바로 처음 생각합니다. 골라보세요!

+0

당신은 정말로 처음에는 옳았습니다! 그리고 그것은 일종의 작품입니다. print $ t1-> toString (1);'실제로 올바른 순서를 보여 주지만 나중에 수정해도 동일한 순서가 사용됩니다 ... 어떤 방법으로 변경 사항을 적용해야합니까? – skerit

+0

변경 사항은 Perl의 XML 구조에 대한 내부 표현에만 적용됩니다. 그래서'print $ xml-> toString (1)'을 추가했습니다. 수정 된 XML을 파일에 저장하거나 소스 파일을 덮어 쓰거나 다른 파일에 저장 한 다음 새 버전을 사용해야합니다. – Borodin

관련 문제