使用 XSLT 和 XSLT 1.0 (MSXML 6) 从 XML 输出的文本 [英] Text output from XML with XSLT with XSLT 1.0 (MSXML 6)

查看:25
本文介绍了使用 XSLT 和 XSLT 1.0 (MSXML 6) 从 XML 输出的文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个无法用 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>&#10;</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>&#10;</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>&#10;</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>&#10;</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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆