Может ли кто-нибудь помочь мне с незаконченной идеей?
Я не очень привык к xslt, но я пытаюсь, и благодаря большому количеству интернета мне помогают.
Но:
следующий сценарий я не могу решить:
Дан пример XML с некоторыми данными геологического слоя, выглядящими следующим образом:
<LAYERS>
<LAYER DEPTHTO = "1.00" PETRO = "Sand" STRAT = "geologiscal_formation_1" INTV = "1"/>
<LAYER DEPTHTO = "94.00" PETRO = "Sand" STRAT = "geologiscal_formation_1" INTV = "1"/>
<LAYER DEPTHTO = "94.20" INTV = "1" INDEX_ZONE = "-1" EGART = "Lost_Data"/>
<LAYER DEPTHTO = "95.00" PETRO = "Gravel" STRAT = "geologiscal_formation_1" INTV = "1"/>
<LAYER DEPTHTO = "100.00" PETRO = "Sand" STRAT = "geologiscal_formation_2" INTV = "1"/>
<LAYER DEPTHTO = "100.50" PETRO = "Mud" STRAT = "geologiscal_formation_2" INTV = "1"/>
<LAYER DEPTHTO = "101.50" PETRO = "Sand" STRAT = "geologiscal_formation_2" INTV = "1"/>
<LAYER DEPTHTO = "101.80" PETRO = "Mud" STRAT = "geologiscal_formation_2" INTV = "1"/>
<LAYER DEPTHTO = "102.90" PETRO = "Mud" STRAT = "geologiscal_formation_3" INTV = "1"/>
<LAYER DEPTHTO = "103.00" PETRO = "Sand" STRAT = "geologiscal_formation_3" INTV = "1"/>
<LAYER DEPTHTO = "103.25" INTV = "1" INDEX_ZONE = "-1" EGART = "Lost_Data"/>
<LAYER DEPTHTO = "103.69" PETRO = "Sand" STRAT = "geologiscal_formation_3" INTV = "1"/>
<LAYER DEPTHTO = "104.00" PETRO = "Mud" STRAT = "geologiscal_formation_3" INTV = "1"/>
</LAYERS>
и используя следующий код xslt:
<?xml version = "1.0" encoding = "utf-8"?>
<xsl:stylesheet version = "1.0"
xmlns:xml = "http://www.w3.org/XML/1998/namespace"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes = " xml xsl xs">
<xsl:output method = "text" version = "1.0" indent = "yes" />
<xsl:key name = "adj" match = "LAYER" use = "generate-id(preceding-sibling::LAYER[not(@STRAT = current()/@STRAT)][1])" />
<xsl:template match = "/*">
<xsl:for-each select = "LAYER[generate-id() = generate-id(key('adj', generate-id(preceding-sibling::LAYER[not(@STRAT = current()/@STRAT)][1]))[1])]">
<xsl:variable name = "INTVID" select = "@INTV"/>
<xsl:variable name = "precedingZone" select = "preceding-sibling::LAYER[@INTV = $INTVID][1]"/>
<xsl:variable name = "DEPTHFROM" select = "$precedingZone/@DEPTHTO"/>
<xsl:if test = "@STRAT != ''">
<xsl:variable name = "current-group" select = "key('adj', generate-id(preceding-sibling::LAYER[not(@STRAT = current()/@STRAT)][1]))" />
<xsl:text>ZONE "</xsl:text>
<xsl:value-of select = "@STRAT"/>
<xsl:text>" </xsl:text>
<xsl:for-each select = "$current-group">
<xsl:sort select = "$DEPTHFROM" data-type = "number" order = "ascending"/>
<xsl:if test = "position() = 1 ">
<xsl:value-of select = "$DEPTHFROM"/>
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:for-each select = "$current-group">
<xsl:sort select = "@DEPTHTO" data-type = "number" order = "descending"/>
<xsl:if test = "position() = 1 ">
<xsl:value-of select = "@DEPTHTO"/>
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:value-of select = "@INDEX_ZONE"/>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
результат выглядит так:
ZONE "geologiscal_formation_1" 94.00
ZONE "geologiscal_formation_1" 94.20 95.00
ZONE "geologiscal_formation_2" 95.00 101.80
ZONE "geologiscal_formation_3" 101.80 103.00
ZONE "geologiscal_formation_3" 103.25 104.00
Но желаемый результат должен выглядеть так:
ZONE "geologiscal_formation_1" 0.00 95.00
ZONE "geologiscal_formation_2" 95.00 101.80
ZONE "geologiscal_formation_3" 101.80 104.00
Дополнительная справочная информация: Поскольку первая строка дает только данные DEPTHTO, я предполагаю, что она начинается с 0, так как давно неизвестно. Группировка работает только частично, т.к. мы получили несколько слоев с "lost_data", что приводит всю задумку к плохому результату.
Поэтому мне нужно какое-то условие, которое игнорирует/пропускает данные, где найдено «потерянные_данные». Но поскольку я использую «для каждого», я не знаю, как это сделать. Я слышал о какой-то «конвейерной обработке», но особо в нее не вникал, так как уже перегружен тем, что получил.
Может кто знает лучше?
И да, я застрял на xslt 1.0 :)
Спасибо за любые идеи или помощь.
Благодаря ответу и с некоторыми незначительными изменениями я смог достичь своей цели:
изменения выглядят так:
<?xml version = "1.0" encoding = "utf-8"?>
<xsl:stylesheet version = "1.0"
xmlns:xml = "http://www.w3.org/XML/1998/namespace"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes = " xml xsl xs">
<xsl:output method = "text" version = "1.0" indent = "yes" />
<xsl:key name = "layer-by-strat" match = "LAYER" use = "@STRAT" />
<xsl:template match = "/*">
<xsl:for-each select = "LAYER[not(@EGART='Lost_Data')][count(. | key('layer-by-strat', @STRAT)[1]) = 1]">
<xsl:variable name = "INTVID" select = "@INTV"/>
<xsl:variable name = "precedingZone" select = "preceding-sibling::LAYER[@INTV = $INTVID][1]"/>
<xsl:variable name = "DEPTHFROM" select = "$precedingZone/@DEPTHTO"/>
<xsl:choose>
<xsl:when test = "$precedingZone">
<xsl:text>ZONE "</xsl:text>
<xsl:value-of select = "@STRAT" />
<xsl:text>" </xsl:text>
<xsl:value-of select = "$DEPTHFROM"/>
<xsl:text> </xsl:text>
<xsl:value-of select = "key('layer-by-strat', @STRAT)[last()]/@DEPTHTO" />
<xsl:text> </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>ZONE "</xsl:text>
<xsl:value-of select = "@STRAT" />
<xsl:text>" 0.00 </xsl:text>
<xsl:value-of select = "key('layer-by-strat', @STRAT)[last()]/@DEPTHTO" />
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Итак, вам просто нужны минимум и максимум из @DEPTHTO
, где @STRAT
имеет значение, а минимум всегда равен 0,0?
Эй, ты, совершенно верно, пример не был хорошим. Я отредактировал его и надеюсь, что теперь стало более понятно, что я имею в виду.
Результат, который вы показываете, может быть получен довольно легко, используя:
XSLT 1.0
<xsl:stylesheet version = "1.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text" encoding = "UTF-8"/>
<xsl:key name = "layer-by-strat" match = "LAYER" use = "@STRAT" />
<xsl:template match = "LAYERS" >
<xsl:for-each select = "LAYER[not(@EGART='Lost_Data')][count(. | key('layer-by-strat', @STRAT)[1]) = 1]">
<xsl:text>ZONE "</xsl:text>
<xsl:value-of select = "@STRAT" />
<xsl:text>" 0.00 </xsl:text>
<xsl:value-of select = "key('layer-by-strat', @STRAT)[last()]/@DEPTHTO" />
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Предполагается, что последний LAYER
в каждой группе имеет желаемое максимальное значение, в противном случае потребуется небольшая корректировка.
Я заметил, что пропустил часть требования, где каждый слой начинается на максимальной глубине предыдущего. Вот скорректированная таблица стилей:
<xsl:stylesheet version = "1.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text" encoding = "UTF-8"/>
<xsl:key name = "layer-by-strat" match = "LAYER" use = "@STRAT" />
<xsl:template match = "LAYERS" >
<xsl:call-template name = "generate-rows">
<xsl:with-param name = "layers" select = "LAYER[not(@EGART='Lost_Data')][count(. | key('layer-by-strat', @STRAT)[1]) = 1]"/>
</xsl:call-template>
</xsl:template>
<xsl:template name = "generate-rows">
<xsl:param name = "layers" select = "/.."/>
<xsl:param name = "accumulated-depth" select = "'0.00'"/>
<xsl:if test = "$layers">
<xsl:variable name = "strat" select = "$layers[1]/@STRAT" />
<xsl:variable name = "max-depth" select = "key('layer-by-strat', $strat)[last()]/@DEPTHTO" />
<!-- output -->
<xsl:text>ZONE "</xsl:text>
<xsl:value-of select = "$strat" />
<xsl:text>" </xsl:text>
<xsl:value-of select = "$accumulated-depth" />
<xsl:text> </xsl:text>
<xsl:value-of select = "$max-depth" />
<xsl:text> </xsl:text>
<!-- recursive call -->
<xsl:call-template name = "generate-rows">
<xsl:with-param name = "layers" select = "$layers[position() > 1]"/>
<xsl:with-param name = "accumulated-depth" select = "$max-depth"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Эй, спасибо, с небольшими изменениями я смог добиться результата :)
Я добавил скорректированную версию, которая, как мне кажется, обрабатывает необходимые изменения.
Эй, кажется, я забыл об атрибуте INTV. Как я могу сгенерировать ключ, используя @STRAT только там, где INTV = 1? В моем примере все INTV =1, но в наборе данных это не так :/
Я полагаю, вы хотите добавить еще один предикат @INTV=1
к параметру $layers
- и, возможно, также к определению ключа (боюсь, я не вижу всей картины).
Поскольку ваш ответ действительно решил мой вопрос, я задам новый вопрос с новым сценарием :) это странные вещи, которые я получил здесь
Я не следую логике, которую вы хотите применить здесь. Разве желаемый результат не просто от 0 до последнего (или максимального) значения
DEPTHTO
(возможно, сгруппированного поSTRAT
)?