1/*
2 This file is part of the syndication library
3 SPDX-FileCopyrightText: 2006 Frank Osterfeld <osterfeld@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "modelmaker.h"
9#include "literal.h"
10#include "model.h"
11#include "property.h"
12#include "rdfvocab.h"
13#include "resource.h"
14#include "sequence.h"
15#include "statement.h"
16
17#include <QDomElement>
18#include <QString>
19
20namespace Syndication
21{
22namespace RDF
23{
24Model ModelMaker::createFromXML(const QDomDocument &doc)
25{
26 Model model;
27
28 if (doc.isNull()) {
29 return model;
30 }
31
32 const QDomElement rdfNode = doc.documentElement();
33
34 const QDomNodeList list = rdfNode.childNodes();
35
36 for (int i = 0; i < list.length(); ++i) {
37 if (list.item(index: i).isElement()) {
38 const QDomElement el = list.item(index: i).toElement();
39 readResource(model, el);
40 }
41 }
42
43 return model;
44}
45
46ResourcePtr ModelMaker::readResource(Model &model, const QDomElement &el)
47{
48 QString about = QStringLiteral("about");
49 QString resource = QStringLiteral("resource");
50
51 ResourcePtr res;
52
53 ResourcePtr type = model.createResource(uri: el.namespaceURI() + el.localName());
54
55 if (*type == *(RDFVocab::self()->seq())) {
56 SequencePtr seq = model.createSequence(uri: el.attribute(name: about));
57
58 res = seq;
59 } else {
60 res = model.createResource(uri: el.attribute(name: about));
61 }
62
63 model.addStatement(subject: res, predicate: RDFVocab::self()->type(), object: type);
64
65 const QDomNodeList children = el.childNodes();
66
67 bool isSeq = res->isSequence();
68
69 for (int i = 0; i < children.length(); ++i) {
70 if (children.item(index: i).isElement()) {
71 QDomElement ce = children.item(index: i).toElement();
72
73 PropertyPtr pred = model.createProperty(uri: ce.namespaceURI() + ce.localName());
74
75 if (ce.hasAttribute(name: resource)) { // referenced Resource via (rdf:)resource
76 NodePtr obj = model.createResource(uri: ce.attribute(name: resource));
77
78 if (isSeq && *pred == *(RDFVocab::self()->li())) {
79 SequencePtr tseq = res.staticCast<Sequence>();
80 tseq->append(node: obj);
81 } else {
82 model.addStatement(subject: res, predicate: pred, object: obj);
83 }
84 } else if (!ce.text().isEmpty() && ce.lastChildElement().isNull()) { // Literal
85 NodePtr obj = model.createLiteral(text: ce.text());
86
87 if (isSeq && *pred == *(RDFVocab::self()->li())) {
88 SequencePtr tseq = res.staticCast<Sequence>();
89 tseq->append(node: obj);
90 } else {
91 model.addStatement(subject: res, predicate: pred, object: obj);
92 }
93 } else { // embedded description
94 QDomElement re = ce.lastChildElement();
95
96 // QString uri = re.attribute(about);
97
98 // read recursively
99 NodePtr obj = readResource(model, el: re);
100
101 if (isSeq && *pred == *(RDFVocab::self()->li())) {
102 SequencePtr tseq = res.staticCast<Sequence>();
103 tseq->append(node: obj);
104 } else {
105 model.addStatement(subject: res, predicate: pred, object: obj);
106 }
107 }
108
109 // TODO: bag, reification (nice to have, but not important for basic RSS 1.0)
110 }
111 }
112
113 return res;
114}
115
116} // namespace RDF
117} // namespace Syndication
118

source code of syndication/src/rdf/modelmaker.cpp