Как я могу отсортировать записи XML с помощью LibXML и Perl?
Я анализирую XML-файл с помощью LibXML и мне нужно отсортировать записи по дате. Каждая запись имеет два поля даты, одно для того, когда запись была опубликована, и одно, когда она была обновлена.
<?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'))) {
...
}
Однако мне нужно выполнить обратную сортировку файла по дате публикации, а не по дате обновления. Как я могу это сделать? Отметка времени выглядит немного шатко. Должен ли я сначала нормализовать это?
Спасибо!
Обновление: после того, как я покопался в пространствах имен XPath и потерпел неудачу, я сделал функцию, которая анализировала XML и сохраняла нужные мне значения в хэше. Я тогда использовал голый sort
сортировать хеш, который сейчас работает отлично.
2 ответа
Одним из способов будет изменить ваш reverse
к sort
заявление (не проверено):
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') ) {
...
}
Надеюсь это немного поможет!
Чистая сортировка может привести к смещению времен из разных часовых поясов:
print for sort "2009-06-15T08:00:00+07:00", "2009-06-15T04:00:00+00:00";
Здесь второй раз через 3 часа после первого, но сортирует первый.
Я не уверен, что вы подразумеваете под "вонючий". Ваш пример просто показывает временные метки в формате rfc3339.