-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxmlSupport.py
executable file
·202 lines (165 loc) · 6.25 KB
/
xmlSupport.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/usr/bin/env python
'''read XML configuration files into a common data structure'''
import logging
import os.path
import re
import sys
import time
from xml.etree import ElementTree
import xml.dom.minidom
logger = logging.getLogger(__name__)
#**************************************************************************
def readPvlistXML(xmlFile):
'''get the list of PVs to monitor from the XML file'''
doc = openScanLogFile(xmlFile)
xref = {}
if doc != None:
db = []
for element in doc.findall('EPICS_PV'):
arr = {}
arr['desc'] = element.text.strip()
for attribute in element.attrib.keys():
arr[attribute] = element.attrib[attribute].strip()
db.append(arr)
xref['pvList'] = db
xref['scanLogFile'] = doc.find('scanLog_file').text
xref['local_www_dir'] = doc.find('local_www_dir').text
return(xref)
#**************************************************************************
readConfigurationXML = readPvlistXML
# def readConfigurationXML(pvListFile):
# '''locate the PV configuration from XML into memory'''
# return readPvlistXML(pvListFile)
#**************************************************************************
def openScanLogFile(xmlFile):
'''
open the XML file with ElementTree
return the doc (doc.getroot() to get the root node)
'''
doc = None
try:
doc = ElementTree.parse(xmlFile)
except Exception:
pass
return doc
#**************************************************************************
def locateScanID(doc, scanid):
'''
find the XML scan entry with matching id attribute
return XML node or None if not found
'''
result = None
#query = "scan/[@id='%s']" % scanid
for node in doc.findall("scan"):
if node.get("id") == scanid:
result = node
break
return result
#**************************************************************************
def flagRunawayScansAsUnknown(doc, scanid):
'''sometimes, a scan ends without this program finding out'''
for node in doc.findall("scan"): # look for any scan ...
if node.get("state") == "scanning": # with state="scanning" ...
if node.get("id") != scanid: # but not the newest node ...
node.set("state", "unknown") # THIS node is not scanning anymore
#**************************************************************************
def readFileAsLines(filename):
'''
open a file and read all of it into
memory as a list separated by line breaks,
return None if error or cannot find file
'''
if not os.path.exists(filename):
return None
try:
with open(filename, 'r') as f:
buf = f.read()
return buf.split("\n")
except Exception:
return None
#**************************************************************************
def writeLinesInFile(filename, lines):
'''write a list of lines to a file, ignore any errors'''
try:
with open(filename, 'w') as f:
f.write("\n".join(lines) + "\n")
except Exception:
pass
#**************************************************************************
def prettyXml(element):
'''fallback support for better code'''
return prettyXmlToString(element)
def prettyXmlToString(element):
'''
make nice-looking XML that is human-readable
@see http://stackoverflow.com/questions/749796/pretty-printing-xml-in-python
'''
txt = ElementTree.tostring(element)
dom = xml.dom.minidom.parseString(txt)
ugly = dom.toprettyxml()
#pretty = dom.toxml()
text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL)
pretty = text_re.sub('>\g<1></', ugly)
return "\n".join(removeBlankLines(pretty.split("\n")))
#**************************************************************************
def removeBlankLines(lines):
result = []
for line in lines:
if len(line.strip()) > 0:
result.append(line)
return result
#**************************************************************************
def writeXmlDocToFile(xmlFile, doc):
'''write the XML doc to a file'''
# splice in the reference to the XSLT at the top of the file (on line 2)
xsltRef = '<?xml-stylesheet type="text/xsl" href="scanlog.xsl" ?>'
lines = prettyXmlToString(doc.getroot()).split("\n")
lines.insert(1, xsltRef)
writeLinesInFile(xmlFile, lines)
return
#**************************************************************************
def appendTextNode(doc, parent, tag, value):
'''append a text node to the XML document'''
elem = ElementTree.Element(tag)
elem.text = value
parent.append(elem)
#**************************************************************************
def appendDateTimeNode(doc, parent, tag):
'''append a date/time node to the XML document'''
elem = ElementTree.Element(tag)
elem.set('date', xmlDate())
elem.set('time', xmlTime())
parent.append(elem)
#**************************************************************************
def xmlDate():
'''current date, for use in XML file (ISO8601)'''
txt = time.strftime('%Y-%m-%d') # XML date format
return txt
#**************************************************************************
def xmlTime():
'''current time, for use in XML file (ISO8601)'''
txt = time.strftime('%H:%M:%S') # XML time format
return txt
#**************************************************************************
def main():
''' test routine '''
if (len(sys.argv) == 2):
pwd = sys.argv[1]
else:
pwd = '.'
config = readConfigurationXML(os.path.join(pwd, 'pvlist.xml'))
if len(config) == 0:
logger.error("ERROR: could not read the configuration file")
return
doc = openScanLogFile(config['scanLogFile'])
root = doc.getroot()
scan = locateScanID(doc, '43:/share1/USAXS_data/2010-03/03_24_setup.dat')
scan.set("gotcha", "True")
print prettyXmlToString(scan)
appendTextNode(doc, root, "modifed.by", sys.argv[0])
appendDateTimeNode(doc, root, "timestamp")
#print prettyXml(root)
writeXmlDocToFile('test.xml', doc)
#**************************************************************************
if __name__ == "__main__":
main()