File failed to load: https://isis.astrogeology.usgs.gov/9.0.0/Object/assets/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
XmlToJson.cpp
1
5
6/* SPDX-License-Identifier: CC0-1.0 */
7
8#include "XmlToJson.h"
9#include "IException.h"
10
11#include <nlohmann/json.hpp>
12#include <iostream>
13
14#include <QDomDocument>
15#include <QDomElement>
16#include <QFile>
17#include <QString>
18
19using json = nlohmann::json;
20
21namespace Isis {
22 json convertLastChildNodeToJson(QDomElement& element);
23 json convertXmlToJson(QDomElement& element, json& output);
24
35 json xmlToJson(QString xmlFile) {
36 QDomDocument doc("xmlInput");
37 QFile file(xmlFile);
38
39 if (!file.open(QIODevice::ReadOnly)) {
40 QString message = QString("Failed to open file for XML Input: [%1]").arg(xmlFile);
41 throw IException(IException::Io, message, _FILEINFO_);
42 }
43
44 QString errMsg;
45 int errLine, errCol;
46 if (!doc.setContent(&file, &errMsg, &errLine, &errCol)) {
47 file.close();
48 QString message = QString("Failed to use file for XML Input: [%1]. %2 at line %3, column %4").arg(xmlFile).arg(errMsg).arg(errLine).arg(errCol);
49 throw IException(IException::Io, message, _FILEINFO_);
50 }
51
52 file.close();
53
54 return xmlToJson(doc);
55 }
56
57
66 json xmlToJson(QDomDocument& doc) {
67 QDomElement docElem = doc.documentElement();
68 json output;
69 return convertXmlToJson(docElem, output);
70 }
71
72
95 json convertLastChildNodeToJson(QDomElement& element){
96 std::string cleanTagName = element.tagName().replace(":", "_").toStdString();
97 json newJson;
98 if (element.hasAttributes()) {
99 // If there are attributes, add them
100 // <tag attributeName="attributeValue">textValue</tag>
101 json attributeSection;
102 QDomNamedNodeMap attrMap = element.attributes();
103 for (int i=0; i < attrMap.size(); i++) {
104 QDomAttr attr = attrMap.item(i).toAttr();
105 attributeSection["attrib_"+attr.name().toStdString()] = attr.value().toStdString();
106 }
107 // If there is no textValue, don't include it
108 // <tag attributeName="attributeValue" />
109 if (!element.text().isEmpty()) {
110 attributeSection["_text"] = element.text().toStdString();
111 }
112 newJson[cleanTagName] = attributeSection;
113 }
114 else {
115 // Just add element and its value
116 // <tag>value</tag>
117 if (!element.text().isEmpty()) {
118 newJson[cleanTagName] = element.text().toStdString();
119 }
120 else {
121 // <tag /> no value case
122 newJson[cleanTagName];
123 }
124 }
125 return newJson;
126 }
127
128
149 json convertXmlToJson(QDomElement& element, json& output) {
150 while (!element.isNull()) {
151 std::string cleanTagName = element.tagName().replace(":", "_").toStdString();
152 QDomElement next = element.firstChildElement();
153 if (next.isNull()) {
154 json converted = convertLastChildNodeToJson(element);
155 if (!converted.is_null()) {
156 // Simple case with no repeated tags at the same level
157 if (!output.contains(cleanTagName)) {
158 output[cleanTagName] = converted[cleanTagName];
159 }
160 else {
161 // There is a repeated tag at the same level in the XML, i.e: <a>val1</a><a>val2</a>
162 // Translated json goal: a:[val1, val2]
163 // If the converted json has an array already, append, else make it an array
164 if (!output[cleanTagName].is_array()) {
165 json repeatedArray = json::array();
166 repeatedArray.push_back(output[cleanTagName]);
167 output[cleanTagName] = repeatedArray;
168 }
169 output[cleanTagName].push_back(converted[cleanTagName]);
170 }
171 }
172 }
173 else {
174 // If there is already an element with this tag name at any level besides the same one,
175 // add it to a list rather than
176 // overwriting. This is the following situation:
177 // XML: <a> <first>value1</first> </a> <a> <second>value2</second></a>
178 // JSON: a: [ {first:value1, second:value2} ]
179 json temporaryJson;
180 convertXmlToJson(next, temporaryJson);
181
182 if (output.contains(cleanTagName)) {
183 // If it's an array already, append, else make it an array
184 if (!output[cleanTagName].is_array()) {
185 json repeatedArray = json::array();
186 repeatedArray.push_back(output[cleanTagName]);
187 output[cleanTagName] = repeatedArray;
188 }
189 output[cleanTagName].push_back(temporaryJson);
190 }
191 else {
192 if (element.hasAttributes()) {
193 QDomNamedNodeMap attrMap = element.attributes();
194 for (int j=0; j < attrMap.size(); j++) {
195 QDomAttr attr = attrMap.item(j).toAttr();
196 temporaryJson["attrib_"+attr.name().toStdString()] = attr.value().toStdString();
197 }
198 }
199 output[cleanTagName] = temporaryJson;
200 }
201 }
202 element = element.nextSiblingElement();
203 }
204 return output;
205 }
206}
Isis exception class.
Definition IException.h:91
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
json convertLastChildNodeToJson(QDomElement &element)
Not intended to be used directly.
Definition XmlToJson.cpp:95
json xmlToJson(QString xmlFile)
Converts an XML file to a json object.
Definition XmlToJson.cpp:35
json convertXmlToJson(QDomElement &element, json &output)
Not intended to be used directly.