I am trying to load an XML file that will be used to configure my DAQ in LabVIEW.
So when looking at the options I have:
e.g. for XML channel
<Channels>
<Channel name="CH_PH1" enable="True" visible="False" virtual="False" units="A" physical_channel="PXI1Slot2/ai0" b_factor="0" m_factor="1033.221069" measurement_type="VOLTAGE" type="D" max_value="0.1" min_value="-0.1">
<RollingAvg do_rolling_avg="False" rolling_avg_frame_sec="0" />
</Channel>
<Channel name="CH_PH2" enable="True" visible="False" virtual="False" units="A" physical_channel="PXI1Slot2/ai1" b_factor="0" m_factor="1073.772766" measurement_type="VOLTAGE" type="D" max_value="0.1" min_value="-0.1">
<RollingAvg do_rolling_avg="False" rolling_avg_frame_sec="0" />
</Channel>
<Channel name="P_CH" enable="True" visible="False" virtual="True" units="V" formula="CH_PH1*CH_PH2" doTotalEnergy="False">
<RollingAvg do_rolling_avg="False" rolling_avg_frame_sec="0" />
</Channel>
<Channel name="P_PH_Total" enable="True" visible="False" virtual="True" units="V" formula="CH_PH1+CH_PH2" doTotalEnergy="False">
<RollingAvg do_rolling_avg="False" rolling_avg_frame_sec="0" />
</Channel>
</Channels>
My code in Python to parse the xml:
def xml():
import xml.etree.ElementTree as ET
tree = ET.parse(r'C:\Users\LAB_PTG\Desktop\Cosmo_v0.93.6\nidaq.xml')
root = tree.getroot()
P={}
C={}
for Channel in root.iter('Channel'):
z=(Channel.attrib)
if z['virtual']=='False':
P.update({z['name']:(z['physical_channel'],z['enable'],z['m_factor'],z['max_value'])})
else:
C.update({z['name']:(z['formula'])})
print(P,C)
Help needed:
I didn't manage creating a xml parser in LabVIEW as it enforces more hard coding and having a fixed stricture.
I am targeting the LV DAQmx continues sampling example and replace the configuration with the parsed xml.
Thanks for every one supporting Assaf Baker
Parsing XML in LV is a bit tricky, but not that difficult. Maybe, you give it a try?
This code loops over all channels, extracts attributes name
and virtual
, and from their children RollingAvg
, it extracts the attribute do_rolling_avg
.
May be, it is more handy to get a list of all attributes / values of a node first, and then work on the generated array:
Now, it is important to close all references at the end to avoid a memory leak, which is done quick and dirty, here.
Further more, if something is not found, the search VIs will throw an error. (Your Python will do so, too). Some error handling should be added if necessary.
Today, there's an option to run Python directly from LV. I don't know this, my LV is from 2017.
There, it is possible to use the System Exec.vi
to run any command on the commandline, and read its output back into LV:
Finally, what Python prints, will be returned as string. I'd work with JSON, which easily converts a dict to JSON:
import json
a=[]
a.append({'name':'CH_PH1', 'virtual':False, 'RollingAvgFrame':3.141})
a.append({'name':'CH_PH2', 'virtual':True, 'RollingAvgFrame':42.0})
print(json.dumps(a))
Output:
[{"name": "CH_PH1", "virtual": false, "RollingAvgFrame": 3.141},
{"name": "CH_PH2", "virtual": true, "RollingAvgFrame": 42.0}]
In LV, define a cluster according to the JSON structure, and use the Unflatten from JSON
VI to fill it. The names of the cluster elements must match those in the JSON code.
However, JSON knows only simple data types. There is no way to transfer time or any other more complex datatype, unless it can be packed as something more simple like a string containing a timestamp.