File indexing completed on 2024-05-12 05:10:08
0001 /************************************************************************* 0002 Copyright (C) 2003-2009 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include <config.h> 0026 0027 #include "bibtexmlexporter.h" 0028 #include "../utils/bibtexhandler.h" 0029 #include "../fieldformat.h" 0030 #include "../core/filehandler.h" 0031 #include "tellico_xml.h" 0032 #include "../utils/stringset.h" 0033 #include "../tellico_debug.h" 0034 0035 #include <KLocalizedString> 0036 0037 #include <QDomDocument> 0038 #include <QTextCodec> 0039 0040 using namespace Tellico; 0041 using Tellico::Export::BibtexmlExporter; 0042 0043 BibtexmlExporter::BibtexmlExporter(Data::CollPtr coll_) : Exporter(coll_) { 0044 } 0045 0046 QString BibtexmlExporter::formatString() const { 0047 return QStringLiteral("Bibtexml"); 0048 } 0049 0050 QString BibtexmlExporter::fileFilter() const { 0051 return i18n("Bibtexml Files") + QLatin1String(" (*.xml)") + QLatin1String(";;") + i18n("All Files") + QLatin1String(" (*)"); 0052 } 0053 0054 bool BibtexmlExporter::exec() { 0055 const QString text = this->text(); 0056 return text.isEmpty() ? false : FileHandler::writeTextURL(url(), text, options() & ExportUTF8, options() & Export::ExportForce); 0057 } 0058 0059 QString BibtexmlExporter::text() { 0060 Data::CollPtr c = collection(); 0061 if(!c || c->type() != Data::Collection::Bibtex) { 0062 return QString(); 0063 } 0064 0065 // there are some special fields 0066 // the entry-type specifies the entry type - book, inproceedings, whatever 0067 QString typeField; 0068 // the key specifies the cite-key 0069 QString keyField; 0070 0071 const QString bibtex = QStringLiteral("bibtex"); 0072 // keep a list of all the 'ordinary' fields to iterate through later 0073 Data::FieldList fields; 0074 foreach(Data::FieldPtr it, this->fields()) { 0075 QString bibtexField = it->property(bibtex); 0076 if(bibtexField == QLatin1String("entry-type")) { 0077 typeField = it->name(); 0078 } else if(bibtexField == QLatin1String("key")) { 0079 keyField = it->name(); 0080 } else if(!bibtexField.isEmpty()) { 0081 fields.append(it); 0082 } 0083 } 0084 0085 QDomImplementation impl; 0086 QDomDocumentType doctype = impl.createDocumentType(QStringLiteral("file"), 0087 QString(), 0088 XML::dtdBibtexml); 0089 //default namespace 0090 const QString& ns = XML::nsBibtexml; 0091 0092 QDomDocument dom = impl.createDocument(ns, QStringLiteral("file"), doctype); 0093 0094 // root element 0095 QDomElement root = dom.documentElement(); 0096 0097 QString encodeStr = QStringLiteral("version=\"1.0\" encoding=\""); 0098 if(options() & Export::ExportUTF8) { 0099 encodeStr += QLatin1String("UTF-8"); 0100 } else { 0101 encodeStr += QLatin1String(QTextCodec::codecForLocale()->name()); 0102 } 0103 encodeStr += QLatin1Char('"'); 0104 0105 // createDocument creates a root node, insert the processing instruction before it 0106 dom.insertBefore(dom.createProcessingInstruction(QStringLiteral("xml"), encodeStr), root); 0107 QString comment = QLatin1String("Generated by Tellico ") + QLatin1String(TELLICO_VERSION); 0108 dom.insertBefore(dom.createComment(comment), root); 0109 0110 FieldFormat::Request format = (options() & Export::ExportFormatted ? 0111 FieldFormat::ForceFormat : 0112 FieldFormat::AsIsFormat); 0113 0114 StringSet usedKeys; 0115 QString type, key, newKey, value, elemName, parElemName; 0116 QDomElement btElem, entryElem, parentElem, fieldElem; 0117 foreach(Data::EntryPtr entryIt, entries()) { 0118 key = entryIt->field(keyField); 0119 if(key.isEmpty()) { 0120 key = BibtexHandler::bibtexKey(entryIt); 0121 } 0122 newKey = key; 0123 char c = 'a'; 0124 while(usedKeys.has(newKey)) { 0125 // duplicate found! 0126 newKey = key + QLatin1Char(c); 0127 ++c; 0128 } 0129 key = newKey; 0130 usedKeys.add(key); 0131 0132 btElem = dom.createElement(QStringLiteral("entry")); 0133 btElem.setAttribute(QStringLiteral("id"), key); 0134 root.appendChild(btElem); 0135 0136 type = entryIt->field(typeField); 0137 if(type.isEmpty()) { 0138 myWarning() << "the entry for '" << entryIt->title() 0139 << "' has no entry-type, skipping it!"; 0140 continue; 0141 } 0142 0143 entryElem = dom.createElement(type); 0144 btElem.appendChild(entryElem); 0145 0146 // now iterate over attributes 0147 foreach(Data::FieldPtr field, fields) { 0148 value = entryIt->formattedField(field, format); 0149 if(value.isEmpty()) { 0150 continue; 0151 } 0152 0153 /* Bibtexml has special container elements for titles, authors, editors, and keywords 0154 I'm going to ignore the titlelist element for right now. All authors are contained in 0155 an authorlist element, editors in an editorlist element, and keywords are in a 0156 keywords element, and themselves as a keyword. Also, Bibtexml can format names 0157 similar to docbook, with first, middle, last, etc elements. I'm going to ignore that 0158 for now, too.*/ 0159 elemName = field->property(bibtex); 0160 // split text for author, editor, and keywords 0161 if(elemName == QLatin1String("author") || 0162 elemName == QLatin1String("editor") || 0163 elemName == QLatin1String("keywords")) { 0164 if(elemName == QLatin1String("author")) { 0165 parElemName = QStringLiteral("authorlist"); 0166 } else if(elemName == QLatin1String("editor")) { 0167 parElemName = QStringLiteral("editorlist"); 0168 } else { // keywords 0169 parElemName = QStringLiteral("keywords"); 0170 elemName = QStringLiteral("keyword"); 0171 } 0172 0173 parentElem = dom.createElement(parElemName); 0174 const QStringList values = FieldFormat::splitValue(entryIt->formattedField(field, format)); 0175 foreach(const QString& value, values) { 0176 fieldElem = dom.createElement(elemName); 0177 fieldElem.appendChild(dom.createTextNode(value)); 0178 parentElem.appendChild(fieldElem); 0179 } 0180 if(parentElem.hasChildNodes()) { 0181 entryElem.appendChild(parentElem); 0182 } 0183 } else { 0184 fieldElem = dom.createElement(elemName); 0185 fieldElem.appendChild(dom.createTextNode(value)); 0186 entryElem.appendChild(fieldElem); 0187 } 0188 } 0189 } 0190 0191 return dom.toString(); 0192 }