Mercurial > hg > classical
changeset 4:719a4f477098 classical-rdf
* Add Classical Archives composer list importer; run it
author | Chris Cannam |
---|---|
date | Thu, 10 Dec 2009 15:15:40 +0000 |
parents | 62324586b8d0 |
children | d23a4c935a22 |
files | common/Objects.cpp common/Objects.h import/Import.cpp import/ImportClassicalArchives.cpp import/ImportClassicalArchives.h import/ImportClassicalComposersOrg.cpp import/ImportWikipediaComposers.cpp import/import.pro import/importers.ttl |
diffstat | 9 files changed, 480 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/common/Objects.cpp Tue Dec 08 17:56:37 2009 +0000 +++ b/common/Objects.cpp Thu Dec 10 15:15:40 2009 +0000 @@ -7,6 +7,14 @@ #include <cstdlib> #include <iostream> +#include <QHash> // to ensure correct qHash(const QString &) is found + +unsigned int +qHash(const QUrl &u) +{ + return qHash(u.toString()); +} + namespace ClassicalData { QMap<QString, Form *> Form::m_map;
--- a/common/Objects.h Tue Dec 08 17:56:37 2009 +0000 +++ b/common/Objects.h Thu Dec 10 15:15:40 2009 +0000 @@ -14,6 +14,8 @@ #include <QMutexLocker> #include <QMap> +extern unsigned int qHash(const QUrl &u); + namespace ClassicalData { class HistoricalEvent : public QObject @@ -266,7 +268,8 @@ Q_OBJECT Q_PROPERTY(QString gender READ gender WRITE setGender STORED true) - Q_PROPERTY(QString nationality READ nationality WRITE setNationality STORED true) + Q_PROPERTY(QSet<QString> nationality READ nationality WRITE setNationality STORED true) + Q_PROPERTY(QSet<QUrl> geonameURIs READ geonameURIs WRITE setGeonameURIs STORED true) Q_PROPERTY(QString period READ period WRITE setPeriod STORED true) Q_PROPERTY(ClassicalData::Birth *birth READ birth WRITE setBirth STORED true) Q_PROPERTY(ClassicalData::Death *death READ death WRITE setDeath STORED true) @@ -277,8 +280,13 @@ QString gender() const { return m_gender; } void setGender(QString n) { m_gender = n; } - QString nationality() const { return m_nationality; } - void setNationality(QString n) { m_nationality = n; } + QSet<QString> nationality() const { return m_nationality; } + void setNationality(QSet<QString> n) { m_nationality = n; } + void addNationality(QString n) { m_nationality.insert(n); } + + QSet<QUrl> geonameURIs() const { return m_geonameURIs; } + void setGeonameURIs(QSet<QUrl> n) { m_geonameURIs = n; } + void addGeonameURI(QUrl n) { m_geonameURIs.insert(n); } QString period() const { return m_period; } void setPeriod(QString n) { m_period = n; } @@ -297,7 +305,8 @@ private: QString m_gender; - QString m_nationality; + QSet<QString> m_nationality; + QSet<QUrl> m_geonameURIs; QString m_period; Birth *m_birth; Death *m_death; @@ -341,6 +350,7 @@ Q_DECLARE_METATYPE(ClassicalData::Movement*); Q_DECLARE_METATYPE(ClassicalData::Document*); Q_DECLARE_METATYPE(QSet<QString>); +Q_DECLARE_METATYPE(QSet<QUrl>); Q_DECLARE_METATYPE(QSet<ClassicalData::Work*>); Q_DECLARE_METATYPE(QSet<ClassicalData::Movement*>); Q_DECLARE_METATYPE(QSet<ClassicalData::Document*>);
--- a/import/Import.cpp Tue Dec 08 17:56:37 2009 +0000 +++ b/import/Import.cpp Thu Dec 10 15:15:40 2009 +0000 @@ -10,6 +10,7 @@ #include "ImportClassicalComposersOrg.h" #include "ImportClassicalDotNet.h" +#include "ImportClassicalArchives.h" #include "ImportWikipediaComposers.h" #include "ImportWikipediaWorks.h" #include "ImportWikipediaWorksK.h" @@ -340,7 +341,15 @@ } if (c->gender() != "") other->setGender(c->gender()); - if (c->nationality() != "") other->setNationality(c->nationality()); + + foreach (QString s, c->nationality()) { + other->addNationality(s); + } + + foreach (QUrl s, c->geonameURIs()) { + other->addGeonameURI(s); + } + if (c->remarks() != "") other->setRemarks(c->remarks()); if (c->period() != "") other->setPeriod(c->period()); @@ -510,11 +519,15 @@ ("QSet<ClassicalData::Form*>"); qRegisterMetaType<QSet<QString> > ("QSet<QString>"); + qRegisterMetaType<QSet<QUrl> > + ("QSet<QUrl>"); qRegisterMetaType<ClassicalComposersOrgImporter *> ("ClassicalData::ClassicalComposersOrgImporter*"); qRegisterMetaType<ClassicalDotNetImporter *> ("ClassicalData::ClassicalDotNetImporter*"); + qRegisterMetaType<ClassicalArchivesImporter *> + ("ClassicalData::ClassicalArchivesImporter*"); qRegisterMetaType<WikipediaComposersImporter *> ("ClassicalData::WikipediaComposersImporter*"); qRegisterMetaType<WikipediaWorksImporter *> @@ -550,6 +563,8 @@ ObjectBuilder::getInstance()->registerClass <ClassicalDotNetImporter>("ClassicalData::ClassicalDotNetImporter*"); ObjectBuilder::getInstance()->registerClass + <ClassicalArchivesImporter>("ClassicalData::ClassicalArchivesImporter*"); + ObjectBuilder::getInstance()->registerClass <WikipediaComposersImporter>("ClassicalData::WikipediaComposersImporter*"); ObjectBuilder::getInstance()->registerClass <WikipediaWorksImporter>("ClassicalData::WikipediaWorksImporter*"); @@ -565,6 +580,10 @@ ("QString", "QSet<QString>", ContainerBuilder::SetKind); ContainerBuilder::getInstance()->registerContainer + <QUrl, QSet<QUrl> > + ("QUrl", "QSet<QUrl>", ContainerBuilder::SetKind); + + ContainerBuilder::getInstance()->registerContainer <Work*, QSet<Work*> > ("ClassicalData::Work*", "QSet<ClassicalData::Work*>", ContainerBuilder::SetKind); @@ -622,9 +641,12 @@ outmapper.addPropertyMapping("ClassicalData::Composer", "aliases", "dbv:alias"); outmapper.addPropertyMapping("ClassicalData::Composer", "birth", "property:birth"); outmapper.addPropertyMapping("ClassicalData::Composer", "death", "property:death"); + outmapper.addPropertyMapping("ClassicalData::Composer", "geonameURIs", "foaf:based_near"); outmapper.addTypeMapping("ClassicalData::Birth", "bio:Birth"); outmapper.addTypeMapping("ClassicalData::Death", "bio:Death"); + outmapper.addTypeUriPrefixMapping("ClassicalData::Birth", ":event/"); + outmapper.addTypeUriPrefixMapping("ClassicalData::Death", ":event/"); outmapper.addPropertyMapping("ClassicalData::Birth", "year", "bio:date"); outmapper.addPropertyMapping("ClassicalData::Death", "year", "bio:date"); outmapper.addPropertyMapping("ClassicalData::Birth", "place", "bio:place"); @@ -648,6 +670,7 @@ outmapper.addPropertyMapping("ClassicalData::Work", "name", "dc:title"); outmapper.addTypeMapping("ClassicalData::Composition", "mo:Composition"); + outmapper.addTypeUriPrefixMapping("ClassicalData::Composition", ":event/"); outmapper.addPropertyMapping("ClassicalData::Composition", "composer", "mo:composer"); outmapper.addPropertyMapping("ClassicalData::Composition", "works", "mo:produced_work");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/import/ImportClassicalArchives.cpp Thu Dec 10 15:15:40 2009 +0000 @@ -0,0 +1,316 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "ImportClassicalArchives.h" + +#include <dataquay/Debug.h> + +#include <QFile> +#include <QFileInfo> +#include <QTextStream> +#include <QRegExp> +#include <QVariant> + +#include <exception> + +using namespace Dataquay; + +namespace ClassicalData { + +void +ClassicalArchivesImporter::setSource(QUrl source) +{ + DEBUG << "ClassicalArchivesImporter::setSource: " << source << endl; + import(source); +} + +static const char *locmap[] = { + "ARG", "Argentinian", "Argentina", "3865483", + "ARM", "Armenian", "Armenia", "174982", + "AUS", "Australian", "Australia", "2077456", + "AUT", "Austrian", "Austria", "2782113", + "AZE", "Azeri", "Azerbaijan", "587116", + "BEL", "Belgian", "Belgium", "2802361", + "BGR", "Bulgarian", "Bulgaria", "732800", + "BLR", "Belarusian", "Belarus", "630336", + "BOH", "Bohemian", "Bohemia", "3074194", + "BRA", "Brazilian", "Brazil", "3469058", + "BSQ", "Basque", "Basque country", "3104499", + "CAN", "Canadian", "Canada", "6251999", + "CHE", "Swiss", "Switzerland", "2658434", + "CHL", "Chilean", "Chile", "3895114", + "CHN", "Chinese", "China", "1814991", + "CRI", "Costa Rican", "Costa Rica", "3624060", + "CTN", "Catalonian", "Catalonia", "3108286", + "CUB", "Cuban", "Cuba", "3562981", + "CZE", "Czech", "Czech Republic", "3077311", + "DEU", "German", "Germany", "2921044", + "DNK", "Danish", "Denmark", "2623032", + "ECU", "Ecuadorian", "Ecuador", "3658394", + "EGY", "Egyptian", "Egypt", "357994", + "ENG", "English", "England", "2635167", + "EPR", "German", "Germany", "2921044", // pardon? + "ESP", "Spanish", "Spain", "2510769", + "EST", "Estonian", "Estonia", "453733", + "ETH", "Ethiopian", "Ethiopia", "337996", + "FIN", "Finnish", "Finland", "660013", + "FLM", "Flemish", "Flanders", "3337388", + "FRA", "French", "France", "3017382", + "GBR", "British", "Britain", "4839292", + "GEO", "Georgian", "Georgia", "614540", + "GRC", "Greek", "Greece", "390903", + "GTM", "Guatemalan", "Guatemala", "3595528", + "HKG", "Hong Kong Chinese", "Hong Kong", "1819729", + "HOL", "Dutch", "Holland", "2750405", + "HRV", "Croatian", "Croatia", "3202326", + "HUN", "Hungarian", "Hungary", "719819", + "IND", "Indian", "India", "1269750", + "IRL", "Irish", "Ireland", "2963597", + "IRN", "Iranian", "Iran", "130758", + "ISL", "Icelandic", "Iceland", "2629691", + "ISR", "Israeli", "Israel", "294640", + "ITA", "Italian", "Italy", "3175395", + "JPN", "Japanese", "Japan", "1861060", + "KAZ", "Kazakh", "Kazakhstan", "1522867", + "KOR", "Korean", "Korea", "1835841", + "LBN", "Lebanese", "Lebanon", "272103", + "LTU", "Lithuanian", "Lithuania", "597427", + "LVA", "Latvian", "Latvia", "458258", + "MAR", "Moroccan", "Morocco", "2542007", + "MEX", "Mexican", "Mexico", "3996063", + "MKD", "Macedonian", "Macedonia", "718075", + "MOR", "Moravian", "Moravia", "3078610", + "MYS", "Malaysian", "Malaysia", "1733045", + "NAI", "North American Indian", "United States of America", "6252001", + "NLD", "Dutch", "Netherlands", "2750405", + "NOR", "Norwegian", "Norway", "3144096", + "NZL", "New Zealander", "New Zealand", "2186224", + "PER", "Peruvian", "Peru", "3932488", + "PHL", "Filipino", "Philippines", "1694008", + "POL", "Polish", "Poland", "798544", + "PRT", "Portuguese", "Portugal", "2264397", + "PRU", "Prussian", "Prussia", "772636", + "PRY", "Paraguayan", "Paraguay", "3437598", + "ROU", "Romanian", "Romania", "798549", + "RUS", "Russian", "Russia", "2017370", + "SCG", "Serbian-Montenegran", "Serbia-Montenegro", "3202468", + "SCO", "Scottish", "Scotland", "2638360", + "SGP", "Singaporean", "Singapore", "1880251", + "SVK", "Slovakian", "Slovakia", "3057568", + "SVN", "Slovenian", "Slovenia", "3190538", + "SWE", "Swedish", "Sweden", "2661886", + "TKM", "Turkmen", "Turkmenistan", "1218197", + "TSL", "Transylvanian", "Transylvania", "4495544", + "TSM", "Tasmanian", "Tasmania", "2147291", + "TUR", "Turkish", "Turkey", "298795", + "UKR", "Ukrainian", "Ukraine", "690791", + "URY", "Uruguayan", "Uruguay", "3439705", + "USA", "American", "United States of America", "6252001", + "VEN", "Venezuelan", "Venezuela", "3625428", + "VNM", "Vietnamese", "Vietnam", "1562822", + "WLS", "Samoan", "Samoa", "4034894", + "ZAF", "South African", "South Africa", "953987", +}; + +QSet<QString> +locationToNationality(QString location) +{ + QSet<QString> nationalities; + QStringList locations = location.split('/'); + foreach (location, locations) { + int cols = 4; + for (size_t i = 0; i < (sizeof(locmap)/sizeof(locmap[0])) / cols; ++i) { + if (location == locmap[i*cols]) { + nationalities.insert(locmap[i*cols+1]); + } + } + } + return nationalities; +} + +QSet<QUrl> +locationToGeonameURIs(QString location) +{ + QSet<QUrl> uris; + QStringList locations = location.split('/'); + foreach (location, locations) { + int cols = 4; + for (size_t i = 0; i < (sizeof(locmap)/sizeof(locmap[0])) / cols; ++i) { + if (location == locmap[i*cols]) { + uris.insert(QUrl(QString("http://sws.geonames.org/") + + locmap[i*cols+3] + "/")); + } + } + } + return uris; +} + +void +parseNames(QString field, QStringList &names, int &birth, int &death, + bool &approx, QString &location) +{ + field.replace(QRegExp("<[^>]*>"), ""); + + QRegExp locre("; (.*)$"); + int pos; + if ((pos = locre.indexIn(field)) >= 0) { + location = locre.cap(1); + field.replace(pos, locre.matchedLength(), ""); + } + + QRegExp datere("\\(([^\\)]+)\\) *$"); + if ((pos = datere.indexIn(field)) >= 0) { + QString contents = datere.cap(1); + if (contents.startsWith("c.")) { + approx = true; + contents = contents.replace("c.", ""); + contents = contents.trimmed(); + } + if (QRegExp("\\d{4}").indexIn(contents) >= 0) { + QStringList bits = contents.split("-"); + if (!bits.empty()) { + QString f1 = bits[0]; + QString f2; + if (bits.size() > 1) f2 = bits[1]; + if (f1.startsWith("b")) { + f1.replace(QRegExp("b[^0-9]*"), ""); + birth = f1.toInt(); + } else if (f1.startsWith("d")) { + f1.replace(QRegExp("d[^0-9]*"), ""); + death = f1.toInt(); + } else if (f2 != "") { + birth = f1.toInt(); + } + if (f2 != "") { + death = f2.toInt(); + } + } + } + field.replace(pos, datere.matchedLength(), ""); + } + + // we don't properly handle their slash alternatives syntax + field = field.replace(QRegExp("/[^/,]*"), ""); + + // nor these + field.replace(QRegExp("\\[[^\\]]*\\]"), ""); + + // nor these + field.replace(QRegExp("\\([^\\)]*\\)"), ""); + + field.replace(QRegExp(" +"), " "); + + // and let's be picky -- we don't like names with just initials, + // can't properly match them + if (QRegExp(",.*\\.").indexIn(field) >= 0) { + return; + } + + // and, from this particular source, I'm suspicious of single-word + // names (sorry) + if (!field.contains(",")) return; + + field = field.trimmed(); + names.push_back(field); + + // comma + QRegExp commare = QRegExp("^([^,]+), *([^,]+)$"); + if ((pos = commare.indexIn(field)) >= 0) { + QString c(commare.cap(1)); + QString d(commare.cap(2)); + names.push_back(QString(d + " " + c).trimmed()); + } +} + +void +ClassicalArchivesImporter::import(QUrl source) +{ + //!!! for now + QString filename = source.toLocalFile(); + + QFile file(filename); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + throw std::exception(); + } + + QTextStream stream(&file); + stream.setCodec("UTF-8"); + QString all = stream.readAll(); + + QRegExp matcher + ("<a href=\"(/composer/[^\"]+)\"><div[^>]*>([^\n]+)</div></a>"); + + DEBUG << "ClassicalArchivesImporter: Have " << all.length() << " chars" << endl; + + int pos = 0, count = 0; + while ((pos = matcher.indexIn(all, pos)) != -1) { + pos += matcher.matchedLength(); + ++count; + + QString namefield = matcher.cap(2); + QStringList names; + + int birth = 0, death = 0; + bool approx = false; + QString location; + + parseNames(namefield, names, birth, death, approx, location); + + if (names.empty()) { + DEBUG << "No name!" << endl; + continue; + } + + DEBUG << "Item " << count + << ": page = " << matcher.cap(1) + << ", name = " << names[0] + << ", birth = " << birth << ", death = " << death + << ", loc " << location << endl; + + if (names[0].contains("Anonymous") || + names[0].contains("Traditional")) { + continue; + } + + Composer *composer = new Composer(); + composer->setName(names[0]); + for (int i = 1; i < names.size(); ++i) { + composer->addAlias(names[i]); + } + + if (birth != 0) { + Birth *e = new Birth(birth); + if (approx) e->setApproximate(true); + composer->setBirth(e); + } + + if (death != 0) { + Death *e = new Death(death); + if (approx) e->setApproximate(true); + composer->setDeath(e); + } + + if (location != "") { + composer->setNationality(locationToNationality(location)); + composer->setGeonameURIs(locationToGeonameURIs(location)); + } + + if (matcher.cap(1) != "") { + QString url = matcher.cap(1); + Document *d = new Document; + d->setUri(QUrl("http://www.classicalarchives.com" + url)); + d->setTopic(composer); + d->setSiteName("Classical Archives"); + composer->addPage(d); + } + + m_objects.push_back(composer); + } + + + DEBUG << "Found " << count << " things" << endl; +} + + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/import/ImportClassicalArchives.h Thu Dec 10 15:15:40 2009 +0000 @@ -0,0 +1,29 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#ifndef _IMPORT_CLASSICAL_ARCHIVES_H_ +#define _IMPORT_CLASSICAL_ARCHIVES_H_ + +#include "Importer.h" + +namespace ClassicalData { + +class ClassicalArchivesImporter : public Importer +{ + Q_OBJECT + +public: + virtual void setSource(QUrl source); + + virtual QObjectList getImportedObjects() { return m_objects; } + +protected: + void import(QUrl source); + + QObjectList m_objects; +}; + +} + +Q_DECLARE_METATYPE(ClassicalData::ClassicalArchivesImporter*); + +#endif
--- a/import/ImportClassicalComposersOrg.cpp Tue Dec 08 17:56:37 2009 +0000 +++ b/import/ImportClassicalComposersOrg.cpp Thu Dec 10 15:15:40 2009 +0000 @@ -238,6 +238,9 @@ // fall through to add } + field.replace("(", ""); + field.replace(")", ""); + names[field] = score; } @@ -288,6 +291,10 @@ QString namefield = name.trimmed(); NameMap names; + if (namefield.contains("P.D.Q.")) { // lose this joke + continue; + } + parseNames(namefield, names); i = 0;
--- a/import/ImportWikipediaComposers.cpp Tue Dec 08 17:56:37 2009 +0000 +++ b/import/ImportWikipediaComposers.cpp Thu Dec 10 15:15:40 2009 +0000 @@ -115,7 +115,7 @@ composer->setDeath(e); } if (nationalityfield != "") { - composer->setNationality(nationalityfield); + composer->addNationality(nationalityfield); } if (summaryfield != "") { summaryfield.replace(QRegExp("^[Cc]omposer, *"), "");
--- a/import/import.pro Tue Dec 08 17:56:37 2009 +0000 +++ b/import/import.pro Thu Dec 10 15:15:40 2009 +0000 @@ -12,8 +12,8 @@ LIBS += ../common/libcommon.a ../../turbot/dataquay/libdataquay.a ../../turbot/ext/libext.a # Input -HEADERS += Importer.h ImportClassicalComposersOrg.h ImportClassicalDotNet.h ImportHoboken.h ImportWikipediaComposers.h ImportWikipediaWorks.h ImportWikipediaWorksK.h ImportWikipediaWorksList.h -SOURCES += Import.cpp ImportClassicalComposersOrg.cpp ImportClassicalDotNet.cpp ImportHoboken.cpp ImportWikipediaComposers.cpp ImportWikipediaWorks.cpp ImportWikipediaWorksK.cpp ImportWikipediaWorksList.cpp +HEADERS += Importer.h ImportClassicalArchives.h ImportClassicalComposersOrg.h ImportClassicalDotNet.h ImportHoboken.h ImportWikipediaComposers.h ImportWikipediaWorks.h ImportWikipediaWorksK.h ImportWikipediaWorksList.h +SOURCES += Import.cpp ImportClassicalArchives.cpp ImportClassicalComposersOrg.cpp ImportClassicalDotNet.cpp ImportHoboken.cpp ImportWikipediaComposers.cpp ImportWikipediaWorks.cpp ImportWikipediaWorksK.cpp ImportWikipediaWorksList.cpp solaris* {
--- a/import/importers.ttl Tue Dec 08 17:56:37 2009 +0000 +++ b/import/importers.ttl Thu Dec 10 15:15:40 2009 +0000 @@ -108,6 +108,85 @@ property:source <file:../source-data/classical-composers.org/firstZ> . +:caiA a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/a.html> . + +:caiB a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/b.html> . + +:caiC a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/c.html> . + +:caiD a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/d.html> . + +:caiE a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/e.html> . + +:caiF a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/f.html> . + +:caiG a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/g.html> . + +:caiH a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/h.html> . + +:caiI a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/i.html> . + +:caiJ a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/j.html> . + +:caiK a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/k.html> . + +:caiL a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/l.html> . + +:caiM a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/m.html> . + +:caiN a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/n.html> . + +:caiO a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/o.html> . + +:caiP a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/p.html> . + +:caiQ a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/q.html> . + +:caiR a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/r.html> . + +:caiS a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/s.html> . + +:caiT a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/t.html> . + +:caiU a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/u.html> . + +:caiV a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/v.html> . + +:caiW a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/w.html> . + +:caiX a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/x.html> . + +:caiY a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/y.html> . + +:caiZ a classical:ClassicalArchivesImporter ; + property:source <file:../source-data/classicalarchives.com/z.html> . + + # These ones need more work: #:wki_216 a classical:WikipediaWorksListImporter ; # property:source <file:../source-data/en.wikipedia.org/works/List_of_compositions_by_Antonio_Vivaldi> .