XSLT技术求助:计算带注释操作的文本行数及行范围
XSLT新手求助:计算带注释操作的行号范围并生成XML
输入XML
<?xml version="1.0" encoding="utf-8"?> <WorkingCycle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Operations> <WorkingCycleOperation> <OperationID>PICKING</OperationID> </WorkingCycleOperation> <WorkingCycleOperation> <OperationID>CUTTING</OperationID> <OperationNote>Lorem ipsum dolor sit amet, consectetur adipiscing elit</OperationNote> </WorkingCycleOperation> <WorkingCycleOperation> <OperationID>FEEDING</OperationID> <OperationNote>sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</OperationNote> </WorkingCycleOperation> <WorkingCycleOperation> <OperationID>MELTING</OperationID> </WorkingCycleOperation> <WorkingCycleOperation> <OperationID>BRUSHING</OperationID> <OperationNote>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat</OperationNote> </WorkingCycleOperation> <WorkingCycleOperation> <OperationID>PACKING</OperationID> </WorkingCycleOperation> </Operations> </WorkingCycle>
需求说明
- 仅处理带有
<OperationNote>的操作 - 计算每个注释文本按20字符拆分后的总行数(字符串长度除以20向上取整)
- 按顺序累加所有带注释操作的行数,为每个操作生成包含操作ID、起始行、结束行的XML节点
- 示例:
- CUTTING注释长55字符,拆分为3行,起止行1-3
- FEEDING注释长65字符,拆分为4行,起止行4-7
- BRUSHING注释长106字符,拆分为6行,起止行8-13
预期输出
<?xml version='1.0' ?> <Line> <OperationID>CUTTING</OperationID> <FromLine>1</FromLine> <ToLine>3</ToLine> </Line> <Line> <OperationID>FEEDING</OperationID> <FromLine>4</FromLine> <ToLine>7</ToLine> </Line> <Line> <OperationID>BRUSHING</OperationID> <FromLine>8</FromLine> <ToLine>13</ToLine> </Line>
当前代码(未达预期)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" version="1.0"> <xsl:template match="WorkingCycle"> <processResponse> <xsl:for-each select="Operations"> <xsl:for-each select="WorkingCycleOperation"> <xsl:variable name="OperID" select="OperationID"/> <!-- <xsl:for-each select="OperationNote">--> <xsl:if test="OperationNote"> <xsl:variable name="j" select="position()"/> <xsl:variable name="opNote" select="OperationNote"/> <xsl:variable name="lines" select="ceiling(string-length($opNote) div 20)"/> <xsl:variable name="end" select="$lines"/> <xsl:choose> <xsl:when test="$j > 1"> <xsl:variable name="start" select="$end + 1"/> </xsl:when> <xsl:otherwise> <xsl:variable name="start" select="1"/> <!-- <xsl:variable name="end" select="$lines"/>--> </xsl:otherwise> </xsl:choose> <OperationID> <xsl:value-of select="$OperID"/> </OperationID> <FromLine> <xsl:value-of select="$start"/> </FromLine> <ToLine> <xsl:value-of select="$end"/> </ToLine> </xsl:if> <!-- </xsl:for-each>--> </xsl:for-each> </xsl:for-each> </processResponse> </xsl:template> </xsl:transform>
问题分析与修正方案
原代码核心问题
- position()取值错误:遍历所有
WorkingCycleOperation,但很多操作无OperationNote,导致position()不是带注释操作的实际顺序 - 行号未累加:未计算前面所有带注释操作的总行数,
start和end仅基于当前操作,无法生成连续行号范围 - 输出结构不符:未生成
<Line>包裹节点,直接输出零散元素
修正后的XSLT代码
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- 输出XML声明 --> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/WorkingCycle"> <!-- 仅筛选带有OperationNote的操作 --> <xsl:for-each select="Operations/WorkingCycleOperation[OperationNote]"> <!-- 计算当前操作的行数 --> <xsl:variable name="current-lines" select="ceiling(string-length(OperationNote) div 20)"/> <!-- 计算前面所有带注释操作的总行数 --> <xsl:variable name="previous-total" select="sum(preceding-sibling::WorkingCycleOperation[OperationNote]/ceiling(string-length(OperationNote) div 20))"/> <!-- 计算起始行和结束行 --> <xsl:variable name="from-line" select="$previous-total + 1"/> <xsl:variable name="to-line" select="$previous-total + $current-lines"/> <!-- 生成预期的Line节点 --> <Line> <OperationID> <xsl:value-of select="OperationID"/> </OperationID> <FromLine> <xsl:value-of select="$from-line"/> </FromLine> <ToLine> <xsl:value-of select="$to-line"/> </ToLine> </Line> </xsl:for-each> </xsl:template> </xsl:transform>
关键说明
- 筛选目标操作:直接用
WorkingCycleOperation[OperationNote]过滤需要处理的节点,避免遍历无关操作 - 累加前面行数:使用
sum(preceding-sibling::WorkingCycleOperation[OperationNote]/ceiling(...))计算当前操作之前所有带注释操作的总行数 - 行号计算逻辑:起始行 = 前面总行数 + 1,结束行 = 前面总行数 + 当前操作行数
- 输出标准结构:每个操作都用
<Line>节点包裹,完全匹配预期输出格式
内容的提问来源于stack exchange,提问作者Flavio
相关产品推荐
相关产品推荐

