我有一个包含电影的xml数据库,例如:
<film id="5">
<title>The Avengers</title>
<date>2012-09-24</date>
<family>Comics</family>
</film>
从Perl脚本我想按日期找到电影。 如果我搜索一个特殊年份的电影,例如:
my $query = "//collection/film[date = 2012]";
它完全奏效并返回2012年的所有电影,但如果我在一年之前搜索所有电影,它就不起作用,例如:
my $query = "//collection/film[date < 2012]";
它返回所有电影..
答案 0 :(得分:4)
嗯,像往常一样,有不止一种方法可以做到这一点。你要么让XPath工具知道它应该比较日期(它从一开始就不知道)用这样的东西:
my $query = '//collection/film[xs:date(./date) < xs:date("2012-01-01")]';
...或者你只是咬紧牙关,只是比较&#39; yyyy&#39;子:
my $query = '//collection/film[substring(date, 1, 4) < "2012"]';
我想,前者在语义上更好,但需要一个支持XPath 2.0的高级XML解析器工具。后者使用XML :: XPath成功验证。
更新:我想解释您的第一个查询有效的原因。 )看,你没有比较那里的日期 - 你比较数字,但只是因为&#39; =&#39;运营商。引自the doc:
当要比较的对象都不是节点集且运算符是=时 或!=,然后通过将对象转换为公共对象来比较对象 键入如下,然后比较它们。如果至少有一个对象 比较是一个布尔值,然后将要比较的每个对象转换为 一个布尔值,好像通过应用布尔函数。否则,如果在 至少有一个要比较的对象是一个数字,然后是每个对象 比较被转换为数字,就像应用数字一样 功能
请参阅?你的2012-09-24&#39;被转换为数字 - 并成为2012年。当然,这相当于2012年。)
这并不适用于任何其他比较运算符:这就是为什么你需要使用substring,或者将date-string转换为数字的原因。我认为第一种方法更具可读性 - 也许更快。 )
答案 1 :(得分:1)
使用此XPath来检查年份
//collection/film[substring-before(date, '-') < '2012']
您的Perl脚本将是,
my $query = "//collection/film[substring-before(date, '-') < '2012']";
OR
my $query = "//collection/film[substring-before(date, '-') = '2012']";
答案 2 :(得分:0)
只需使用:
//collection/film[translate(date, '-', '') < 20120101]
这会从日期中删除破折号,然后将其与2012-01-01(删除破折号)进行比较。
以同样的方式,您可以在指定日期之前获得所有日期(不仅仅是年份)的电影:
//collection/film[translate(date, '-', '') < translate($theDate, '-', '']