Index: /TOOLS/MOSAIX/CreateWeightsMask.bash
===================================================================
--- /TOOLS/MOSAIX/CreateWeightsMask.bash	(revision 6090)
+++ /TOOLS/MOSAIX/CreateWeightsMask.bash	(revision 6091)
@@ -340,31 +340,35 @@
 cp iodef_oce_to_atm.xml   iodef.xml
 
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="mask_src"]'     -k name  -v maskutil_T
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="area_src"]'     -k name  -v area_grid_T
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_src"]'                     -k type  -v ${srcDomainType}
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_dst"]'                     -k type  -v ${dstDomainType}
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k order -v 1
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k quantity    -v false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k renormalize -v false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k use_area -v false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="mask_source"]'   -k name  -v maskutil_T
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="area_source"]'   -k name  -v area_grid_T
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]'                                 -k name  -v dia_${OutFileName}
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="title"]'         -t "${SRC} mask interpolated to ${DST}"
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="source_grid"]'   -t ${srcDomainType}
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="dest_grid"]'     -t ${dstDomainType}
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="order"]'         -t 1
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_src"]'                      -k type  -v ${srcDomainType}
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]'                      -k type  -v ${dstDomainType}
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k weight_filename -v rmp_${OutFileName}.nc
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k order -v 1
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="normalization"]' -t false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="quantity"]'      -t false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="use_area"]'      -t false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k renormalize -v false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k quantity    -v false
-python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k use_area    -v false
-
+cat << EOF > command_file_${OutFileName}.txt
+-n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="mask_src"]'     -k name  -v maskutil_T
+-n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="area_src"]'     -k name  -v area_grid_T
+-n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_src"]'                     -k type  -v ${srcDomainType}
+-n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_dst"]'                     -k type  -v ${dstDomainType}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k order -v 1
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k quantity    -v false
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k renormalize -v false
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k use_area -v false
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="mask_source"]'   -k name  -v maskutil_T
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="area_source"]'   -k name  -v area_grid_T
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]'                                 -k name  -v dia_${OutFileName}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="title"]'         -t "${SRC} mask interpolated to ${DST}"
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="source_grid"]'   -t ${srcDomainType}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="dest_grid"]'     -t ${dstDomainType}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="order"]'         -t 1
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_src"]'                      -k type  -v ${srcDomainType}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]'                      -k type  -v ${dstDomainType}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k weight_filename -v rmp_${OutFileName}.nc
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k order -v 1
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="normalization"]' -t false
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="quantity"]'      -t false
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="use_area"]'      -t false
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k renormalize -v false
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k quantity    -v false
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k use_area    -v false
+EOF
+
+python3 update_xml.py -i iodef.xml -c command_file_${OutFileName}.txt
 cp iodef.xml iodef_${OutFileName}.xml
+
 ln -fs ${OCE}_coordinates_mask.nc  oce_grid.nc
 ln -fs ${ATM}_grid.nc              atm_grid.nc
@@ -488,54 +492,55 @@
     #ln -fs ${ATM}_grid.nc              atm_grid.nc
     ln -fs ${ATM}_grid_maskFrom_${OCE}.nc atm_grid.nc
+
+    OutFileName=${srcGrid}${src}_to_${dstGrid}${dst}_${FullName}
     
     case ${Direction} in
 	( o2a )
 	cp iodef_oce_to_atm.xml iodef.xml
-	
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="mask_src"]'   -k name -v maskutil_${DSTGRID} 
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/file_definition/file[@id="file_dst"]/field[@id="mask_dst"]'   -k name -v Oce2AtmMask
-	
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="mask_source"]' -k name -v maskutil_${SRCGRID}
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="area_source"]' -k name -v area_grid_${SRCGRID}
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="mask_dest"]'   -k name -v Oce2AtmMask
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="area_dest"]'   -k name -v aire
+	cat << EOF > command_file_${OutFileName}.txt
+-n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="mask_src"]'   -k name -v maskutil_${DSTGRID} 
+-n 'context[@id="interpol_read"]/file_definition/file[@id="file_dst"]/field[@id="mask_dst"]'   -k name -v Oce2AtmMask
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="mask_source"]' -k name -v maskutil_${SRCGRID}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="area_source"]' -k name -v area_grid_${SRCGRID}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="mask_dest"]'   -k name -v Oce2AtmMask
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="area_dest"]'   -k name -v aire
+EOF
 	;;
 	( a2o )
 	cp iodef_atm_to_oce.xml iodef.xml
-	
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="mask_src"]'   -k name -v Oce2AtmMask
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/file_definition/file[@id="file_dst"]/field[@id="mask_dst"]'   -k name -v mask_${DSTGRID}
-	
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="mask_source"]' -k name  -v Oce2AtmMask
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="area_source"]' -k name  -v aire
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="mask_dest"]'   -k name  -v mask_${DSTGRID}
-	python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="area_dest"]'   -k name  -v area_grid_${DSTGRID}
-	;;
-    esac
-
-    OutFileName=${srcGrid}${src}_to_${dstGrid}${dst}_${FullName}
+	cat << EOF > command_file_${OutFileName}.txt
+-n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="mask_src"]'   -k name -v Oce2AtmMask
+-n 'context[@id="interpol_read"]/file_definition/file[@id="file_dst"]/field[@id="mask_dst"]'   -k name -v mask_${DSTGRID}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="mask_source"]' -k name -v Oce2AtmMask
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="area_source"]' -k name -v aire
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="mask_dest"]'   -k name -v mask_${DSTGRID}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="file_dst"]/field[@id="area_dest"]'   -k name -v area_grid_${DSTGRID}
+EOF
+	;;
+    esac
+
+    cat << EOF >> command_file_${OutFileName}.txt
+-n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_dst"]'                     -k type  -v ${dstDomainType}
+-n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_src"]'                     -k type  -v ${srcDomainType}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_src"]'                      -k type  -v ${srcDomainType}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]'                      -k type  -v ${dstDomainType}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k weight_filename -v rmp_${OutFileName}.nc
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k order       -v ${numOrder}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k quantity    -v ${Quantity}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k renormalize -v ${Renormalize}
+-n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k use_area    -v ${useArea}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]'                                 -k name -v dia_${OutFileName}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="title"]'         -t "${SRC} mask interpolated to ${DST}"
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="dest_grid"]'     -t ${dstDomainType}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="source_grid"]'   -t ${srcDomainType}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="normalization"]' -t ${Renormalize}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="order"]'         -t ${numOrder}   
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="quantity"]'      -t ${Quantity}
+-n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="use_area"]'      -t ${useArea}
+EOF
+
+    python3 update_xml.py -i iodef.xml -c command_file_${OutFileName}.txt
+    cp iodef.xml iodef_${OutFileName}.xml
     
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_dst"]'                     -k type  -v ${dstDomainType}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_read"]/domain_definition/domain[@id="domain_src"]'                     -k type  -v ${srcDomainType}
-    
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_src"]'                      -k type  -v ${srcDomainType}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]'                      -k type  -v ${dstDomainType}
-    
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k weight_filename -v rmp_${OutFileName}.nc
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k order       -v ${numOrder}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k quantity    -v ${Quantity}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k renormalize -v ${Renormalize}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/domain_definition/domain[@id="domain_dst"]/interpolate_domain'   -k use_area    -v ${useArea}
-    
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]'                                 -k name -v dia_${OutFileName}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="title"]'         -t "${SRC} mask interpolated to ${DST}"
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="dest_grid"]'     -t ${dstDomainType}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="source_grid"]'   -t ${srcDomainType}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="normalization"]' -t ${Renormalize}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="order"]'         -t ${numOrder}   
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="quantity"]'      -t ${Quantity}
-    python3 update_xml.py -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="use_area"]'      -t ${useArea}
-    
-    cp iodef.xml iodef_${OutFileName}.xml
     ${MpiRun} ./interpol.exe --mask_src=${maskSrc} --mask_dst=${maskDst} --use_area=${useArea}
 
Index: /TOOLS/MOSAIX/update_xml.py
===================================================================
--- /TOOLS/MOSAIX/update_xml.py	(revision 6090)
+++ /TOOLS/MOSAIX/update_xml.py	(revision 6091)
@@ -22,5 +22,8 @@
 __HeadURL    = "$HeadURL$"
 
-# 
+# python update_xml.py -i ~/Unix/TOOLS/MOSAIX/iodef_atm_to_oce.xml -o essai.xml -n 'context[@id="interpol_read"]/file_definition/file[@id="file_src"]/field[@id="mask_src"]' -k name -v Bidon
+# python update_xml.py -i ~/Unix/TOOLS/MOSAIX/iodef_atm_to_oce.xml -d -o essai.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="title"]' -t "SRC mask interpolated to DST"
+# python update_xml.py -i ~/Unix/TOOLS/MOSAIX/iodef_atm_to_oce.xml -o essai.xml -c InFile.txt
+
 # Tested with python/2.7.12 and python/3.6.4
 #
@@ -34,86 +37,157 @@
   sys.stderr.write ( "Present version is: " + str(Version[0]) + "." + str(Version[1]) + "." + str(Version[2]) + "\n" )
   sys.exit (1)
+
+## ============================================================================
+## Needed functions
+
+def simplify_string_list (list_str) :
+    '''Concatenate some elements of the list of strings when needed'''
+    zlist = list_str.copy () ; list_new = []
+    while ( len (zlist) > 0 ) :
+        arg = zlist.pop (0)    
+        if arg[0] == '"' :
+            for arg2 in zlist.copy () :
+                arg = arg + " " + arg2
+                zlist.pop (0)
+                if arg2[-1] == '"' : break
+        arg = arg.strip('"').strip("'")
+        list_new.append (arg)
+    return list_new
   
+def UpdateNode (iodef, Node, Text, Key, Value) :
+    '''Update an xml node'''
+    # Remove whitespaces at both ends
+    Node = Node.rstrip().lstrip()
+
+    ## Find node
+    nodeList = iodef.findall (Node)
+
+    ## Check that one and only one node is found
+    if len (nodeList) == 0 :
+        print ( "Error : node not found" )
+        print ( "Node  : ", Node )
+        sys.exit (1)
+    
+    if len (nodeList) > 1 :
+        print ( "Error : " + len (nodeList)+" occurences of node found" )
+        print ( "Node  : ", Node )
+        sys.exit (2)
+
+    ## Update element
+    elem = nodeList[0]
+
+    if Debug :
+        print ( 'Node:', Node, ' -- Key:', Key, ' -- Value:', Value , ' -- Text:', Text  )
+
+    if Text != None :
+        if Debug :
+            print ( 'Attributes of node: ' + str (elem.attrib) )
+            print ( 'Text              : ' + str (elem.text)   )
+        elem.text = Text
+
+    if Key != None :
+        # To do : check that Key exist (it is added if not : do we want that ?)
+        if Debug :
+            print ( 'Attributes of node: ' + str (elem.attrib) )
+        elem.attrib.update ( { Key:Value } )
+
+    return iodef
+
+## ============================================================================
+## Main code
+
 # Creating a parser to read the command line arguments
 # The first step in using the argparse is creating an ArgumentParser object:
 parser = argparse.ArgumentParser (description = """
-examples : 
+Examples with the modification on the command line : 
      python %(prog)s -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="file_src"]/field[@id="mask_source"]' -k name -v maskutil_T
      python %(prog)s -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="dest_grid"]'   -t dstDomainType
-     python %(prog)s -i iodef.xml -e commands.txt (not implemented yet)
-   """ + "\n" + "SVN : " + __Revision__, formatter_class=argparse.RawDescriptionHelpFormatter, epilog='-------- This is the end of the help message --------')
+
+Usage with a command file : 
+     python %(prog)s -i iodef.xml -c commands.txt
+   
+Syntax in the command file : removes the quote around the node description : 
+-n context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="dest_grid"]   -t dstDomainType
+
+   """ + "SVN : " + __Revision__, formatter_class=argparse.RawDescriptionHelpFormatter, epilog='-------- This is the end of the help message --------')
 
 # Adding arguments
-group1 = parser.add_mutually_exclusive_group (required=True)
-
-parser.add_argument ( '-i', '--input'  , help="input file"            , default='iodef.xml', type=str, metavar='<input_file>' )
-parser.add_argument ( '-o', '--output' , help="output file"           , default=None       , type=str, metavar='<output_file>'  )
-parser.add_argument ( '-n', '--node'   , help="xml node in Xpath syntax", default=None, required=True, type=str, metavar='<xml_node>')
-group1.add_argument ( '-k', '--key'    , help="xml key to update"     , default=None , type=str , metavar='<xml_key>' )
-group1.add_argument ( '-t', '--text'   , help="will replace the 'text' part of the Xpath by <text>", default=None, type=str, metavar='<text>' )
-parser.add_argument ( '-v', '--value'  , help="new value for xml key", default=None, type=str, metavar='<value>' )
+group1 = parser.add_mutually_exclusive_group (required=False)
+
+parser.add_argument ( '-i', '--input'  , help="XML input file"              , default='iodef.xml', type=str, metavar='<input_file>'  )
+parser.add_argument ( '-o', '--output' , help="XML output file"             , default=None       , type=str, metavar='<output_file>' )
+parser.add_argument ( '-n', '--node'   , help="XML node in Xpath syntax", default=None, type=str, metavar='<xml_node>')
+group1.add_argument ( '-k', '--key'    , help="XML key to update"       , default=None , type=str , metavar='<xml_key>' )
+group1.add_argument ( '-t', '--text'   , help="Will replace the 'text' part of the Xpath by <text>", default=None, type=str, metavar='<text>' )
+parser.add_argument ( '-v', '--value'  , help="New value for xml key  ", default=None, type=str, metavar='<value>' )
 parser.add_argument ( '-d', '--debug'  , action="store_true", default=False )
 parser.add_argument ( '-V', '--verbose', action="store_true", default=False )
+parser.add_argument ( '-c', '--commandfile', help="file with list of command", default=None, type=str )
 
 # Parse command line
-myargs = parser.parse_args()
-Verbose  = myargs.verbose
-
-if Verbose : print ( "Command line arguments : " , myargs )
-
-FileIn   = myargs.input
-FileOut  = myargs.output
-Node     = myargs.node
-Key      = myargs.key
-Text     = myargs.text
-Value    = myargs.value
-Debug    = myargs.debug
-
-# Error handling not dealed by argparse
-if Key != None and Value == None :
-    print ( "Error. When -k|--key=<key> is specified, you must specify -v|--value=<xml_value>" )
-    sys.exit (-1)
-
+myargs  = parser.parse_args ()
+Verbose = myargs.verbose
+Debug   = myargs.debug
+
+if Debug : print ( "Command line arguments : ", myargs )
+
+FileCommand = myargs.commandfile
+FileIn      = myargs.input
+FileOut     = myargs.output
+Node        = myargs.node
+Key         = myargs.key
+Text        = myargs.text
+Value       = myargs.value
+    
+if FileCommand != None : 
+    if ( Node != None or Key != None or Text != None or Value != None ) :
+        print ('Error : when a command file is specified, options -k|--key, -n|--node and -v|--value a unused' )
+        exit (-2)
+    
 if FileOut == None : FileOut = FileIn
-
-# Remove whitespaces at both ends
-Node = Node.rstrip().lstrip()
-
+    
 ## Get XML tree from input file
 iodef = xml.etree.ElementTree.parse ( FileIn )
 
-## Find node
-nodeList = iodef.findall ( Node )
-
-## Check that one and only one node is found
-if len (nodeList) == 0 :
-    print ( "Error : node not found" )
-    print ( "Node  : " + Node )
-    sys.exit (1)
-    
-if len (nodeList) > 1 :
-    print ( "Error : " + len (nodeList)+" occurences of node found" )
-    print ( "Node  : " + Node )
-    sys.exit (2)
-
-## Update element
-elem = nodeList[0]
-
-if Debug :
-    print ( 'Node  : ' + Node  )
-    print ( 'Key   : ' + Key   )
-    print ( 'Value : ' + Value )
-
-if Text != None :
-    if Debug :
-        print ( 'Attributes of node: ' + str (elem.attrib) )
-        print ( 'Text              : ' + str (elem.text)   )
-    elem.text = Text
-
-if Key != None :
-    # To do : check that Key exist (it is added if not : do we want that ?)
-    if Debug :
-        print ( 'Attributes of node: ' + str (elem.attrib) )
-    elem.attrib.update ( { Key:Value } )
+if FileCommand == None :
+    ## Only one node to modify
+    
+    # Error handling not dealed by argparse
+    if Key != None and Value == None :
+        print ( "Error. When -k|--key=<key> is specified, you must specify -v|--value=<xml_value>" )
+        sys.exit (-1)
+
+    iodef = UpdateNode ( iodef, Node, Text, Key, Value)
+
+else :
+    ## Read a list of modification commands in a command file
+    fic = open (FileCommand, 'r')
+    lignes = fic.readlines()
+
+    for nn, ligne in enumerate (lignes) :
+
+        ligne = ligne.strip()
+        if ligne    == ''  : break # Skips blank lines
+        if ligne[0] == '#' : break # Skips comment lines
+
+        ligne = ligne.split('#')[0] # Remove trailing comments
+        
+        list_args = ligne.split()
+        list_args = simplify_string_list ( list_args )
+        
+        if Debug :
+            print ( '{:3d} : '.format(nn+1), end='')
+            print ( list_args )
+        myargs_ligne = parser.parse_args ( list_args )
+
+        Node     = myargs_ligne.node
+        Key      = myargs_ligne.key
+        Text     = myargs_ligne.text
+        Value    = myargs_ligne.value
+        
+        if Key != None and Value == None :
+            print ( "Error. When -k|--key=<key> is specified, you must specify -v|--value=<xml_value>" )
+            sys.exit (-1)
+        UpdateNode ( iodef, Node, Text, Key, Value)
     
 ## Writes XML tree to file
