XSLT 从特定组的节点 'above' 读取属性?

XSLT read attribute from node 'above' of specific group?

有没有办法根据之前节点的其他属性来定义属性? (请原谅我的术语,我不经常使用 xslt)。

我得到了一些土层数据,其中包含土层的终止深度。 需要的是特定组的一层的开始深度(顶部)。

我的第一个尝试是给组的第一层 top = 0。 下一层得到上一层的“DEPTHFROM”= DEPTHTO。

也许一个例子会清楚一点:

一个 XML 看起来像这样的数据块(一些土壤层):

<ZONES>
    
<ZONE LAYER_DESC="Flysand unchained" DEPTHTO="0.30" GROUP="1"/>
<ZONE LAYER_DESC="Flysand unchained" DEPTHTO="1.10" GROUP="1"/>
<ZONE LAYER_DESC="Flysand unchained" DEPTHTO="1.40" GROUP="1"/>
<ZONE LAYER_DESC="Flysand unchained" DEPTHTO="1.70" GROUP="1"/>
<ZONE LAYER_DESC="Drifting sand" DEPTHTO="1.80" GROUP="1"/>
<ZONE LAYER_DESC="Drifting sand" DEPTHTO="2.20" GROUP="1"/>
<ZONE LAYER_DESC="Drifting sand" DEPTHTO="2.60" GROUP="1"/>
<ZONE LAYER_DESC="Sand unchained" DEPTHTO="0.30" GROUP="2"/>
<ZONE LAYER_DESC="Sand unchained" DEPTHTO="1.10" GROUP="2"/>
<ZONE LAYER_DESC="Sand unchained" DEPTHTO="1.40" GROUP="2"/>
<ZONE LAYER_DESC="Sand unchained" DEPTHTO="1.70" GROUP="2"/>
<ZONE LAYER_DESC="fine sand" DEPTHTO="1.80" GROUP="2"/>
<ZONE LAYER_DESC="fine sand" DEPTHTO="2.20" GROUP="2"/>
<ZONE LAYER_DESC="fine sand" DEPTHTO="2.60" GROUP="2"/>

</ZONES>

使用 xslt(坚持使用 xslt 1.0 引擎)所需的文本输出可能如下所示:

(LAYER_DESC, 'DEPTHFROM'-> calculated from DEPTHTO from node above of specific layer group), quotes are not required


"Flysand unchained" "0.00"
"Flysand unchained" "0.30" 
"Flysand unchained" "1.10" 
"Flysand unchained" "1.40" 
"Drifting sand" "1.70" 
"Drifting sand" "1.80" 
"Drifting sand" "2.20" 
"Sand unchained" "0.00"
"Sand unchained" "0.30"
"Sand unchained" "1.10"
"Sand unchained" "1.40"
"fine sand" "1.80"
"fine sand" "2.20"

我更习惯于数据库操作,在那里我可能会使用一些行计数器来完成该任务,在那里不会很疯狂。

亲切的问候和感谢每一个想法,我会继续寻找。

XSLT 1.0

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:output method="text" encoding="utf-8"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="ZONE">        
        <xsl:value-of select="@LAYER_DESC"/>
        <xsl:text> </xsl:text>        
        <xsl:variable name="groupId" select="@GROUP"/>
        <xsl:variable name="precedingZone" select="preceding-sibling::ZONE[@GROUP = $groupId][1]"/>        
        <xsl:choose>
            <xsl:when test="$precedingZone">
                <xsl:value-of select="$precedingZone/@DEPTHTO"/>
            </xsl:when>
            <xsl:otherwise>0.00</xsl:otherwise>
        </xsl:choose>
        <xsl:text>            
</xsl:text>
    </xsl:template>
</xsl:stylesheet>

输出

Flysand unchained 0.00            
Flysand unchained 0.30            
Flysand unchained 1.10            
Flysand unchained 1.40            
Drifting sand 1.70            
Drifting sand 1.80            
Drifting sand 2.20            
Sand unchained 0.00            
Sand unchained 0.30            
Sand unchained 1.10            
Sand unchained 1.40            
fine sand 1.70            
fine sand 1.80            
fine sand 2.20    

您想找到 preceding-sibling 轴上的第一个(最近的)元素,然后从那里读取 DEPTHTO 属性。

所以:preceding-sibling::ZONE[1]/@DEPTHTO

将这些 select 表达式视为海盗地图上的方向:面向棕榈树走 20 步,然后面向锯齿状的岩石走 10 步,然后向下挖掘 6 英尺以找到埋藏的宝藏.

<xsl:transform version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <xsl:apply-templates select="ZONES/ZONE" />
</xsl:template>

<xsl:template match="ZONE">
    <xsl:text>"</xsl:text>
    <xsl:value-of select="@LAYER_DESC" />
    <xsl:text>" "</xsl:text>
    <xsl:value-of select="preceding-sibling::ZONE[1][@GROUP=current()/@GROUP]/@DEPTHTO" />
    <xsl:if     test="not(preceding-sibling::ZONE[1][@GROUP=current()/@GROUP]/@DEPTHTO)">0.00</xsl:if>
    <xsl:text>"
</xsl:text>
</xsl:template>

</xsl:transform>

输出:

"Flysand unchained" "0.00"
"Flysand unchained" "0.30"
"Flysand unchained" "1.10"
"Flysand unchained" "1.40"
"Drifting sand" "1.70"
"Drifting sand" "1.80"
"Drifting sand" "2.20"
"Sand unchained" "0.00"
"Sand unchained" "0.30"
"Sand unchained" "1.10"
"Sand unchained" "1.40"
"fine sand" "1.70"
"fine sand" "1.80"
"fine sand" "2.20"

我认为最初请求的输出没有考虑@GROUP?或者可能是我的错误。

上面的答案几乎没有对输入的规律性做出假设。它不假定每个元素都是一个 ZONE 或每个 ZONE 都具有所有预期的属性。如果你对输入更加确定,那么编码就可以做出假设。例如:

<xsl:choose>
    <xsl:when    test="@GROUP=preceding-sibling::*[1]/@GROUP">
        <xsl:value-of select="preceding-sibling::*[1]/@DEPTHTO"/>
    </xsl:when>
    <xsl:otherwise>0.00</xsl:otherwise>
</xsl:choose>