1 | #!/usr/bin/env python |
---|
2 | ### =========================================================================== |
---|
3 | ### |
---|
4 | ### Modifies or add an element in an XML file |
---|
5 | ### |
---|
6 | ### =========================================================================== |
---|
7 | ## |
---|
8 | ## Warning, to install, configure, run, use any of Olivier Marti's |
---|
9 | ## software or to read the associated documentation you'll need at least |
---|
10 | ## one (1) brain in a reasonably working order. Lack of this implement |
---|
11 | ## will void any warranties (either express or implied). |
---|
12 | ## O. Marti assumes no responsability for errors, omissions, |
---|
13 | ## data loss, or any other consequences caused directly or indirectly by |
---|
14 | ## the usage of his software by incorrectly or partially configured |
---|
15 | ## personal. |
---|
16 | ## |
---|
17 | ## SVN information |
---|
18 | __Author__ = "$Author$" |
---|
19 | __Date__ = "$Date$" |
---|
20 | __Revision__ = "$Revision$" |
---|
21 | __Id__ = "$Id$" |
---|
22 | __HeadURL = "$HeadURL$" |
---|
23 | |
---|
24 | # |
---|
25 | # Tested with python/2.7.12 and python/3.6.4 |
---|
26 | # |
---|
27 | import xml.etree.ElementTree |
---|
28 | import argparse, sys, textwrap |
---|
29 | |
---|
30 | # Check version of Python |
---|
31 | Version = sys.version_info |
---|
32 | if Version < (2,7,0) : |
---|
33 | sys.stderr.write ( "You need python 2.7 or later to run this script\n" ) |
---|
34 | sys.stderr.write ( "Present version is: " + str(Version[0]) + "." + str(Version[1]) + "." + str(Version[2]) + "\n" ) |
---|
35 | sys.exit (1) |
---|
36 | |
---|
37 | # Creating a parser to read the command line arguments |
---|
38 | # The first step in using the argparse is creating an ArgumentParser object: |
---|
39 | parser = argparse.ArgumentParser (description = """ |
---|
40 | examples : |
---|
41 | 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 |
---|
42 | python %(prog)s -i iodef.xml -n 'context[@id="interpol_run"]/file_definition/file[@id="dia"]/variable[@name="dest_grid"]' -t dstDomainType |
---|
43 | python %(prog)s -i iodef.xml -e commands.txt (not implemented yet) |
---|
44 | """ + "\n" + "SVN : " + __Revision__, formatter_class=argparse.RawDescriptionHelpFormatter, epilog='-------- This is the end of the help message --------') |
---|
45 | |
---|
46 | # Adding arguments |
---|
47 | group1 = parser.add_mutually_exclusive_group (required=True) |
---|
48 | |
---|
49 | parser.add_argument ( '-i', '--input' , help="input file" , default='iodef.xml', type=str, metavar='<input_file>' ) |
---|
50 | parser.add_argument ( '-o', '--output' , help="output file" , default=None , type=str, metavar='<output_file>' ) |
---|
51 | parser.add_argument ( '-n', '--node' , help="xml node in Xpath syntax", default=None, required=True, type=str, metavar='<xml_node>') |
---|
52 | group1.add_argument ( '-k', '--key' , help="xml key to update" , default=None , type=str , metavar='<xml_key>' ) |
---|
53 | group1.add_argument ( '-t', '--text' , help="will replace the 'text' part of the Xpath by <text>", default=None, type=str, metavar='<text>' ) |
---|
54 | parser.add_argument ( '-v', '--value' , help="new value for xml key", default=None, type=str, metavar='<value>' ) |
---|
55 | parser.add_argument ( '-d', '--debug' , action="store_true", default=False ) |
---|
56 | parser.add_argument ( '-V', '--verbose', action="store_true", default=False ) |
---|
57 | |
---|
58 | # Parse command line |
---|
59 | myargs = parser.parse_args() |
---|
60 | Verbose = myargs.verbose |
---|
61 | |
---|
62 | if Verbose : print ( "Command line arguments : " , myargs ) |
---|
63 | |
---|
64 | FileIn = myargs.input |
---|
65 | FileOut = myargs.output |
---|
66 | Node = myargs.node |
---|
67 | Key = myargs.key |
---|
68 | Text = myargs.text |
---|
69 | Value = myargs.value |
---|
70 | Debug = myargs.debug |
---|
71 | |
---|
72 | # Error handling not dealed by argparse |
---|
73 | if Key != None and Value == None : |
---|
74 | print ( "Error. When -k|--key=<key> is specified, you must specify -v|--value=<xml_value>" ) |
---|
75 | sys.exit (-1) |
---|
76 | |
---|
77 | if FileOut == None : FileOut = FileIn |
---|
78 | |
---|
79 | # Remove whitespaces at both ends |
---|
80 | Node = Node.rstrip().lstrip() |
---|
81 | |
---|
82 | ## Get XML tree from input file |
---|
83 | iodef = xml.etree.ElementTree.parse ( FileIn ) |
---|
84 | |
---|
85 | ## Find node |
---|
86 | nodeList = iodef.findall ( Node ) |
---|
87 | |
---|
88 | ## Check that one and only one node is found |
---|
89 | if len (nodeList) == 0 : |
---|
90 | print ( "Error : node not found" ) |
---|
91 | print ( "Node : " + Node ) |
---|
92 | sys.exit (1) |
---|
93 | |
---|
94 | if len (nodeList) > 1 : |
---|
95 | print ( "Error : " + len (nodeList)+" occurences of node found" ) |
---|
96 | print ( "Node : " + Node ) |
---|
97 | sys.exit (2) |
---|
98 | |
---|
99 | ## Update element |
---|
100 | elem = nodeList[0] |
---|
101 | |
---|
102 | if Debug : |
---|
103 | print ( 'Node : ' + Node ) |
---|
104 | print ( 'Key : ' + Key ) |
---|
105 | print ( 'Value : ' + Value ) |
---|
106 | |
---|
107 | if Text != None : |
---|
108 | if Debug : |
---|
109 | print ( 'Attributes of node: ' + str (elem.attrib) ) |
---|
110 | print ( 'Text : ' + str (elem.text) ) |
---|
111 | elem.text = Text |
---|
112 | |
---|
113 | if Key != None : |
---|
114 | # To do : check that Key exist (it is added if not : do we want that ?) |
---|
115 | if Debug : |
---|
116 | print ( 'Attributes of node: ' + str (elem.attrib) ) |
---|
117 | elem.attrib.update ( { Key:Value } ) |
---|
118 | |
---|
119 | ## Writes XML tree to file |
---|
120 | iodef.write ( FileOut ) |
---|
121 | |
---|
122 | ## This is the end |
---|
123 | sys.exit (0) |
---|
124 | |
---|
125 | ### =========================================================================== |
---|
126 | ### |
---|
127 | ### That's all folk's !!! |
---|
128 | ### |
---|
129 | ### =========================================================================== |
---|
130 | |
---|