在perl中反转XML节点

时间:2012-03-21 21:14:18

标签: xml perl libxml2

我需要反转父节点中子节点的顺序。 这是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:mc2xml@gmail.com">
<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>

我将此xml提供的程序仅将第一个display-name节点作为名称,这很烦人,因为这些项目是按该编号进行编排的。

所以我希望最后一个节点首先出现。

我正在使用此脚本来获取channel个节点。这是合并2 xml的代码的一部分。但是我被困在那里:

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

2 个答案:

答案 0 :(得分: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:mc2xml@gmail.com">
<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:mc2xml@gmail.com">
<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>

修改

我误解了您的要求,并认为您希望<display-name>元素在每个<channel>内反转。以下是反转<channel><tv>元素的代码的核心。

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

现在我认为我第一次是对的。随便挑选!

答案 1 :(得分: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