7

我有一个包含电影的 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]";

它返回所有电影..

4

3 回答 3

4

好吧,像往常一样,有不止一种方法可以做到这一点。) 要么让 XPath 工具知道它应该将日期(从一开始就不知道)与以下内容进行比较:

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

...或者你只是硬着头皮比较'yyyy'子串:

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

我想前者在语义上更好,但需要一个支持 XPath 2.0 的高级 XML 解析器工具。后者通过 XML::XPath 成功验证。

更新:我想解释一下为什么您的第一个查询有效。)看,你不在那里比较日期 - 你比较数字,但只是因为'='运算符。从文档中引用:

当要比较的对象都不是节点集并且运算符是 = 或 != 时,通过将对象转换为如下的通用类型然后进行比较来比较对象。如果至少一个要比较的对象是布尔值,则每个要比较的对象都被转换为布尔值,就好像通过应用布尔函数一样。否则,如果至少一个要比较的对象是一个数字,则每个要比较的对象都被转换为一个数字,就好像通过应用 number 函数一样。

看?您的 '2012-09-24' 被转换为数字 - 并成为 2012。当然,它等于 2012。)

但是,这不适用于任何其他比较运算符:这就是您需要使用子字符串或将日期字符串转换为数字的原因。我认为第一种方法更具可读性——也许也更快。)

于 2012-06-24T14:43:07.783 回答
1

使用这个 XPath,检查年份

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

您的 Perl 脚本将是,

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

或者

my $query = "//collection/film[substring-before(date, '-') = '2012']";
于 2012-06-24T14:54:06.110 回答
0

只需使用

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

这会从日期中删除破折号,然后将其比较为小于 2012-01-01(删除破折号)。

以同样的方式,您可以获得日期早于给定日期(不仅是年份)的所有电影:

//collection/film[translate(date, '-', '') < translate($theDate, '-', '']
于 2012-06-24T15:17:08.190 回答