Earth Observation Mission CFI Software Usage Guide for Object Oriented Software |
The Earth Observation CFI provides a class called XmlFile (FileHandling library) that is dedicated to handle XML files.
Although the XmlFile class hides all these details to the programmer, a few basic concepts need to be presented here to understand how to use the library functions in order to achieve a given goal. We assume that the user has some basic knowledge of XML and understands the concepts of XML elements, attributes and text nodes:
Any well-formed XML file may be viewed as a hierarchy of elements, attributes and values that can be represented as a tree. In fact this is the in-memory representation used by libxml when an XML file is read into memory.
In order to read an XML file, the following sequence should be followed:
XmlFile myXml(filename)
XmlFile myXml()
myXml.read(filename)
XmlFile::clean
, or it is done when the object XmlFile is destroyed. The sequential reading allows to read a file ensuring that all elements within the XML tree are visited only once using recursively the following rules:
The XmlFile class uses an iterarator that points to the last read element. This iterator points to the root element when the file is loaded in memory (after the calling the constructor or the read
method)
Starting with that iterator, all elements are visited once and only once until the iterator returns to the root element. The iterator behaves as follows:
XmlFile::getElementValueAs*
method is called several times, the search will start just after the point where the iterator was left in the preceding call. XmlFile::root()
method allows to reset the iterator to the root element in order to start over from the beginning. Following there is a summary of the methods for reading the files sequentially:
XmlFile::getElementValueAs*
(* = Int, Real, String):anx = myXml.getElementValueAsReal("ANX_Longitude")
XmlFile::getElementArrayAs*
(* = Int, Real, String):
These methods read all elements with a given name. A call to any of these functions will first set the iterator pointing to the root element, then will traverse the file looking for the requested elements and will return the vector of values leaving the iterator pointing to the last element read.
Example:
intArray = myXml.getElementValueArrayAsInt("Absolute_Orbit", intArray)
XmlFile::getAttributeValueAs*
(* = Int, Real, String):numOrbitChanges = myXml.getElementValueArrayAsInt("List_Of_Orbit_Changes", "count")
See Sequential reading example
Random access to the in-memory representation of an XML file is achieved using XPath expressions. XPath expressions allow addressing XML elements and attributes using a syntax that resembles the one used for addressing files and directories in a hierarchical file system and is based on the following rules:
Following there is a summary of the methods for reading the file with the path expresion:
XmlFile::getPathValueAs*
(* = Int, Real, String):mlstDrift = myXml.getPathValueAsReal ("/Earth_Explorer_File/Data_Block/List_of_Orbit_Changes/Orbit_Change[1]/Cycle/MLST_Drift")
XmlFile::getPathArrayAs*
(* = Int, Real, String):mlstDriftArray = myXml.getPathArrayAsReal ("/Earth_Explorer_File/Data_Block/List_of_Orbit_Changes/Orbit_Change[*]/Cycle/MLST_Drift")
On these methods iterator has the same behaviour as in the XmlFile::getElementValueAs*
familliy of methods.
Together with these functions for reading, the class provides methods for a random access to a requested tag:
XmlFile::root
: Go to the root element XmlFile::next
: Go to the next element: XmlFile::nextSibling
: Go to the next sibling XmlFile::toElement
: Go to the element next element with the requested name XmlFile::toPath
: Go to the element element with the requested path XmlFile::currentElementName
: Get the current element name XmlFile::currentPathName
: Get the current path name XmlFile::findValueInElement
: Find the Xpath with a given element name and value XmlFile::findValueInPath
: Find the Xpath with a given element Xpath and value. The input XPath expression must contain the [*]
character sequence in order to indicate the elements in a sequence (list) that are iterated. All these functions set the iterator pointing to the found element. If the search operation returns an error, the iterator is not moved.
// ------------------------------------------------------------------------ // // C++ Example Program. // READING XML FILES: Sequential reading // // ------------------------------------------------------------------------ // Non-EOCFI include files #include <string> #include <vector> #include <iostream> // EOCFI includes #include "XmlFile.h" #include "FixedHeader.h" #include "FileHandlingData.h" // Namespaces using namespace EECFI; using namespace std; // Main program int main (int argc, char *argv[]) { //------------------------------------------------- //------------------------------------------------- try { long i; // Load XML file into memory XmlFile myXml("./osf.xml"); //Reading element "File_Description" (First element with that tag name) string stringValue = myXml.getElementValueAsString("File_Description"); cout << "File_Description: " << stringValue << endl; // Reading an attribute: Number of elements in the list long orbitNumber; orbitNumber = myXml.getAttributeValueAsInt("List_of_Orbit_Changes", "count"); cout << "List_Of_Orbit_Changes contain " << orbitNumber << " Elements" << endl; // Reading the list of all absolute orbits in the list vector <long> integerArray; integerArray = myXml.getElementArrayAsInt("Absolute_Orbit", integerArray); for (i = 0 ; i < integerArray.size() ; ++i) { cout << "Orbit Number " << i <<" = " << integerArray[i] << endl; } // Free memory (optional: the class destructor would free the memory in anycase) myXml.clean(); }//end try catch (CfiError cfiError) { //If an exception is thrown, there have been errors during execution vector<string> errorMessages; // Get error messages cfiError.getMsg(errorMessages); // Pring Error messages for (long i = 0; i < errorMessages.size(); i++) { cout << errorMessages[i] << endl; } } return 0; }
// ------------------------------------------------------------------------ // // C++ Example Program. // READING XML FILES: Random reading // // ------------------------------------------------------------------------ // Non-EOCFI include files #include <string> #include <vector> #include <iostream> // EOCFI includes #include "XmlFile.h" #include "FixedHeader.h" #include "FileHandlingData.h" // Namespaces using namespace EECFI; using namespace std; // Main program int main (int argc, char *argv[]) { //------------------------------------------------- // Put all the code inside try-catch statements // so, if something fails, an exception is thrown //------------------------------------------------- try { long i; XmlFile myXml; // Load XML file into memory myXml.read("./osf.xml"); //Reading element "File_Description" (read an specific XPath) string stringValue = myXml.getPathValueAsString("/Earth_Explorer_File/Earth_Explorer_Header/Fixed_Header/File_Description"); cout << "File_Description: " << stringValue << endl; //Reading element "ANX_Longitude" from the 3rd element in the list (read an specific XPath) double doubleValue = myXml.getPathValueAsReal("/Earth_Explorer_File/Data_Block/List_of_Orbit_Changes/Orbit_Change[3]/Cycle/ANX_Longitude"); cout << "ANX_Longitude(3): " << doubleValue << endl; // Reading the list of all absolute orbits in the list vector <long> integerArray; integerArray = myXml.getPathArrayAsInt("/Earth_Explorer_File/Data_Block/List_of_Orbit_Changes/Orbit_Change[*]/Orbit/Absolute_Orbit", integerArray); for (i = 0 ; i < integerArray.size() ; ++i) { cout << "Orbit Number " << i <<" = " << integerArray[i] << endl; } // Search an element with a given XPath string searchPath; string foundPath; searchPath = "/Earth_Explorer_File/Data_Block/List_of_Orbit_Changes/Orbit_Change[*]/Orbit/Absolute_Orbit"; foundPath = myXml.findValueInPath(searchPath, "7488"); cout << "Orbit Value found in XPath = " << foundPath << endl; // Free memory (optional: the class destructor would free the memory in anycase) myXml.clean(); }//end try catch (CfiError cfiError) { //If an exception is thrown, there have been errors during execution vector<string> errorMessages; // Get error messages cfiError.getMsg(errorMessages); // Pring Error messages for (long i = 0; i < errorMessages.size(); i++) { cout << errorMessages[i] << endl; } } return 0; }