我有一个包含电影的xml数据库,例如:
<film id="5">
<title>The Avengers</title>
<date>2012-09-24</date>
<family>Comics</family>
</film>
Run Code Online (Sandbox Code Playgroud)
从Perl脚本我想按日期找到电影.如果我搜索一个exacly年的电影,例如:
my $query = "//collection/film[date = 2012]";
Run Code Online (Sandbox Code Playgroud)
它完全正常并返回2012年的所有电影,但如果我在一年之前搜索所有电影,它就不起作用,例如:
my $query = "//collection/film[date < 2012]";
Run Code Online (Sandbox Code Playgroud)
它返回所有电影..
嗯,像往常一样,有不止一种方法可以做到这一点。)要么让 XPath 工具知道它应该将日期(它从一开始就不知道)与如下内容进行比较:
my $query = '//collection/film[xs:date(./date) < xs:date("2012-01-01")]';
Run Code Online (Sandbox Code Playgroud)
...或者你只是硬着头皮比较“yyyy”子字符串:
my $query = '//collection/film[substring(date, 1, 4) < "2012"]';
Run Code Online (Sandbox Code Playgroud)
我认为前者在语义上更好,但需要支持 XPath 2.0 的高级 XML 解析器工具。并且后者已通过 XML::XPath 成功验证。
更新:我想解释一下为什么你的第一个查询有效。)看,您不在那里比较日期 - 您比较数字,但只是因为“=”运算符。引用文档:
当要比较的对象都不是节点集并且运算符是 = 或 != 时,则通过将对象转换为公共类型然后进行比较来进行比较,如下所示。如果至少一个要比较的对象是布尔值,则每个要比较的对象都会转换为布尔值,就像应用布尔函数一样。否则,如果至少一个要比较的对象是数字,则每个要比较的对象都被转换为数字,就好像通过应用数字函数一样。
看?您的“2012-09-24”已转换为数字 - 并成为 2012。当然,这等于 2012。)
但这不适用于任何其他比较运算符:这就是为什么您需要使用子字符串或将日期字符串转换为数字的原因。我认为第一种方法可能更具可读性,而且速度更快。)