2

我正在使用 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 内部有太多的处理,因此无法从源代码中计算行数。

4

3 回答 3

2

一种概念上简单的方法是使用第二阶段过程。获取初始转换的输出(您发布的内容)并通过模板(或 @Alejandro 之类的样式表)运行它,该模板将其解析为行,并将以AAA... 开头和以 . 结尾的行分组XXX。有关使用tokenize()xsl:analyze-stringxsl:for-each-group. _ 然后统计每组的行数,重新输出每一行,将行数插入到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,或者使用扩展函数 node-set()。(但即使使用单独的样式表处理器,您仍然可以避免重新解析中间 XML 的成本,如果您可以使用 SAX 将两个样式表处理器一起流水线化。)在 XSLT 2.0 中,您可以处理一个模板的 XML 输出另一个模板,没有限制。

于 2010-08-23T16:00:14.947 回答
1

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

<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'
于 2010-08-23T15:06:47.620 回答
0

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

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

于 2010-08-26T14:25:25.680 回答