| Earth Observation Mission CFI Software Usage Guide for Object Oriented Software |

# WRITING XML FILES

The XmlFile class in the FileHandling library can be used to write or modify XML files:

## Writing a new file

In order to create an XML file, the following calling sequence should be followed:

- Create XmlFile object with the empty constructors:
  `XmlFile myXml()
  ` Note that the FileHandling library may handle in parallel up to XFCFI_MAX_FILES_NUMBER files.

- Create the XML tree in memory with `XmlFile::create`:
  `myXml.create()
  `

- Create the root element:
  `myXml.createRoot("RootNodeName")
  `

- Add elements to the file.

- Write the XML file to disk:
  `myXml.write(output_file_name)`

- Clean memory. The in-memory representation of an XML file normally takes a significant amount of memory space, typically between 7 and 10 times the size of the file on disk. For this reason it is important to provide the means for releasing the memory allocated after being used. This can be done using the `XmlFile::clean`, or it is done when the object XmlFile is destroyed.

## Modifying an existing file

It is possible to modify an existing XML file and save to disk with the same name or a different one. The following calling sequence should be followed:

- Create XmlFile object. There are two options to create the object:

  1. Using the constructor with the input file name:
     `XmlFile myXml(input_file_name)`

  2. With the empty constructor and loading the file in memory with XmlFile::read method:
     `XmlFile myXml()
     myXml.read(input_file_name)`

  Note that the FileHandling library may handle in parallel up to XFCFI_MAX_FILES_NUMBER files.

- Add and or modify elements to the file.

- Write the XML file to disk:

  - Save the file with the same name (overwrite file): `myXml.write()`
  - Save the file with a different name: `myXml.write(output_file_name)`

- Clean memory. The in-memory representation of an XML file normally takes a significant amount of memory space, typically between 7 and 10 times the size of the file on disk. For this reason it is important to provide the means for releasing the memory allocated after being used. This can be done using the `XmlFile::clean`, or it is done when the object XmlFile is destroyed.

## Adding elements in an XML file

Elements may be added using as input:

- a reference element to which they are attached:referenced using an XPath expression
- the created element name

The following possibilities are available:

- Add a child to the reference element with `XmlFile::addChild`. If the reference element already has children, the new element will be appended at the end of the children list.
- Add a sibling after the reference element using `XmlFile::addNext`. This will insert the new element just after the reference one.
- Add a sibling before the reference element using `XmlFile::addPrevious`. This will insert the new element just before the reference one.
- Attributes are added with `XmlFile::addAttribute` function using the name of the element that contains them as the reference element.

After a new element has been added to the in-memory representation of the XML file, the iterator is pointing to the last added element. Therefore, relative XPath expressions used just after an element insertion are relative to the inserted element.

## Removing elements in an XML file

Existing elements are removed using `XmlFile::removeNode` with an XPath expression addressing them. If the requested element has children, all of them will be removed recursively.

## Setting and/or modifying element values

When elements and attributes are created, they have no value. Element and attribute values may be set and/or modified with `XmlFile::setValue` (overcharged methods using an XPath expression for addressing the requested element or attribute).

## Example

    // ------------------------------------------------------------------------
    //
    //                           C++ Example Program.
    //                           WRITING 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
      {
        XmlFile myXml;
        static string writtenXmlFile("output_file.xml");

        //The name to the file is given when we write it to disk
        myXml.create();
        myXml.createRoot("Earth_Explorer_File");

        // Creating a child after another
        myXml.addChild( ".", "Data_Block");
        myXml.addChild( ".", "List_of_Orbit_Changes");
        myXml.addChild( ".", "Orbit_Change");
        myXml.addChild( ".", "Orbit");
        myXml.addChild( ".", "Absolute_Orbit");

        // Adding a value to the current node
        myXml.setValue( ".", "10", "%s");

        // Adding a sibling next to the current node, and then its value
        // Creating and setting value can be done in 2 steps...
        myXml.addNext( ".", "Relative_Orbit");
        myXml.setValue( ".", "15", "%s");

        //... or only in one
        myXml.addChild( "..", "Phase_Number", "1", "%s");

        // Adding a sibling before the current node, and then its value
        myXml.addPrevious( ".", "Cycle_Number", "1", "%s");

        // Another child, with a different path
        myXml.addChild( "/Earth_Explorer_File/Data_Block/List_of_Orbit_Changes/Orbit_Change[1]", "Cycle");

        myXml.addChild( ".", "Repeat_Cycle", "3", "%s");
        myXml.addAttribute( ".", "units", "day", "%s");
        myXml.addNext( ".", "Cycle_Length");

        // Adding an attribute to the current node, and then its value
        myXml.addAttribute( ".", "unit");
        myXml.setValue( "@unit", "orbit", "%s");

        myXml.setValue ( ".", "43" , "%s");
        myXml.addNext( ".", "ANX_Longitude");

        // Adding a value as double. Please, pay attention to the format
        myXml.setValue( ".", 0.1335, "%06.4lf" );
        myXml.addAttribute( ".", "unit", "deg", "%s");

        // Removing an attribute, and then the current node
        myXml.removeNode( "@unit" );
        myXml.removeNode( "../Repeat_Cycle" );

         myXml.addPrevious( "Cycle_Length", "Repeat_Cycle");

         // Adding a value as long. Please, pay attention to the format
         myXml.setValue( ".", 5L, "%ld" );
         myXml.setValue( "@unit", "day", "%s");
         myXml.setValue( "../Cycle_Length", "57", "%s");
         myXml.addChild( "..",  "MLST", "22:00:00.45545", "%s");
         myXml.addNext( ".", "MLST_Drift", "011.010101", "%s" );
         myXml.addChild( "../..", "Time_of_ANX");
         myXml.addChild( ".", "TAI_of_ANX", "TAI=2002-03-01T03:01:09.01345", "%s" );
         myXml.addNext( ".", "UTC_of_ANX", "UTC=2002-03-01T03:01:10.01345", "%s" );
         myXml.addNext( ".", "UT1_of_ANX", "UT1=2002-03-01T03:01:11.01345", "%s");

         //Write XML file to disk
         myXml.write( writtenXmlFile );

      } //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;

    }