File indexing completed on 2024-05-05 09:06:15
0001 /* 0002 SPDX-FileCopyrightText: 2017 Nicolas Carion 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #include "xml.hpp" 0007 #include <QDebug> 0008 #include <QFile> 0009 #include <QSaveFile> 0010 0011 // static 0012 bool Xml::docContentFromFile(QDomDocument &doc, const QString &fileName, bool namespaceProcessing) 0013 { 0014 QFile file(fileName); 0015 if (!file.open(QIODevice::ReadOnly)) { 0016 qWarning() << "Failed to open file" << file.fileName() << "for reading"; 0017 return false; 0018 } 0019 if (!doc.setContent(&file, namespaceProcessing)) { 0020 qWarning() << "Failed to parse file" << file.fileName() << "to QDomDocument"; 0021 file.close(); 0022 return false; 0023 } 0024 file.close(); 0025 return true; 0026 } 0027 0028 bool Xml::docContentToFile(const QDomDocument &doc, const QString &fileName) 0029 { 0030 QSaveFile file(fileName); 0031 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { 0032 qWarning() << "Cannot write to file" << file.fileName(); 0033 return false; 0034 } 0035 file.write(doc.toString().toUtf8()); 0036 if (!file.commit()) { 0037 qWarning() << "Error while writing to file" << file.fileName(); 0038 return false; 0039 } 0040 return true; 0041 } 0042 0043 QString Xml::getSubTagContent(const QDomElement &element, const QString &tagName) 0044 { 0045 QVector<QDomNode> nodeList = getDirectChildrenByTagName(element, tagName); 0046 if (!nodeList.isEmpty()) { 0047 if (nodeList.size() > 1) { 0048 QString str; 0049 QTextStream stream(&str); 0050 element.save(stream, 4); 0051 qDebug() << "Warning: " << str << "provides several " << tagName << ". We keep only first one."; 0052 } 0053 QString content = nodeList.at(0).toElement().text(); 0054 return content; 0055 } 0056 return QString(); 0057 } 0058 0059 QVector<QDomNode> Xml::getDirectChildrenByTagName(const QDomElement &element, const QString &tagName) 0060 { 0061 auto children = element.childNodes(); 0062 QVector<QDomNode> result; 0063 for (int i = 0; i < children.count(); ++i) { 0064 if (children.item(i).isNull() || !children.item(i).isElement()) { 0065 continue; 0066 } 0067 QDomElement child = children.item(i).toElement(); 0068 if (child.tagName() == tagName) { 0069 result.push_back(child); 0070 } 0071 } 0072 return result; 0073 } 0074 0075 QString Xml::getTagContentByAttribute(const QDomElement &element, const QString &tagName, const QString &attribute, const QString &value, 0076 const QString &defaultReturn, bool directChildren) 0077 { 0078 QDomNodeList nodes; 0079 if (directChildren) { 0080 nodes = element.childNodes(); 0081 } else { 0082 nodes = element.elementsByTagName(tagName); 0083 } 0084 for (int i = 0; i < nodes.count(); ++i) { 0085 auto current = nodes.item(i); 0086 if (current.isNull() || !current.isElement()) { 0087 continue; 0088 } 0089 auto elem = current.toElement(); 0090 if (elem.tagName() == tagName && elem.hasAttribute(attribute)) { 0091 if (elem.attribute(attribute) == value) { 0092 return elem.text(); 0093 } 0094 } 0095 } 0096 return defaultReturn; 0097 } 0098 0099 void Xml::addXmlProperties(QDomElement &element, const std::unordered_map<QString, QString> &properties) 0100 { 0101 for (const auto &p : properties) { 0102 QDomElement prop = element.ownerDocument().createElement(QStringLiteral("property")); 0103 prop.setAttribute(QStringLiteral("name"), p.first); 0104 QDomText value = element.ownerDocument().createTextNode(p.second); 0105 prop.appendChild(value); 0106 element.appendChild(prop); 0107 } 0108 } 0109 0110 void Xml::addXmlProperties(QDomElement &element, const QMap<QString, QString> &properties) 0111 { 0112 QMapIterator<QString, QString> i(properties); 0113 while (i.hasNext()) { 0114 i.next(); 0115 QDomElement prop = element.ownerDocument().createElement(QStringLiteral("property")); 0116 prop.setAttribute(QStringLiteral("name"), i.key()); 0117 QDomText value = element.ownerDocument().createTextNode(i.value()); 0118 prop.appendChild(value); 0119 element.appendChild(prop); 0120 } 0121 } 0122 0123 QString Xml::getXmlProperty(const QDomElement &element, const QString &propertyName, const QString &defaultReturn) 0124 { 0125 return Xml::getTagContentByAttribute(element, QStringLiteral("property"), QStringLiteral("name"), propertyName, defaultReturn, false); 0126 } 0127 0128 QString Xml::getXmlParameter(const QDomElement &element, const QString &propertyName, const QString &defaultReturn) 0129 { 0130 return Xml::getTagContentByAttribute(element, QStringLiteral("parameter"), QStringLiteral("name"), propertyName, defaultReturn, false); 0131 } 0132 0133 void Xml::setXmlProperty(QDomElement element, const QString &propertyName, const QString &value) 0134 { 0135 QDomNodeList params = element.elementsByTagName(QStringLiteral("property")); 0136 // Update property if it already exists 0137 bool found = false; 0138 for (int i = 0; i < params.count(); ++i) { 0139 QDomElement e = params.item(i).toElement(); 0140 if (e.attribute(QStringLiteral("name")) == propertyName) { 0141 if (e.hasChildNodes()) { 0142 e.firstChild().setNodeValue(value); 0143 } else { 0144 QDomText resourceValue = element.ownerDocument().createTextNode(value); 0145 e.appendChild(resourceValue); 0146 } 0147 found = true; 0148 break; 0149 } 0150 } 0151 if (!found) { 0152 // create property 0153 QMap<QString, QString> map; 0154 map.insert(propertyName, value); 0155 addXmlProperties(element, map); 0156 } 0157 } 0158 0159 void Xml::setXmlParameter(const QDomElement &element, const QString &propertyName, const QString &value) 0160 { 0161 QDomNodeList params = element.elementsByTagName(QStringLiteral("parameter")); 0162 // Update property if it already exists 0163 for (int i = 0; i < params.count(); ++i) { 0164 QDomElement e = params.item(i).toElement(); 0165 if (e.attribute(QStringLiteral("name")) == propertyName) { 0166 e.setAttribute(QStringLiteral("value"), value); 0167 break; 0168 } 0169 } 0170 } 0171 0172 bool Xml::hasXmlParameter(const QDomElement &element, const QString &propertyName) 0173 { 0174 QDomNodeList params = element.elementsByTagName(QStringLiteral("parameter")); 0175 for (int i = 0; i < params.count(); ++i) { 0176 QDomElement e = params.item(i).toElement(); 0177 if (e.attribute(QStringLiteral("name")) == propertyName) { 0178 return true; 0179 } 0180 } 0181 return false; 0182 } 0183 0184 bool Xml::hasXmlProperty(const QDomElement &element, const QString &propertyName) 0185 { 0186 QDomNodeList params = element.elementsByTagName(QStringLiteral("property")); 0187 for (int i = 0; i < params.count(); ++i) { 0188 QDomElement e = params.item(i).toElement(); 0189 if (e.attribute(QStringLiteral("name")) == propertyName) { 0190 return true; 0191 } 0192 } 0193 return false; 0194 } 0195 0196 QMap<QString, QString> Xml::getXmlPropertyByWildcard(const QDomElement &element, const QString &propertyName) 0197 { 0198 QMap<QString, QString> props; 0199 QDomNodeList params = element.elementsByTagName(QStringLiteral("property")); 0200 for (int i = 0; i < params.count(); ++i) { 0201 QDomElement e = params.item(i).toElement(); 0202 if (e.attribute(QStringLiteral("name")).startsWith(propertyName)) { 0203 props.insert(e.attribute(QStringLiteral("name")), e.text()); 0204 } 0205 } 0206 return props; 0207 } 0208 0209 void Xml::removeXmlProperty(QDomElement effect, const QString &name) 0210 { 0211 QDomNodeList params = effect.elementsByTagName(QStringLiteral("property")); 0212 for (int i = 0; i < params.count(); ++i) { 0213 QDomElement e = params.item(i).toElement(); 0214 if (e.attribute(QStringLiteral("name")) == name) { 0215 effect.removeChild(params.item(i)); 0216 break; 0217 } 0218 } 0219 } 0220 0221 void Xml::renameXmlProperty(const QDomElement &effect, const QString &oldName, const QString &newName) 0222 { 0223 QDomNodeList params = effect.elementsByTagName(QStringLiteral("property")); 0224 // Update property if it already exists 0225 for (int i = 0; i < params.count(); ++i) { 0226 QDomElement e = params.item(i).toElement(); 0227 if (e.attribute(QStringLiteral("name")) == oldName) { 0228 e.setAttribute(QStringLiteral("name"), newName); 0229 break; 0230 } 0231 } 0232 } 0233 0234 void Xml::removeMetaProperties(QDomElement producer) 0235 { 0236 QDomNodeList params = producer.elementsByTagName(QStringLiteral("property")); 0237 for (int i = 0; i < params.count(); ++i) { 0238 QDomElement e = params.item(i).toElement(); 0239 if (e.attribute(QStringLiteral("name")).startsWith(QLatin1String("meta"))) { 0240 producer.removeChild(params.item(i)); 0241 --i; 0242 } 0243 } 0244 }