Unverified Commit fee86a1c authored by Adam Paquette's avatar Adam Paquette Committed by GitHub
Browse files

XmlToJson Namespace fix (#5652)

* Fix xmltojson namespaced xml key conversion

* Update xml test with namespaced elements

* Added changelog entry
parent 9b4978ec
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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

+17 −15
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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 {
@@ -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()) {
@@ -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]);
          }
        }
      }
+38 −0
Original line number Diff line number Diff line
@@ -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");
}