使用 XSLT 和 XSLT 1.0 (MSXML 6) 从 XML 输出的文本 [英] Text output from XML with XSLT with XSLT 1.0 (MSXML 6)
问题描述
我有一个无法用 xslt 1.0 解决的问题.已经给出了 XSLT 2.0 的解决方案并且工作正常(见下文).
对于按 STRAT_ZONE 分组的每个图层,需要来自 DEPTHFROM_ZONE 的最小值和最大值 DEPTHTO_ZONE.
按 STRAT_ZONE 分组似乎不是一个选项,因为该属性可以重复.逐行检查是一个想法.
有没有人有任何提示,如何尝试达到预期的目标?
数据块:
<ZONE STRAT_ZONE=Flysand 被解开";DEPTHFROM_ZONE=0.00";DEPTHTO_ZONE=0.30"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Flysand 被解开";DEPTHFROM_ZONE=0.30"DEPTHTO_ZONE=1.10"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Flysand 被解开";DEPTHFROM_ZONE=1.10"DEPTHTO_ZONE=1.40"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Flysand 被解开";DEPTHFROM_ZONE=1.40"DEPTHTO_ZONE=1.70"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=1.70"DEPTHTO_ZONE=1.80";INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=1.80"DEPTHTO_ZONE=2.20"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=2.20"DEPTHTO_ZONE=2.60"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Flysand 被解开";DEPTHFROM_ZONE=2.60"DEPTHTO_ZONE=2.80"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Flysand 被解开";DEPTHFROM_ZONE=2.80"DEPTHTO_ZONE=2.90"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=2.90"DEPTHTO_ZONE=3.10"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=3.10"DEPTHTO_ZONE=3.40"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=3.40"DEPTHTO_ZONE=3.70"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=3.70"DEPTHTO_ZONE=4.50"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=流沙"DEPTHFROM_ZONE=4.50"DEPTHTO_ZONE=4.90"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Vulcanic"DEPTHFROM_ZONE=4.90"DEPTHTO_ZONE=6.00";INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Vulcanic"DEPTHFROM_ZONE=6.00"DEPTHTO_ZONE=6.20"INDEX_ZONE=-1"/><ZONE STRAT_ZONE=Vulcanic"DEPTHFROM_ZONE=6.20"DEPTHTO_ZONE=6.30"INDEX_ZONE=-1"/></区域>
所需的输出:
ZONEFlysand unchained"0.00 1.70 -1ZONE流沙"1.70 2.60 -1ZONEFlysand unchained"2.60 2.90 -1ZONE流沙"2.90 4.90 -1区域Vulcanic"4.90 6.30 -1
2.0 版解决方案看起来像这样(感谢 Martin Honnen):
<预><代码><xsl:template match="ZONES"><xsl:for-each-group select="ZONE";组相邻=@STRAT_ZONE"><xsl:value-ofselect="'ZONE', current-grouping-key(), min(current-group()/@DEPTHFROM_ZONE), max(current-group()/@DEPTHTO_ZONE), @INDEX_ZONE"/><xsl:text> </xsl:text></xsl:for-each-group></xsl:模板>但是如何使用 MSXML 6 处理器在 XSLT 1.0 中实现相同的结果?
非常感谢您的帮助.
在 XSLT 1.0 中有几种方法可以实现 group-adjacent
.我相信在您的情况下使用最方便的方法是:
XSLT 1.0
<xsl:output method="text"编码=UTF-8"/><xsl:key name="adj";匹配=区域"use="generate-id(preceding-sibling::ZONE[not(@STRAT_ZONE = current()/@STRAT_ZONE)][1])";/><xsl:template match="/ZONES"><xsl:for-each select="ZONE[generate-id() = generate-id(key('adj', generate-id(preceding-sibling::ZONE[not(@STRAT_ZONE = current()/@STRAT_ZONE)][1]))[1])]"><xsl:variable name="current-group";select=key('adj', generate-id(preceding-sibling::ZONE[not(@STRAT_ZONE = current()/@STRAT_ZONE)][1]))";/><xsl:text>ZONE "</xsl:text><xsl:value-of select="@STRAT_ZONE"/><xsl:text>"</xsl:text><xsl:for-each select="$current-group"><xsl:sort select="@DEPTHFROM_ZONE";数据类型=数字"order=升序"/><xsl:if test=position() = 1"><xsl:value-of select="@DEPTHFROM_ZONE"/></xsl:if></xsl:for-each><xsl:text></xsl:text><xsl:for-each select="$current-group"><xsl:sort select="@DEPTHTO_ZONE";数据类型=数字"order=降序"/><xsl:if test=position() = 1"><xsl:value-of select="@DEPTHTO_ZONE"/></xsl:if></xsl:for-each><xsl:text></xsl:text><xsl:value-of select="@INDEX_ZONE"/><xsl:text> </xsl:text></xsl:for-each></xsl:模板></xsl:stylesheet>
这通过值与当前节点不同的第一个在前兄弟节点的 id
对节点进行分组 - 并且此 id
对所有具有相同值的相邻节点是通用的价值.
I have a problem I cannot solve with xslt 1.0. A solution for XSLT 2.0 was already given and works fine (see further below).
For each layer grouped by STRAT_ZONE the minimal values from DEPTHFROM_ZONE and maximum value DEPTHTO_ZONE are needed.
Grouping by STRAT_ZONE seems not an option, because the attribute can repeat itself. A checkup line by line was an idea.
Does anyone have any tips, how to try reach the desired goal?
Datablock:
<ZONES>
<ZONE STRAT_ZONE="Flysand unchained" DEPTHFROM_ZONE="0.00" DEPTHTO_ZONE="0.30" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Flysand unchained" DEPTHFROM_ZONE="0.30" DEPTHTO_ZONE="1.10" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Flysand unchained" DEPTHFROM_ZONE="1.10" DEPTHTO_ZONE="1.40" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Flysand unchained" DEPTHFROM_ZONE="1.40" DEPTHTO_ZONE="1.70" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="1.70" DEPTHTO_ZONE="1.80" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="1.80" DEPTHTO_ZONE="2.20" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="2.20" DEPTHTO_ZONE="2.60" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Flysand unchained" DEPTHFROM_ZONE="2.60" DEPTHTO_ZONE="2.80" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Flysand unchained" DEPTHFROM_ZONE="2.80" DEPTHTO_ZONE="2.90" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="2.90" DEPTHTO_ZONE="3.10" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="3.10" DEPTHTO_ZONE="3.40" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="3.40" DEPTHTO_ZONE="3.70" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="3.70" DEPTHTO_ZONE="4.50" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Drifting sand" DEPTHFROM_ZONE="4.50" DEPTHTO_ZONE="4.90" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Vulcanic" DEPTHFROM_ZONE="4.90" DEPTHTO_ZONE="6.00" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Vulcanic" DEPTHFROM_ZONE="6.00" DEPTHTO_ZONE="6.20" INDEX_ZONE="-1"/>
<ZONE STRAT_ZONE="Vulcanic" DEPTHFROM_ZONE="6.20" DEPTHTO_ZONE="6.30" INDEX_ZONE="-1"/>
</ZONES>
Desired output:
ZONE "Flysand unchained" 0.00 1.70 -1
ZONE "Drifting sand" 1.70 2.60 -1
ZONE "Flysand unchained" 2.60 2.90 -1
ZONE "Drifting sand" 2.90 4.90 -1
ZONE "Vulcanic" 4.90 6.30 -1
A Version 2.0 solution looks like that (Thanks Martin Honnen):
<xsl:template match="ZONES">
<xsl:for-each-group select="ZONE" group-adjacent="@STRAT_ZONE">
<xsl:value-of
select="'ZONE', current-grouping-key(), min(current-group()/@DEPTHFROM_ZONE), max(current-group()/@DEPTHTO_ZONE), @INDEX_ZONE"/>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:template>
But how to realize the same result in XSLT 1.0 using MSXML 6 processor?
Thank you very much for any help.
There are several methods to implement group-adjacent
in XSLT 1.0. I believe the most convenient one to use in your case would be this:
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="adj" match="ZONE" use="generate-id(preceding-sibling::ZONE[not(@STRAT_ZONE = current()/@STRAT_ZONE)][1])" />
<xsl:template match="/ZONES">
<xsl:for-each select="ZONE[generate-id() = generate-id(key('adj', generate-id(preceding-sibling::ZONE[not(@STRAT_ZONE = current()/@STRAT_ZONE)][1]))[1])]">
<xsl:variable name="current-group" select="key('adj', generate-id(preceding-sibling::ZONE[not(@STRAT_ZONE = current()/@STRAT_ZONE)][1]))" />
<xsl:text>ZONE "</xsl:text>
<xsl:value-of select="@STRAT_ZONE"/>
<xsl:text>" </xsl:text>
<xsl:for-each select="$current-group">
<xsl:sort select="@DEPTHFROM_ZONE" data-type="number" order="ascending"/>
<xsl:if test="position() = 1 ">
<xsl:value-of select="@DEPTHFROM_ZONE"/>
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:for-each select="$current-group">
<xsl:sort select="@DEPTHTO_ZONE" data-type="number" order="descending"/>
<xsl:if test="position() = 1 ">
<xsl:value-of select="@DEPTHTO_ZONE"/>
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:value-of select="@INDEX_ZONE"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This groups the nodes by the id
of the first preceding sibling whose value is different from the current node - and this id
is common to all adjacent nodes with the same value.
这篇关于使用 XSLT 和 XSLT 1.0 (MSXML 6) 从 XML 输出的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!