Skip to content

Commit

Permalink
XmlToJson Namespace fix (#5652)
Browse files Browse the repository at this point in the history
* Fix xmltojson namespaced xml key conversion

* Update xml test with namespaced elements

* Added changelog entry
  • Loading branch information
acpaquette authored Oct 31, 2024
1 parent 9b4978e commit fee86a1
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ file. Slightly modified the FunctionalTestJigsawBundleXYZ ctest accordingly. Iss
- Fixed a bug in isisminer in which bad (e.g. self-intersecting) polygon geometries were not treated properly. Added pertinent unit tests to GisGeometry and Strategy classes. Issue: [5612](https://github.com/DOI-USGS/ISIS3/issues/5612)
- Fixed a bug in kaguyasp2isis that doesn't work for data with a detached label.
- Fixed FunctionalTestCamstatsDefaultParameters test by increasing the runtime speed [#5459](https://github.com/DOI-USGS/ISIS3/issues/5459)
- Fixed XmlToJson namespaced key conversion [#5652](https://github.com/DOI-USGS/ISIS3/pull/5652)

## [8.3.0] - 2024-09-30

Expand Down
32 changes: 17 additions & 15 deletions isis/src/base/objs/XmlToJson/XmlToJson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ namespace Isis {
* @param element A QDomElement to be converted to JSON and added to the JSON object.
*/
json convertLastChildNodeToJson(QDomElement& element){
std::string cleanTagName = element.tagName().replace(":", "_").toStdString();
json newJson;
if (element.hasAttributes()) {
// If there are attributes, add them
Expand All @@ -108,17 +109,17 @@ namespace Isis {
if (!element.text().isEmpty()) {
attributeSection["_text"] = element.text().toStdString();
}
newJson[element.tagName().replace(":", "_").toStdString()] = attributeSection;
newJson[cleanTagName] = attributeSection;
}
else {
// Just add element and its value
// <tag>value</tag>
if (!element.text().isEmpty()) {
newJson[element.tagName().replace(":", "_").toStdString()] = element.text().toStdString();
newJson[cleanTagName] = element.text().toStdString();
}
else {
// <tag /> no value case
newJson[element.tagName().replace(":", "_").toStdString()];
newJson[cleanTagName];
}
}
return newJson;
Expand Down Expand Up @@ -147,23 +148,24 @@ namespace Isis {
*/
json convertXmlToJson(QDomElement& element, json& output) {
while (!element.isNull()) {
std::string cleanTagName = element.tagName().replace(":", "_").toStdString();
QDomElement next = element.firstChildElement();
if (next.isNull()){
json converted = convertLastChildNodeToJson(element);
// Simple case with no repeated tags at the same level
if (!output.contains(element.tagName().toStdString())){
if (!output.contains(cleanTagName)){
output.update(converted);
}
else {
// There is a repeated tag at the same level in the XML, i.e: <a>val1</a><a>val2</a>
// Translated json goal: a:[val1, val2]
// If the converted json has an array already, append, else make it an array
if (!output[element.tagName().toStdString()].is_array()) {
if (!output[cleanTagName].is_array()) {
json repeatedArray;
repeatedArray.push_back(output[element.tagName().toStdString()]);
output[element.tagName().replace(":", "_").toStdString()] = repeatedArray;
output[cleanTagName] = repeatedArray;
}
output[element.tagName().replace(":", "_").toStdString()].push_back(converted[element.tagName().toStdString()]);
output[cleanTagName].push_back(converted[cleanTagName]);
}
}
else {
Expand All @@ -172,16 +174,16 @@ namespace Isis {
// overwriting. This is the following situation:
// XML: <a> <first>value1</first> </a> <a> <second>value2</second></a>
// JSON: a: [ {first:value1, second:value2} ]
if (output.contains(element.tagName().toStdString())) {
if (output.contains(cleanTagName)) {
// If it's an array already, append, else make it an array
json temporaryJson;
convertXmlToJson(next, temporaryJson);
if (!output[element.tagName().toStdString()].is_array()) {
if (!output[cleanTagName].is_array()) {
json repeatedArray;
repeatedArray.push_back(output[element.tagName().toStdString()]);
output[element.tagName().replace(":", "_").toStdString()] = repeatedArray;
output[cleanTagName] = repeatedArray;
}
output[element.tagName().replace(":", "_").toStdString()].push_back(temporaryJson);
output[cleanTagName].push_back(temporaryJson);
}
else {
if (element.hasAttributes()) {
Expand All @@ -192,12 +194,12 @@ namespace Isis {
tempArea["attrib_"+attr.name().toStdString()] = attr.value().toStdString();
}
tempArea.update(
convertXmlToJson(next, output[element.tagName().toStdString()]));
output[element.tagName().replace(":", "_").toStdString()] = tempArea;
convertXmlToJson(next, output[cleanTagName]));
output[cleanTagName] = tempArea;
}
else {
output[element.tagName().toStdString()] =
convertXmlToJson(next, output[element.tagName().replace(":", "_").toStdString()]);
output[cleanTagName] =
convertXmlToJson(next, output[cleanTagName]);
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions isis/tests/XmlToJsonTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,42 @@ TEST(XmlToJson, TestXMLEverythingTogether) {
EXPECT_EQ(result["TagLevel0"]["TagLevel1B"]["Third"]["Greek"]["AnotherLevel"]["Gamma"]["_text"], "GammaValue");
}

// This tests that all the sub-pieces tested above work together in a single XMl document
TEST(XmlToJson, TestXMLWithNamespace) {
QString xmlInput = R"(
<Discipline_Area>
<disp:Display_Settings>
<Local_Internal_Reference>
<local_identifier_reference>eis000xxx_2032116t234928_0000c35f-wac-pushb-img_raw</local_identifier_reference>
<local_reference_type>display_settings_to_array</local_reference_type>
</Local_Internal_Reference>
<disp:Display_Direction>
<disp:horizontal_display_axis>Sample</disp:horizontal_display_axis>
<disp:horizontal_display_direction>Left to Right</disp:horizontal_display_direction>
<disp:vertical_display_axis>Line</disp:vertical_display_axis>
<disp:vertical_display_direction>Top to Bottom</disp:vertical_display_direction>
</disp:Display_Direction>
</disp:Display_Settings>
<img:Exposure>
<img:exposure_duration unit="ms">27.54</img:exposure_duration>
</img:Exposure>
</Discipline_Area>
)";

QDomDocument xmlDocument("TestDocument");
xmlDocument.setContent(xmlInput);
json result = xmlToJson(xmlDocument);

EXPECT_EQ(result["Discipline_Area"]["disp_Display_Settings"]["Local_Internal_Reference"]["local_identifier_reference"], "eis000xxx_2032116t234928_0000c35f-wac-pushb-img_raw");
EXPECT_EQ(result["Discipline_Area"]["disp_Display_Settings"]["Local_Internal_Reference"]["local_reference_type"], "display_settings_to_array");

EXPECT_EQ(result["Discipline_Area"]["disp_Display_Settings"]["disp_Display_Direction"]["disp_horizontal_display_axis"], "Sample");
EXPECT_EQ(result["Discipline_Area"]["disp_Display_Settings"]["disp_Display_Direction"]["disp_horizontal_display_direction"], "Left to Right");
EXPECT_EQ(result["Discipline_Area"]["disp_Display_Settings"]["disp_Display_Direction"]["disp_vertical_display_axis"], "Line");
EXPECT_EQ(result["Discipline_Area"]["disp_Display_Settings"]["disp_Display_Direction"]["disp_vertical_display_direction"], "Top to Bottom");

EXPECT_EQ(result["Discipline_Area"]["img_Exposure"]["img_exposure_duration"]["_text"], "27.54");
EXPECT_EQ(result["Discipline_Area"]["img_Exposure"]["img_exposure_duration"]["attrib_unit"], "ms");
}


0 comments on commit fee86a1

Please sign in to comment.