XML parsing with XSLT

2019-07-31 11:27发布

Hi I have the following XML code:

<?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>

And I have to get it in this format:

<?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>

There are 5 types/stages

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

All lines with Type="Movement" should be deleted and only after that the data should be transformed. The "Start" of every following Stage is going to be the "epoch_end" of the one before. For the last epoch the epoch_end should be 99999

How would a xsl stylesheet look like to do that?

1条回答
倾城 Initia
2楼-- · 2019-07-31 11:38

With XSLT 3's xsl:iterate you can pass on the previously processed item and then output it with the right start and end values, also taking care of the last item with 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

查看更多
登录 后发表回答