Dodatek E. Import metadanych z formatu XML

Funkcjonalność aplikacji redaktora i administratora można rozszerzać przy pomocy tzw. rozszerzeń. Między innymi można dodawać rozszerzenia umożliwiające import metadanych do systemu dLibra z zewnętrznych źródeł. Takim właśnie rozszerzeniem jest rozszerzenie umożliwiające importowanie opisu bibliograficznego z pliku zapisanego w formacie XML (informacje na temat formatu XML można znaleźć tutaj).

Rozszerzenie umożliwiające import metadanych z formatu XML bazuje na zapytaniach XQuery (informacje na temat XQuery można znaleźć tutaj). Poniższy opis zakłada, że czytelnik jest zaznajomiony z standardem XQuery.

Aby była możliwość importowania opisu bibliograficznego, rozszerzenie XML musi być odpowiednio skonfigurowane. Domyślna konfiguracja tego rozszerzenia pozwala na importowanie opisu bibliograficznego z formatu RDF oraz z formatu MASTER.

Rozszerzenie XML konfiguruje się przy użyciu dwóch plików właściwości (pliki właściwości zawierają pary klucz=wartość):

Powiązanie pomiędzy tymi plikami jest bardzo ścisłe - dla każdego testu z pliku tests.properties istnieją reguły konwersji w pliku conversion.properties. Dla pliku XML z metadanymi mechanizm importu wykonuje po kolei zapytania testowe z pliku tests.properties. Jeśli natrafi na zapytanie, które zwraca więcej niż 0 wartości to importuje metadane z pliku XML przy użyciu reguł konwersji (z pliku conversion.properties) odpowiadających testowi.

W pliku tests.properties zamieszczone są zapytania XQuery, które sprawdzają czy dany plik z metadanymi można importować przy użyciu reguł konwersji skojarzonych z tym zapytaniem. Klucz identyfikuje reguły konwersji w pliku conversion.properties.

Przykładowo załóżmy, że mamy następujące pliki (przykład ten prezentuje domyślną konfigurację rozszerzenia):

plik tests.properties:

master=for $x in fn:doc({document})/*[fn:compare(fn:name(), 'msDescription')=0] return $x
rdf_dc=for $x in fn:doc({document})/*[fn:compare(fn:local-name(), 'RDF')=0] return $x

plik conversion.properties:

master.Title=for $x in fn:doc({document})//msHeading/title return $x
master.Creator=for $x in fn:doc({document})//msHeading/author return $x 
master.Description=for $x in fn:doc({document})//msContents/overview return $x
master.Publisher=for $x in fn:doc({document})//msContents/respStmt/resp/name return $x
master.Contributor=for $x in fn:doc({document})/msDescription/msContents/respStmt//resp return $x
master.Date=for $x in fn:doc({document})//msHeading/origDate return $x
master.Type=for $x in fn:doc({document})//physDesc/form return $x
master.Identifier=for $x in fn:doc({document})//msIdentifier/country/settlement/repository/idno return $x
master.Source=for $x in fn:doc({document})//msPart//idno return $x
master.Language=for $x in fn:doc({document})//msContents/textLang return $x
master.Language=for $x in fn:doc({document})//msContents/textLang/@otherLangs return $x
master.Rights=for $x in fn:doc({document})//msIdentifier/repository return $x

rdf_dc.Title=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Title'] return $x
rdf_dc.Creator=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Creator'] return $x
rdf_dc.Subject=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Subject'] return $x
rdf_dc.Description=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Description'] return $x
rdf_dc.Publisher=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Publisher'] return $x
rdf_dc.Contributor=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Contributor'] return $x
rdf_dc.Date=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Date'] return $x
rdf_dc.Type=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Type'] return $x
rdf_dc.Identifier=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Identifier'] return $x
rdf_dc.Source=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Source'] return $x
rdf_dc.Language=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Language'] return $x
rdf_dc.Relation=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Relation'] return $x
rdf_dc.Coverage=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Coverage'] return $x
rdf_dc.Rights=for $x in fn:doc({document})//*[fn:local-name()='Description']/*[fn:local-name()='Rights'] return $x

Jak widać, plik conversion.properties zawiera reguły konwersji odpowiadające testom z pliku tests.properties. Klucz w pliku conversion.properties składa się z klucza identyfikującego test w pliku tests.properties, kropki oraz identyfikatora atrybutu (nazwy RDF) w systemie dLibra. Wartości zapytań znajdujących się w pliku conversion.properties zostaną przypisane atrybutom o określonej nazwie RDF.

Załóżmy, że chcemy zaimportować plik A zawierający metadane w formacie XML. Mechanizm importu sprawdza kolejno testy znajdujące się w pliku tests.properties. Pierwszy test, który zwróci w wyniku listę wartości o rozmiarze większym od 0 decyduje o regułach konwersji. Załóżmy ze był to test opatrzony kluczem master. Mechanizm importu wybiera reguły konwersji z pliku conversion.properties - wszystkie te które rozpoczynają się od słowa master. Następnie wartości z zapytań XQuery trafiają do odpowiedniego atrybutu, np. do atrybutu, którego nazwa RDF to Title trafią wszystkie wartości z zapytania for $x in fn:doc({document})//msHeading/title return $x. Jeśli chcemy by dla jednego atrybutu obowiązywały dwa zapytania XQuery to należy dodać kolejną linię z zapytaniem (tak jak ma to miejsce w przypadku atrybutu Language).

Każde zapytanie XQuery powinno wykorzystywać ciąg znaków {document} do określenia dokumentu na którym wykonywane jest zapytanie. Rozszerzenie zamienia ten ciąg znaków scieżką do pliku XML.