Привет, у меня есть следующий 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?
Я могу использовать версию 3





С 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
В порядке. Большое Вам спасибо. Не могли бы вы отредактировать свой код, чтобы включить <quality>Good</quality> в каждую эпоху? Как бы я это сделал?
У вас есть пример, содержащий буквенные элементы результата (например, epoch или epoch_start) в коде XSLT, так что теперь вы должны начать экспериментировать самостоятельно, добавление дополнительного литерального элемента результата должно быть чем-то, что вы можете понять, это не сложнее, чем печатать это в комментарии, который вы написали, так что попробуйте. Если вам действительно не удается этого добиться, опубликуйте новый вопрос с подробностями того, что вы пытались и как это не удалось.
Итак, какой процессор XSLT вы используете, какую версию XSLT вы можете использовать? Возможно, это хорошая работа для XSLT 3
xsl:iterate select = "Stage[not(@Type = 'Movement')]", но если мы пожертвуем вам код бесплатно, вы должны хотя бы сообщить нам, какую версию XSLT вы можете использовать.