Вот формат примера узла xml, с которого я анализирую данные:
<!-- /StationName/BACnetTemp/MNB_1_HX/HiPressureAlarm -->
<node name="HiPressureAlarm" class="tridium.control.BinaryInputNode" module="coreRuntime" release="2.301.535.v1">
<properties>
<position><x>576</x><y>866</y></position>
<timeDelay>
<duration>60</duration>
</timeDelay>
<eventEnable>
<toOffnormal>true</toOffnormal>
<toFault>false</toFault>
<toNormal>true</toNormal>
</eventEnable>
<alarmText>MCD Basement Re-Heat High Pressure Alarm</alarmText>
<changeOfStateTime>2018-05-07T08:55:04.09-4</changeOfStateTime>
<changeOfStateCount>848</changeOfStateCount>
<elapsedActiveTime>
<duration>126872</duration>
</elapsedActiveTime>
<activeInactiveText>
<active>Alarm</active>
<inactive>Normal</inactive>
</activeInactiveText>
<alarmValueEnabled>true</alarmValueEnabled>
</properties>
</node> <!-- HiPressureAlarm -->
Комментарий в начале - это путь к точке, из которой я пытаюсь экспортировать некоторые данные в файл Excel. У меня все остальное работает, кроме возможности связать путь с узлом, с которого я извлекаю данные.
Я могу поместить все комментарии в список, используя следующий код:
comments=soup.findAll(text=lambda text:isinstance(text, Comment))
Затем я попробовал следующее, чтобы найти комментарий и связать его с путем:
for comment in comments:
x='/'+nodeName
if x in comment:
nodePath = comment
Проблема в том, что есть несколько узлов с одинаковыми именами с разными путями, поэтому он давал мне одинаковый путь для каждого узла. Поэтому сразу после цикла for я добавил следующий код:
if nodePath in comments:
comments.remove(nodePath)
Это должно было сработать, но следующая проблема в том, что в xml есть несколько экземпляров одного и того же комментария, и порядок не соответствует порядку, в котором он находит узел и его данные, поэтому пути не совпадать с правильным узлом.
Есть ли способ найти узел и затем присвоить комментарий перед ним переменной, чтобы затем проанализировать в Excel?
Вот мой полный код, который анализирует данные:
def alarms(self,soup):
alarms=soup.find_all('toOffnormal')
comments=soup.findAll(text=lambda text:isinstance(text, Comment))
nodeStartList=[]
for alarm in alarms:
nodeStart=alarm.parent.parent.parent
nodeStartList.append(nodeStart)
dataList=[]
for item in nodeStartList:
nodeName=item['name']
for comment in comments:
x='/'+nodeName
if x in comment:
nodePath = comment
if nodePath in comments:
comments.remove(nodePath)
if item.find('timeDelay')!= None:
timeDelay=item.find('timeDelay').get_text("|", strip=True)
else:
timeDelay='0'
if item.find('eventEnable')!=None:
toOffnormal=item.find('toOffnormal').get_text("| ", strip=True)
toFault=item.find('toFault').get_text("| ", strip=True)
toNormal=item.find('toNormal').get_text("| ", strip=True)
else:
toOffnormal='false'
toFault='false'
toNormal='false'
alarmText=item.find('alarmText').get_text("| ", strip=True)
if item.find('highLimit')!= None:
highLimit=item.find('highLimit').get_text("| ", strip=True)
else:
highLimit='N/A'
if item.find('lowLimit')!= None:
lowLimit=item.find('lowLimit').get_text("| ", strip=True)
else:
lowLimit='N/A'
if item.find('deadband'):
deadband=item.find('deadband').get_text("| ", strip=True)
else:
deadband='N/A'
if item.find('lowLimitEnabled'):
lowLimitEnabled=item.find('lowLimitEnabled').get_text("| ", strip=True)
else:
lowLimitEnabled='false'
if item.find('highLimitEnabled'):
highLimitEnabled=item.find('highLimitEnabled').get_text("| ", strip=True)
else:
highLimitEnabled='false'
itemList=[nodeName,nodePath,timeDelay,toOffnormal,toFault,toNormal,alarmText,highLimit,lowLimit,deadband,lowLimitEnabled,highLimitEnabled]
dataList.append(itemList)
self.df=pandas.DataFrame(dataList)
self.df.columns=['pointName','pointPath','timeDelay','toOffnormal','toFault','toNormal','alarmText','highLimit','lowLimit','deadband','lowLimitEnabled','highLimitEnabled']
return self.df