/***********************************************************************//** * @brief Return pointer on child walking down a hierarchy of tags * * @param[in] name Child element hierarchy. * @return Pointer to child element (NULL if element does not exist). * * @exception GException::invalid_argument * Hierarchy string invalid. * * Returns a pointer to the child element described by a hierarchy of the * following syntax * * params > param[1] > value > struct * * The > symbols indicate subsequent hierarchy levels, the square brackets * provides the index in case that multiple tags with the same name exist * at a given hierarchy level. Omitting the index means that the first * tag with the specified name is accessed. * * If the specified element does not exist the method returns a NULL pointer. ***************************************************************************/ GXmlElement* GXmlNode::element(const std::string& name) { // Initialise child node pointer GXmlElement* element = NULL; // Split name into tags std::vector<std::string> tags = gammalib::split(name, ">"); // Walk down the hierarchy GXmlNode* current = this; for (int i = 0; i < tags.size(); ++i) { // Get tag name and index std::string tag = gammalib::strip_whitespace(tags[i]); int index = extract_index(tag); // Break if the requested node does not exist int n = current->elements(tag); if (n < 1 || index < 0 || index >= n) { element = NULL; break; } // Get node element = current->element(tag, index); current = element; // Break if node has not been found if (current == NULL) { element = NULL; break; } } // endfor: walked down hierarchy // Return child element return element; }
/***********************************************************************//** * @brief Append all XML child nodes from another XML node * * @param[in] node XML node. * * Append all XML child nodes found in @p node to the actual object. Nodes * are copied deeply so that they live now on their on in the actual object. ***************************************************************************/ void GXmlNode::extend(const GXmlNode& node) { // Do nothing if node container is empty if (!node.is_empty()) { // Get size. Note that we extract the size first to avoid an // endless loop that arises when a container is appended to // itself. int num = node.size(); // Reserve enough space reserve(size() + num); // Loop over all child nodes and append pointers to deep copies for (int i = 0; i < num; ++i) { m_nodes.push_back(node[i]->clone()); } } // endif: node container was not empty // Return return; }
/***********************************************************************//** * @brief Test XML constructors **************************************************************************/ void TestGXml::test_GXml_construct(void) { // Test void constructor test_try("Test void constructor"); try { GXml xml; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test load constructor test_try("Test load constructor"); try { GXml xml(m_xml_file); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test copy constructor test_try("Test copy constructor"); try { GXml xml1(m_xml_file); GXml xml2 = xml1; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test XML file creation test_try("Test XML file creation"); try { GXml xml; xml.append(GXmlComment("This is a comment.")); xml.append(GXmlElement("source_library")); GXmlElement* lib = xml.element("source_library", 0); lib->append(GXmlElement("source name=\"LMC\" type=\"DiffuseSource\"")); GXmlNode* src = lib->element("source", 0); src->append(GXmlElement("spectrum type=\"PLSuperExpCutoff\"")); GXmlNode* spec = src->element("spectrum", 0); spec->append(GXmlElement("parameter free=\"1\" max=\"1000\" min=\"1e-07\"" " name=\"Prefactor\" scale=\"1e-07\"" " value=\"0.02754520844\"")); spec->append(GXmlElement("parameter free=\"1\" max=\"5\" min=\"-5\"" " name=\"Index1\" scale=\"1\" value=\"-2.0458781\"")); GXmlElement* par = spec->element("parameter", 0); par->attribute("value", "1.01"); par->attribute("error", "3.145"); par = spec->element("parameter", 1); par->attribute("value", "-2.100"); par->attribute("error", "9.876"); src->append(GXmlElement("spatialModel file=\"LMC.fits\" type=\"SpatialMap\"")); GXmlNode* spat = src->element("spatialModel", 0); spat->append(GXmlElement("parameter free=\"0\" max=\"1000\" min=\"0.001\"" " name=\"Prefactor\" scale=\"1\" value=\"1\"")); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Return return; }