【问题标题】:How to count output lines with xslt?如何用 xslt 计算输出行数?
【发布时间】:2010-08-23 11:39:15
【问题描述】:

我正在使用 XSLT 输出文本。我需要计算每个部分的行数并将其写到我的输出文件中。如何做到这一点?

我的输出是这样的:

HDR+aaa:bbb' AAA+78901234567890+String1:String2' BBB+123+弦' CCC+321:1212' DDD+112211' DDD+121122' XXX+number_of_records+78901234567890' AAA+1234567890+String1:String2' BBB+123+弦' CCC+321:1212' DDD+1212:2121' BBB+123+弦' BBB+122+弦' CCC+字符串' XXX+number_of_records+1234567890'

number_of_records 应包含从 AAA 到 XXX 的行数,包括这两行。在第一部分中,行数应该是 6,在第二条消息中应该是 8。每个部分的第一行和最后一行将共享相同的唯一 ID 号。

无法从源代码计算行数,因为 XSLT 内部有太多的处理。

【问题讨论】:

  • 没有输入或它的样本,没有人可以在这里给你太多帮助。您使用的是 XSLT 1 还是 2;你用的是什么处理器?
  • 同时发布您的 XSLT,因为这对于辨别需要什么是必要的

标签: xslt text line-count


【解决方案1】:

一个概念上简单的方法是使用第二阶段过程。获取初始转换的输出(您发布的内容)并通过模板(或 @Alejandro 之类的样式表)运行它,该模板将其解析为行,并将以 AAA... 开头并以 XXX 结尾的行分组。使用tokenize()xsl:analyze-stringxsl:for-each-group,请参阅Up-conversion using XSLT 2.0 以获得非常清晰实用的教程。然后统计每组的行数,重新输出每一行,将行数插入到XXX记录中。

但这效率低下,而且有些容易出错,因为您将解析初始输出。为什么要解析样式表内部已有的信息序列化?您可以通过将初始输出更改为 XML 来避免效率低下,例如

<hdr>
  <section id="78901234567890">
    <!-- It sounds like AAA's ID actually applies to the section? -->
    <AAA String1="..." String2="..."/>
    <BBB .../>
    <!-- no need to include XXX at this stage AFAICT -->
  </section>
  <section id="1234567890">
    ...
  </section>
</hdr>

然后,第二阶段模板(或单独的样式表)可以将此 XML 作为输入,并像您在上面所做的那样非常容易地对其进行序列化,同时计算行数。 在 XSLT 1.0 中,您必须使用单独的样式表来处理输出 XML,或者使用 extension function node-set()。 (但即使使用单独的样式表处理器,您仍然可以避免重新解析中间 XML 的成本,如果您可以使用 SAX 将两个样式表处理器一起流水线化。)在 XSLT 2.0 中,您可以使用以下命令处理一个模板的 XML 输出另一个模板,没有限制。

【讨论】:

    【解决方案2】:

    只是为了好玩,直到您发布输入示例和构建文本输出的样式表,此样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
        <xsl:template match="result" name="result">
            <xsl:param name="pString" select="."/>
            <xsl:variable name="vAfter" select="substring-after($pString, 'AAA+')"/>
            <xsl:choose>
                <xsl:when test="$vAfter!=''">
                    <xsl:variable name="vId" 
                            select="substring-before($vAfter, '+')"/>
                    <xsl:variable name="vEnd" 
                      select='concat("XXX+number_of_records+",$vId,"&apos;&#xA;")'/>
                    <xsl:variable name="vInto" 
                            select="substring-before($vAfter,$vEnd)"/>
                    <xsl:value-of 
                            select='concat(substring-before($pString,"AAA+"),
                                 "AAA+",
                                 $vInto,
                                 "XXX+",
                                 string-length(translate($vInto,
                                                         translate($vInto,
                                                                   "&#xA;",
                                                                   ""),
                                                         "")) + 1,
                                 "+",$vId,"&apos;&#xA;")'/>
                    <xsl:call-template name="result">
                        <xsl:with-param name="pString" 
                            select="substring-after($vAfter,$vEnd)"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$pString"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    </xsl:stylesheet>
    

    有了这个输入:

    <result>
    HDR+aaa:bbb'
    AAA+78901234567890+String1:String2'
    BBB+123+String'
    CCC+321:1212'
    DDD+112211'
    DDD+121122'
    XXX+number_of_records+78901234567890'
    AAA+1234567890+String1:String2'
    BBB+123+String'
    CCC+321:1212'
    DDD+1212:2121'
    BBB+123+String'
    BBB+122+String'
    CCC+String'
    XXX+number_of_records+1234567890'
    </result>
    

    输出:

    HDR+aaa:bbb'
    AAA+78901234567890+String1:String2'
    BBB+123+String'
    CCC+321:1212'
    DDD+112211'
    DDD+121122'
    XXX+6+78901234567890'
    AAA+1234567890+String1:String2'
    BBB+123+String'
    CCC+321:1212'
    DDD+1212:2121'
    BBB+123+String'
    BBB+122+String'
    CCC+String'
    XXX+8+1234567890'
    

    【讨论】:

      【解决方案3】:

      我的解决方案:我创建了一个扩展函数,每次调用它时都会将 number_of_records 递增一。我使用 xsl:comment 来抑制输出,直到我真的需要输出数字。我在每个 XXX+ 行之后重置 number_of_records。

      分两步执行此操作会造成太多麻烦。

      【讨论】:

        猜你喜欢
        • 2021-12-26
        • 1970-01-01
        • 2020-07-06
        • 1970-01-01
        • 1970-01-01
        • 2013-12-23
        • 2023-02-14
        • 1970-01-01
        • 2012-04-19
        相关资源
        最近更新 更多