Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl Xpath: search item before a date year

Tags:

date

perl

xpath

I have an xml database that contains films, for example:

<film id="5">
        <title>The Avengers</title>
        <date>2012-09-24</date>
        <family>Comics</family>
</film>

From a Perl script I want to find film by date. If I search films of an exacly year, for example:

my $query = "//collection/film[date = 2012]";

it works exactly and return all films of 2012 year, but if I search all film before a year, it didn't work, for example:

my $query = "//collection/film[date < 2012]";

it returns all film..

like image 1000
lory105 Avatar asked Jun 24 '12 14:06

lory105


2 Answers

Well, as usual, there's more than one way to do it. ) Either you let XPath tool know that it should compare dates (it doesn't know from the start) with something like this:

my $query = '//collection/film[xs:date(./date) < xs:date("2012-01-01")]';

... or you just bite the bullet and just compare the 'yyyy' substrings:

my $query = '//collection/film[substring(date, 1, 4) < "2012"]';

The former is better semantically, I suppose, but requires an advanced XML parser tool which supports XPath 2.0. And the latter was successfully verified with XML::XPath.

UPDATE: I'd like to give my explanation of why your first query works. ) See, you don't compare dates there - you compare numbers, but only because of '=' operator. Quote from the doc:

When neither object to be compared is a node-set and the operator is = or !=, then the objects are compared by converting them to a common type as follows and then comparing them. If at least one object to be compared is a boolean, then each object to be compared is converted to a boolean as if by applying the boolean function. Otherwise, if at least one object to be compared is a number, then each object to be compared is converted to a number as if by applying the number function.

See? Your '2012-09-24' was converted to number - and became 2012. Which, of course, is equal to 2012. )

This doesn't work with any other comparative operators, though: that's why you need to either use substring, or convert the date-string to number. I supposed the first approach would be more readable - and faster as well, perhaps. )

like image 60
raina77ow Avatar answered Nov 13 '22 03:11

raina77ow


Use this XPath, to check the year

//collection/film[substring-before(date, '-') &lt; '2012']

Your Perl script will be,

my $query = "//collection/film[substring-before(date, '-') &lt; '2012']";

OR

my $query = "//collection/film[substring-before(date, '-') = '2012']";
like image 36
Siva Charan Avatar answered Nov 13 '22 03:11

Siva Charan