代码之家  ›  专栏  ›  技术社区  ›  code-geek

XSLT累加器-计算特定节点之间的节点数

  •  0
  • code-geek  · 技术社区  · 6 年前

    我有以下xml模式:

    <tag name="(some_string)_start">
    <tag name="step1">
    <tag name="step2">
    <tag name="step3">
    <tag name="step4">
    <tag name="(some_string)_end">
    <tag name="(some_other_string)_start">
    <tag name="step1">
    <tag name="step2">
    <tag name="step3">
    <tag name="step4">
    <tag name="step5">
    <tag name="(some_other_string)_end">
    

    我需要使用XSLT将其转换为文本文件,如下所示:

    name=(some_string), step_index=0
    name=step1, step_index=1
    name=step2, step_index=2
    name=step3, step_index=3
    name=step4, step_index=4
    name=(some_string), step_index=5
    name=(some_other_string), step_index=0
    name=step1, step_index=1
    name=step2, step_index=2
    name=step3, step_index=3
    name=step4, step_index=4
    name=step5, step_index=5
    name=(some_other_string), step_index=6
    

    我想计算后缀为“开始”到“结束”的节点数 当我遇到后缀为“start”的下一个名称时,计数器应该重新初始化为零

    以下是我尝试的XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">    
        <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
        <xsl:accumulator name="step-index" initial-value="0">
            <xsl:accumulator-rule match="sample[matches(@name, '.*Start$')]" select="0">
            </xsl:accumulator-rule>
            <xsl:accumulator-rule match="sample[matches(@name, '.*End$')]" select="$value+1">
            </xsl:accumulator-rule>         
        </xsl:accumulator>
        <xsl:template match="tag">
            <xsl:text>,name=</xsl:text>
            <xsl:value-of select="@name"/>
            <xsl:text>,step-index=</xsl:text>
                <xsl:value-of select="accumulator-after('step-index')"/>
        </xsl:template>
    </xsl:stylesheet>
    

    但我没有得到所需的输出使用上述累加器的方法。 如何使用XSLT计算步骤索引值?

    0 回复  |  直到 6 年前
        1
  •  1
  •   Martin Honnen    6 年前

    正如我在一篇评论中所说,您没有解释您的方法是如何失败的,以及您是否至少尝试使用XSLT3处理器运行XSLT3功能。

    <?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"
        exclude-result-prefixes="#all"
        expand-text="yes"
        version="3.0">
        
        <xsl:mode use-accumulators="step-index"/>
    
        <xsl:output method="text"/>
        <xsl:strip-space elements="*"/>
        
        <xsl:accumulator name="step-index" initial-value="0">
            <xsl:accumulator-rule match="tag[ends-with(@name, '_start')]" select="0"/>
            <xsl:accumulator-rule match="tag[not(ends-with(@name, '_start'))]" select="$value + 1"/>
        </xsl:accumulator>
        
        <xsl:template match="tag">
            <xsl:text>name={@name => replace('_(start|end)$', '')},step-index={accumulator-after('step-index')}&#10;</xsl:text>
        </xsl:template>
      
    </xsl:stylesheet>
    

    抨击 https://xsltfiddle.liberty-development.net/ehW12fW/1 在萨克森9.8中,他使用了一个结构良好的样本

    <root>
    <tag name="(some_string)_start"/>
    <tag name="step1"/>
    <tag name="step2"/>
    <tag name="step3"/>
    <tag name="step4"/>
    <tag name="(some_string)_end"/>
    <tag name="(some_other_string)_start"/>
    <tag name="step1"/>
    <tag name="step2"/>
    <tag name="step3"/>
    <tag name="step4"/>
    <tag name="step5"/>
    <tag name="(some_other_string)_end"/>
    </root>
    

    它输出

    name=(some_string),step-index=0
    name=step1,step-index=1
    name=step2,step-index=2
    name=step3,step-index=3
    name=step4,step-index=4
    name=(some_string),step-index=5
    name=(some_other_string),step-index=0
    name=step1,step-index=1
    name=step2,step-index=2
    name=step3,step-index=3
    name=step4,step-index=4
    name=step5,step-index=5
    name=(some_other_string),step-index=6