2012-06-24 15 views
7

que tiene una base de datos XML que contiene las películas, por ejemplo:Perl XPath: elemento de búsqueda antes de un año la fecha

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

Desde un script en Perl que quiero encontrar la película por fecha. si busco películas de un año exacly, por ejemplo:

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

funciona exactamente y volver todas las películas de 2012 años, pero si busco toda la película antes de un año, no funcionó, por ejemplo:

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

devuelve toda la película ..

+1

relacionadas: http://stackoverflow.com/questions/4347320/xpath-dates -comparación – dusan

Respuesta

4

Bueno, como de costumbre, hay más de una manera de hacerlo.) O dejas herramienta XPath sabe que debe comparar las fechas (no se sabe desde el principio) con algo como esto:

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

... o simplemente de tripas corazón y simplemente comparar el 'aaaa' subseries:

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

el primero es mejor semánticamente, supongo, pero requiere una herramienta de analizador XML avanzada que soporta XPath 2.0. Y el último se verificó con éxito con XML :: XPath.

ACTUALIZACIÓN: Me gustaría dar mi explicación de por qué funciona su primera consulta.) Ver, no se comparan fechas allí - se comparan los números, pero solo por el operador '='. Presupuesto de the doc:

Cuando ni objeto a comparar es un conjunto de nodos y el operador es = o =, entonces los objetos se comparan mediante la conversión a un común tipo de la siguiente manera y luego compararlos! . Si al menos un objeto para ser comparado es un booleano, entonces cada objeto a comparar se convierte en un booleano como si aplicara la función booleana. De lo contrario, si al menos un objeto para comparar es un número, entonces cada objeto que se comparó se convierte a un número como si aplicara la función número .

Ver? Su '2012-09-24' se convirtió en número, y se convirtió en 2012. Lo que, por supuesto, es igual a 2012.)

Esto no funciona con ningún otro operador comparativo, sin embargo: es por eso que necesita use subcadena o convierta la cadena de fecha en número. Supuse que el primer enfoque sería más legible, y más rápido también, tal vez.)

+0

+1 rara solución XPath no hacky – daxim

1

Utilice esta XPath, para comprobar el año será

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

Su script Perl,

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

O

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

Sólo tiene que utilizar:

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

Esto quita los guiones de la fecha y luego lo compara por ser menor que 2012-01-01 (con los guiones eliminados).

De la misma manera se puede conseguir todas las películas con fechas antes de una fecha determinada (no sólo el año):

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