使用XSLT进行XML解析

时间:2019-02-24 09:09:38

标签: xml parsing xslt xml-parsing

嗨,我有以下XML代码:

<?xml version="1.0" encoding="utf-8"?>
<UserStaging>
            <NeuroRKStaging>
               <Stage Type="REM" Start="0" />
               <Stage Type="Stage3" Start="150" />
               <Stage Type="Movement" Start="3030" />
               <Stage Type="Wake" Start="3150" />
               <Stage Type="Stage2" Start="4680" />
               <Stage Type="Stage3" Start="5340" />
               <Stage Type="Movement" Start="6090" />
               <Stage Type="Wake" Start="6480" />
               <Stage Type="Stage1" Start="9330" />
               <Stage Type="Stage3" Start="10290" />
            </NeuroRKStaging>
</UserStaging>

我必须以这种格式获取它:

<?xml version="1.0" encoding="utf-8"?>
<stages>
    <epoch><epoch_start>0</epoch_start><epoch_end>150</epoch_end><stage>REM</stage></epoch>   
    <epoch><epoch_start>150</epoch_start><epoch_end>3150</epoch_end><stage>NREM3</stage></epoch>
    <epoch><epoch_start>3150</epoch_start><epoch_end>4680</epoch_end><stage>Wake</stage></epoch>
    <epoch><epoch_start>4680</epoch_start><epoch_end>5340</epoch_end><stage>NREM2</stage></epoch>
    <epoch><epoch_start>5340</epoch_start><epoch_end>6480</epoch_end><stage>NREM3</stage></epoch>
    <epoch><epoch_start>6480</epoch_start><epoch_end>9330</epoch_end><stage>Wake</stage></epoch>
    <epoch><epoch_start>9330</epoch_start><epoch_end>10290</epoch_end><stage>NREM1</stage></epoch>
    <epoch><epoch_start>10290</epoch_start><epoch_end>99999</epoch_end><stage>NREM3</stage></epoch>
</stages>

有5种类型/阶段

Stage1 transforms to NREM1
Stage2 transforms to NREM2
Stage3 transforms to NREM3
REM remains REM
Wake remains Wake

所有具有Type =“ Movement”的行都应删除,只有在此之后才对数据进行转换。 接下来的每个阶段的“开始”将是之前一个阶段的“ epoch_end”。对于最后一个纪元,epoch_end应该为99999

xsl样式表如何做到这一点?

1 个答案:

答案 0 :(得分:1)

使用XSLT 3的xsl:iterate,您可以传递先前处理过的项目,然后以正确的开始和结束值输​​出它,还可以使用xsl:on-completion处理最后一个项目:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

  <xsl:param name="default-end" as="xs:integer" select="99999"/>

  <xsl:param name="type-map" as="map(xs:string, xs:string)"
    select="map { 'Stage1' : 'NREM1', 'Stage2' : 'NREM2', 'Stage3' : 'NREM3' }"/>

  <xsl:output indent="yes"/>

  <xsl:template match="NeuroRKStaging">
      <stages>
          <xsl:iterate select="Stage[not(@Type = 'Movement')]">
              <xsl:param name="previous" as="element()?" select="()"/>
              <xsl:on-completion>
                  <xsl:if test="$previous">
                      <epoch>
                      <epoch_start>{$previous/@Start}</epoch_start>
                      <epoch_end>{$default-end}</epoch_end>
                      <xsl:apply-templates select="$previous/@Type"/>
                  </epoch>
                  </xsl:if>
              </xsl:on-completion>
              <xsl:if test="$previous">
                  <epoch>
                      <epoch_start>{$previous/@Start}</epoch_start>
                      <epoch_end>{@Start}</epoch_end>
                      <xsl:apply-templates select="$previous/@Type"/>
                  </epoch>
              </xsl:if>
              <xsl:next-iteration>
                  <xsl:with-param name="previous" select="."/>
              </xsl:next-iteration>
          </xsl:iterate>
      </stages>
  </xsl:template>

  <xsl:template match="Stage/@Type">
      <stage>{.}</stage>
  </xsl:template>

  <xsl:template match="Stage/@Type[map:contains($type-map, .)]">
      <stage>{$type-map(.)}</stage>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFN1y8Z/1