File indexing completed on 2024-04-28 07:50:17

0001 /*
0002     This file is part of the syndication library
0003     SPDX-FileCopyrightText: 2006 Frank Osterfeld <osterfeld@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "modelmaker.h"
0009 #include "literal.h"
0010 #include "model.h"
0011 #include "property.h"
0012 #include "rdfvocab.h"
0013 #include "resource.h"
0014 #include "sequence.h"
0015 #include "statement.h"
0016 
0017 #include <QDomElement>
0018 #include <QString>
0019 
0020 namespace Syndication
0021 {
0022 namespace RDF
0023 {
0024 Model ModelMaker::createFromXML(const QDomDocument &doc)
0025 {
0026     Model model;
0027 
0028     if (doc.isNull()) {
0029         return model;
0030     }
0031 
0032     const QDomElement rdfNode = doc.documentElement();
0033 
0034     const QDomNodeList list = rdfNode.childNodes();
0035 
0036     for (int i = 0; i < list.length(); ++i) {
0037         if (list.item(i).isElement()) {
0038             const QDomElement el = list.item(i).toElement();
0039             readResource(model, el);
0040         }
0041     }
0042 
0043     return model;
0044 }
0045 
0046 ResourcePtr ModelMaker::readResource(Model &model, const QDomElement &el)
0047 {
0048     QString about = QStringLiteral("about");
0049     QString resource = QStringLiteral("resource");
0050 
0051     ResourcePtr res;
0052 
0053     ResourcePtr type = model.createResource(el.namespaceURI() + el.localName());
0054 
0055     if (*type == *(RDFVocab::self()->seq())) {
0056         SequencePtr seq = model.createSequence(el.attribute(about));
0057 
0058         res = seq;
0059     } else {
0060         res = model.createResource(el.attribute(about));
0061     }
0062 
0063     model.addStatement(res, RDFVocab::self()->type(), type);
0064 
0065     const QDomNodeList children = el.childNodes();
0066 
0067     bool isSeq = res->isSequence();
0068 
0069     for (int i = 0; i < children.length(); ++i) {
0070         if (children.item(i).isElement()) {
0071             QDomElement ce = children.item(i).toElement();
0072 
0073             PropertyPtr pred = model.createProperty(ce.namespaceURI() + ce.localName());
0074 
0075             if (ce.hasAttribute(resource)) { // referenced Resource via (rdf:)resource
0076                 NodePtr obj = model.createResource(ce.attribute(resource));
0077 
0078                 if (isSeq && *pred == *(RDFVocab::self()->li())) {
0079                     SequencePtr tseq = res.staticCast<Sequence>();
0080                     tseq->append(obj);
0081                 } else {
0082                     model.addStatement(res, pred, obj);
0083                 }
0084             } else if (!ce.text().isEmpty() && ce.lastChildElement().isNull()) { // Literal
0085                 NodePtr obj = model.createLiteral(ce.text());
0086 
0087                 if (isSeq && *pred == *(RDFVocab::self()->li())) {
0088                     SequencePtr tseq = res.staticCast<Sequence>();
0089                     tseq->append(obj);
0090                 } else {
0091                     model.addStatement(res, pred, obj);
0092                 }
0093             } else { // embedded description
0094                 QDomElement re = ce.lastChildElement();
0095 
0096                 // QString uri = re.attribute(about);
0097 
0098                 // read recursively
0099                 NodePtr obj = readResource(model, re);
0100 
0101                 if (isSeq && *pred == *(RDFVocab::self()->li())) {
0102                     SequencePtr tseq = res.staticCast<Sequence>();
0103                     tseq->append(obj);
0104                 } else {
0105                     model.addStatement(res, pred, obj);
0106                 }
0107             }
0108 
0109             // TODO: bag, reification (nice to have, but not important for basic RSS 1.0)
0110         }
0111     }
0112 
0113     return res;
0114 }
0115 
0116 } // namespace RDF
0117 } // namespace Syndication