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 | |
20 | namespace Syndication |
21 | { |
22 | namespace RDF |
23 | { |
24 | Model 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 | |
46 | ResourcePtr 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 | |