2012-06-24 24 views
7

之前搜索項目我有一個包含電影,例如XML數據庫:Perl中的XPath:日期一年

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

從一個Perl腳本,我想按日期查找電影。 如果我搜索一個exacly年的電影,例如:

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

它的工作原理完全和返回2012年的所有電影,但是如果我在一年前搜索所有電影,它沒有工作,例如:

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

返回所有的電影..

+1

相關:http://stackoverflow.com/questions/4347320/xpath-dates比較 – dusan

回答

4

好,像往常一樣,不止一種方法去做一件事。 )你可以讓XPath的工具,知道它應該有這樣的事情比較日期(它不會從一開始就知道了):

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

...或者你只是硬着頭皮只是比較「YYYY」子:

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

前者是更好的語義,我想,但需要一個先進的XML解析器工具,它支持XPath 2.0。後者已成功通過XML :: XPath驗證。

更新:我想給我解釋爲什麼你的第一個查詢工作。 )看,你不會比較那裏的日期 - 你比較數字,但只是因爲'='運算符。從the doc引用:

當待比較既不對象是一個節點集合和運算符是= 或=,則目的是通過將它們轉換爲一個公共 類型如下,然後比較它們相比! 。如果要比較的至少一個對象是布爾值,則每個要比較的對象都將被轉換爲布爾值,如同應用布爾函數一樣。否則,如果在 至少有一個要比較的對象是一個數字,那麼比較每個對象 將被轉換爲數字,就好像通過應用數字 函數一樣。

請參閱?你的'2012年9月24日'被轉換爲數字 - 併成爲2012年。當然,這相當於2012年。)

這不適用於任何其他比較運營商,但這就是爲什麼您需要要麼使用子字符串,要麼將日期字符串轉換爲數字。我認爲第一種方法會更具可讀性 - 也許更快。)

+0

+1罕見的非hacky XPath解決方案 – daxim

1

使用這個XPath,檢查年度

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

你的Perl腳本會,

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

OR

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

只需使用

//collection/film[translate(date, '-', '') < 20120101] 

這將從日期中刪除破折號,然後將其與2012-01-01進行比較(刪除破折號)。

以同樣的方式,你可以得到的日期所有電影之前給定的日期(不只是一年):

//collection/film[translate(date, '-', '') < translate($theDate, '-', '']