XSLT分组问题:按ExternalBatchNo前缀分组machine与part失败求助
问题
需要实现基于单个元素的双条件分组:将ExternalBatchNo中-之前部分相同的machine和part归为一组,拆分出多个<Document>节点,每个节点包含同前缀的machine和part。
输入XML
<Document> <DocumentLine> <ExternalBatchNo>KEC36770</ExternalBatchNo> <Attribute01>machine</Attribute01> </DocumentLine> <DocumentLine> <ExternalBatchNo>KEC36770-2</ExternalBatchNo> <Attribute01>part</Attribute01> </DocumentLine> <DocumentLine> <ExternalBatchNo>KEC36771</ExternalBatchNo> <Attribute01>machine</Attribute01> </DocumentLine> <DocumentLine> <ExternalBatchNo>KEC36771-2</ExternalBatchNo> <Attribute01>part</Attribute01> </DocumentLine> <DocumentLine> <ExternalBatchNo>KEC36771-3</ExternalBatchNo> <Attribute01>part</Attribute01> </DocumentLine> </Document>
期望输出
<Document> <DocumentLine> <ExternalBatchNo>KEC36770</ExternalBatchNo> <Attribute01>machine</Attribute01> </DocumentLine> <DocumentLine> <ExternalBatchNo>KEC36770-2</ExternalBatchNo> <Attribute01>part</Attribute01> </DocumentLine> </Document> <Document> <DocumentLine> <ExternalBatchNo>KEC36771</ExternalBatchNo> <Attribute01>machine</Attribute01> </DocumentLine> <DocumentLine> <ExternalBatchNo>KEC36771-2</ExternalBatchNo> <Attribute01>part</Attribute01> </DocumentLine> <DocumentLine> <ExternalBatchNo>KEC36771-3</ExternalBatchNo> <Attribute01>part</Attribute01> </DocumentLine> </Document>
尝试的代码问题
使用以下代码时,machine对应的分组ID为空,只能对part完成分组:
<xsl:for-each-group select="Message/Documents/Document/DocumentLine" group-by="substring-before(ExternalBatchNo,'-')">
解决方案
问题出在substring-before(ExternalBatchNo,'-')——当ExternalBatchNo中没有-时,这个函数会返回空字符串,导致machine条目无法和对应前缀的part条目归为一组。
可以通过给无-的ExternalBatchNo拼接一个-来统一处理,确保substring-before总能获取到正确的前缀:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/Document"> <!-- 按处理后的前缀分组 --> <xsl:for-each-group select="DocumentLine" group-by="substring-before(concat(ExternalBatchNo, '-'), '-')"> <!-- 生成每个分组对应的Document节点 --> <Document> <!-- 输出当前分组下的所有DocumentLine --> <xsl:copy-of select="current-group()"/> </Document> <!-- 添加空行分隔不同Document节点 --> <xsl:text> </xsl:text> </xsl:for-each-group> </xsl:template> </xsl:stylesheet>
代码说明
concat(ExternalBatchNo, '-'):给所有ExternalBatchNo末尾拼接-,比如KEC36770变成KEC36770-,KEC36770-2变成KEC36770-2-。substring-before(..., '-'):此时无论原字符串是否有-,都能提取到第一个-之前的正确前缀,比如KEC36770和KEC36770-2的前缀都是KEC36770。current-group():获取当前分组下的所有DocumentLine节点,直接复制输出即可。
内容的提问来源于stack exchange,提问作者Sjoert
相关产品推荐
相关产品推荐

