【问题标题】:How to parse xml data into different format?如何将xml数据解析成不同的格式?
【发布时间】:2019-02-23 16:23:20
【问题描述】:

我有以下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 以此类推,一个项目的“epoch_end”是下一个项目的“开始”。 纪元时间是可变的。

我将如何使用例如 python 解析 xml 数据? 有没有比使用 minidump 之类的东西更好的方法来完成工作? 适当的解析命令是什么样的? 感谢您的回复。

【问题讨论】:

    标签: python xml parsing xml-parsing


    【解决方案1】:

    这类工作的常用工具是 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>
    

    【讨论】:

    • 谢谢。如何仅用 NREM1 替换 Stage1,用 NREM2 替换 Stage2,用 NREM3 替换 Stage3?例如 Type="Wake" 应该保持 Wake 并且只有每个“Stage”应该被“NREM”替换
    • 我不会沉迷于为每个新的规范增量编写新的代码增量。如果您需要回答有关新 XSLT 问题的具体问题,请提出新问题。
    【解决方案2】:

    基于 xml.etree.ElementTree 的解决方案。可以在没有用于调试的 dicts 中间列表的情况下实现。

    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>
    

    【讨论】:

    • 感谢您的回复。你误解我了。我只想用 NREM1 替换 Stage1,用 NREM2 替换 Stage2,用 NREM3 替换 Stage3。而已。例如 Wake 应该保持 Wake 并且 REM 应该保持 REM 并且没有像 NREM4 及以上的东西。如果可能的话,我还想先删除数据中所有带有运动的行,然后再将其解析为新格式。
    猜你喜欢
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多