2012-06-24 12 views
7

Mam bazy danych XML zawierający filmy, na przykład:Perl Xpath: pozycja wyszukiwania roku przed datą

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

ze skryptu Perl chcę znaleźć filmu według daty. Gdybym wyszukiwać filmy wydane rok exacly, na przykład:

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

to działa dokładnie i zwrócić wszystkie filmy z 2012 roku, ale jeśli mogę szukać cały film przed rokiem, to nie działa, na przykład:

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

zwraca całą folię ..

+1

pokrewne: http://stackoverflow.com/questions/4347320/xpath-dates -porównywalne – dusan

Odpowiedz

4

Cóż, jak zwykle, jest więcej niż jeden sposób, aby to zrobić.) Albo niech narzędzie XPath wiedzieć, że powinien porównać dat (nie wiem od początku) z mniej więcej tak:

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

... lub po prostu zacisnąć zęby i po prostu porównywać „yyyy” podciągi:

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

były to lepiej semantycznie, jak sądzę, ale wymaga zaawansowanych funkcji parsera XML, który obsługuje XPath 2.0. Ta ostatnia została pomyślnie zweryfikowana za pomocą XML :: XPath.

AKTUALIZACJA: Chciałbym podać wyjaśnienie, dlaczego działa pierwsze zapytanie.) Widzisz, nie porównujesz tam dat - porównujesz liczby, ale tylko z powodu operatora "=". Cytat the doc:

Kiedy ani przedmiot należy porównać to zestaw węzłów i operator = lub =, a następnie obiekty są porównywane poprzez przekształcenie ich do wspólnego typu następująco a następnie porównując je! . Jeśli przynajmniej jeden obiekt do porównania jest wartością logiczną, to każdy porównywany obiekt jest konwertowany na na wartość logiczną, jak przy użyciu funkcji boolowskiej. W przeciwnym razie, jeśli co najmniej jeden obiekt do porównania jest liczbą, to każdy obiekt, który ma być porównywany, zostanie przekonwertowany na liczbę tak, jak przy użyciu funkcji o numerze: .

Zobacz? Twój numer "2012-09-24" został przekonwertowany na numer - i stał się numerem 2012. Co, oczywiście, jest równy rokowi 2012.)

Nie działa to z żadnymi innymi operatorami porównawczymi: dlatego musisz albo użyj podłańcucha, albo przekonwertuj ciąg daty na liczbę. Sądziłem, że pierwsze podejście będzie łatwiejsze do odczytania, a może i szybsze.)

+0

+1 rzadki nie-hacki system XPath – daxim

1

Użyj tego XPath, aby sprawdzić roku

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

Twój skrypt Perl będzie,

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

LUB

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

Wystarczy użyć:

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

To usuwa kreski z daty, a następnie porównuje je za mniej niż 2012-01-01 (z usuniętymi myślnikami).

W ten sam sposób można uzyskać wszystkie filmy z dat przed określoną datą (nie tylko rok):

//collection/film[translate(date, '-', '') < translate($theDate, '-', ''] 
Powiązane problemy