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> .