Как разобрать данные XML в другой формат? - PullRequest
0 голосов
/ 23 февраля 2019

У меня есть следующие данные в формате xml.

 <UserStaging>
    <Staging>
      <Stage Type="Stage1" Start="0" />
      <Stage Type="Stage2" Start="50"/>
      <Stage Type="Stage3" Start="100" />
    </Staging>
 </UserStaging>

И я должен получить их в этом формате:

<epoch><epoch_start>0</epoch_start<epoch_end>50</epoch_end><stage>NREM1</stage></epoch>   
<epoch><epoch_start>50</epoch_start<epoch_end>100</epoch_end<stage>NREM2</stage></epoch>
<epoch><epoch_start>100</epoch_start<epoch_end>9999</epoch_end<stage>NREM3</stage></epoch>

Где Stage1 это NREM1, Stage2 это NREM2 и такon, а "epoch_end" элемента - это "Start" следующего элемента.Время эпохи является переменным.

Как бы я проанализировал данные xml, например, с python?Есть ли лучший способ, чем использовать что-то вроде минидампа, чтобы сделать работу?Как будут выглядеть соответствующие команды синтаксического анализа?Спасибо за любой ответ.

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

xml.etree.ElementTree основанное решение.Может быть реализовано без промежуточного списка диктов, который используется для отладки.

import xml.etree.ElementTree as ET

data = '''<UserStaging>
    <Staging>
      <Stage Type="Stage1" Start="0" />
      <Stage Type="Stage2" Start="50"/>
      <Stage Type="Stage3" Start="100" />
    </Staging>
 </UserStaging>'''

tree = ET.fromstring(data)
new_data = []
start = 0
for idx, stage in enumerate(tree.iter('Stage')):
    new_data.append({'start': stage.attrib['Start'],
                     'stage': 'NREM{}'.format(idx + 1)})
    if idx > 0:
        new_data[idx - 1]['end'] = stage.attrib['Start']

root = ET.Element("UserStaging")
for idx, entry in enumerate(new_data):
    epoch = ET.SubElement(root, "epoch")
    start = ET.SubElement(epoch, "epoch_start").text = entry['start']
    end = ET.SubElement(epoch, "epoch_end").text = entry['end'] if idx < len(new_data) - 1 else '9999'
    stage = ET.SubElement(epoch, "stage").text = entry['stage']

ET.dump(root)

Вывод:

<UserStaging>
   <epoch>
      <epoch_start>0</epoch_start>
      <epoch_end>50</epoch_end>
      <stage>NREM1</stage>
   </epoch>
   <epoch>
      <epoch_start>50</epoch_start>
      <epoch_end>100</epoch_end>
      <stage>NREM2</stage>
   </epoch>
   <epoch>
      <epoch_start>100</epoch_start>
      <epoch_end>9999</epoch_end>
      <stage>NREM3</stage>
   </epoch>
</UserStaging>
0 голосов
/ 23 февраля 2019

Обычным инструментом для такого рода работ является XSLT.В этом случае работа легко выполняется с использованием XSLT 1.0, который легко доступен для Python:

<xsl:stylesheet...

<xsl:template match="Stage">
  <epoch>
    <epoch_start>
      <xsl:value-of select="@Start"/>
    </epoch_start>
    <epoch_end>
      <xsl:variable name="next" select="following-sibling::*[1]"/>
      <xsl:choose>
         <xsl:when test="$next">
           <xsl:value-of select="$next/@Start"/>
         <xsl:when>
         <xsl:otherwise>9999</xsl:otherwise>
      </xsl:choose>
    </epoch_end>
    <stage>NREM<xsl:number/></stage>
  </epoch>
</xsl:template>

</xsl:stylesheet>
...