如何使用xslt计算输出行数?

发布于 2024-09-16 02:01:27 字数 526 浏览 3 评论 0原文

我正在使用 XSLT 输出文本。我需要计算每个部分的行数并将其写入我的输出文件。这怎么能做到呢?

我的输出如下:

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'

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

由于 XSLT 内部有大量处理,因此无法从源代码中计算行数。

I'm outputting text with XSLT. I need to count the number of lines of each section and write it out to my output file. How this could be done?

My output is like this:

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'

The number_of_records should contain number of lines from AAA to XXX including both lines. In the first section the number of lines should be 6 and in the second message it should be 8. The first and the last line of each section will share the same unique ID-number.

The number of lines cannot be counted from source since there is so much processing inside XSLT.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

弱骨蛰伏 2024-09-23 02:01:27

从概念上讲,一种简单的方法是使用第二阶段过程。获取初始转换的输出(您发布的内容)并通过模板(或类似 @Alejandro 的样式表)运行它,将其解析为行,并将以 AAA... 开头和结尾的行分组与XXX。请参阅使用 XSLT 2.0 进行上转换,了解非常清晰的信息有关使用 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()。 (但是,即使使用单独的样式表处理器,如果您可以使用 SAX 将两个样式表处理器一起通过管道传输,您仍然可以避免重新解析中间 XML 的成本。)在 XSLT 2.0 中,您可以使用以下命令处理一个模板的 XML 输出:另一个模板,没有限制。

A conceptually simple way to do this would be to use a second-stage process. Take the output of your initial transformation (what you posted) and run it through a template (or stylesheet like @Alejandro's) that parses it into lines, and groups the lines starting with AAA... and ending with XXX. See Up-conversion using XSLT 2.0 for a very clear and practical tutorial on doing this, using tokenize(), xsl:analyze-string, and xsl:for-each-group. Then count the lines in each group, and re-output each line, plug the line count into the XXX record.

But that's inefficient, and somewhat error-prone, since you would be parsing the initial output. Why parse a serialization of information that the stylesheet already had internally? You could avoid the inefficiency by changing your initial output to XML, something like

<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>

Then the second-stage template (or a separate stylesheet) could take this XML as input and very easily serialize it as you have done above, counting the lines as it goes.
In XSLT 1.0, you would have to use a separate stylesheet to process the output XML, or else use the extension function node-set(). (But even with a separate stylesheet processor, you could still avoid the cost of re-parsing the intermediate XML, if you can pipeline the two stylesheet processors together using SAX.) In XSLT 2.0, you can process the XML output of one template with another template, without restriction.

一念一轮回 2024-09-23 02:01:27

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

<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,"'
")'/>
                <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,
                                                               "
",
                                                               ""),
                                                     "")) + 1,
                             "+",$vId,"'
")'/>
                <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'

Just for fun, until you post your input sample and stylesheet building that text output, this stylesheet:

<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,"'
")'/>
                <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,
                                                               "
",
                                                               ""),
                                                     "")) + 1,
                             "+",$vId,"'
")'/>
                <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>

With this input:

<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>

Output:

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'
不语却知心 2024-09-23 02:01:27

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

分两步做可能会造成太多麻烦。

My solution: I created an extension function that increments number_of_records by one each time I call it. I use xsl:comment to suppress the output until I really need to output the number. I reset the number_of_records after each XXX+ -line.

Doing this in two steps vould have caused too much hassle.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文