2009-06-13 85 views
3

我使用LibXML解析XML文件,并需要按日期对条目进行排序。每个条目都有两个日期字段,一个用于发布条目,另一个用于更新时间。如何使用LibXML和Perl对XML条目进行排序?

<?xml version="1.0" encoding="utf-8"?> 
... 
<entry> 
    <published>2009-04-10T18:51:04.696+02:00</published> 
    <updated>2009-05-30T14:48:27.853+03:00</updated> 
    <title>The title</title> 
    <content>The content goes here</content> 
</entry> 
... 

XML文件已按更新日期排序,最近排在第一位。我可以很容易地逆转,要首先把旧的条目:

my $parser = XML::LibXML->new(); 
my $doc = $parser->parse_file($file); 
my $xc = XML::LibXML::XPathContext->new($doc->documentElement()); 

foreach my $entry (reverse($xc->findnodes('//entry'))) { 
    ... 
} 

不过,我需要逆向排序按日期公布的文件,而不是按日期进行更新。我怎样才能做到这一点?时间戳也看起来有点won。。我需要首先对其进行标准化吗?

谢谢!

更新: 在摆弄XPath命名空间和失败之后,我做了一个函数,它解析XML并将所需的值存储在一个哈希中。然后,我用一个光秃秃的sort对散列进行排序,现在工作得很好。

+1

很高兴看到你去了XML :: LibXML路线。要习惯XML的严格性有点困难,但从长远来看,它将为您节省大量时间。 (我不得不与那些在实现XML时使用捷径的供应商合作,这意味着我实际上不能给他们XML,我不得不给他们一些标签汤,非常恼人。) – jrockway 2009-06-14 12:49:55

回答

5

一个办法是改变你的reversesort声明(未经测试):

sub parse_date { 
    # Transforms date from 2009-04-10T18:51:04.696+02:00 to 20090410 
    my $date= shift; 
    $date= join "", $date =~ m!\A(\d{4})-(\d{2})-(\d{2}).*!; 
    return $date; 
} 

sub by_published_date { 
    my $a_published= parse_date($a->getChildrenByTagName('published')); 
    my $b_published= parse_date($b->getChildrenByTagName('published')); 

    # putting $b_published in front will ensure the descending order. 
    return $b_published <=> $a_published; 
} 

foreach my $entry (sort by_published_date $xc->findnodes('//entry')) { 
    ... 
} 

希望这有助于一点!

+0

啊,我现在看到了,我想。 .. $ a和$ b是两个单独的条目,对吗?但是,我怎样才能以编程方式浏览所有条目?有些文件有数百个条目... – Andrew 2009-06-13 12:45:15

+0

我仍然没有得到$ a和$ b的来源... – Andrew 2009-06-13 13:58:46

2

裸排序可能把从不同的时区超时的顺序:

print for sort "2009-06-15T08:00:00+07:00", "2009-06-15T04:00:00+00:00"; 

在这里,第二时间为3小时后的第一个,但首先进行排序。

我不确定你的意思是“wonky”。您的示例仅显示rfc3339格式的时间戳。

相关问题