XSLT排序后Node/LINE段丢失问题排查及修正请求
修复XSLT中Node/LINE节点丢失问题,同时完成Node/ITEM与Node/LINE的分组排序
问题背景
需要对XML中的两类节点分别排序:
- Node/ITEM:按
LINE/CIDENT/FIER[@TYPE='Key1']/VALUE分组,同组内按LINE/CIDENT/FIER[@TYPE='Key2']/VALUE排序 - Node/LINE:按
CIDENT/FIER[@TYPE='Key1']/VALUE分组,同组内按CIDENT/FIER[@TYPE='Key2']/VALUE排序
现有XSLT仅能正确处理Node/ITEM的排序,但Node/LINE节点会完全丢失。以下是示例输入、期望输出及问题XSLT代码:
输入XML示例
<Root> <Node> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>A</VALUE></FIER> <FIER TYPE="Key2"><VALUE>2</VALUE></FIER> </CIDENT> <DATA>Line A-2</DATA> </LINE> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>B</VALUE></FIER> <FIER TYPE="Key2"><VALUE>1</VALUE></FIER> </CIDENT> <DATA>Line B-1</DATA> </LINE> <ITEM> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>A</VALUE></FIER> <FIER TYPE="Key2"><VALUE>1</VALUE></FIER> </CIDENT> <DATA>Item A-1</DATA> </LINE> </ITEM> <ITEM> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>A</VALUE></FIER> <FIER TYPE="Key2"><VALUE>2</VALUE></FIER> </CIDENT> <DATA>Item A-2</DATA> </LINE> </ITEM> </Node> </Root>
期望输出XML示例
<Root> <Node> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>A</VALUE></FIER> <FIER TYPE="Key2"><VALUE>2</VALUE></FIER> </CIDENT> <DATA>Line A-2</DATA> </LINE> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>B</VALUE></FIER> <FIER TYPE="Key2"><VALUE>1</VALUE></FIER> </CIDENT> <DATA>Line B-1</DATA> </LINE> <ITEM> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>A</VALUE></FIER> <FIER TYPE="Key2"><VALUE>1</VALUE></FIER> </CIDENT> <DATA>Item A-1</DATA> </LINE> </ITEM> <ITEM> <LINE> <CIDENT> <FIER TYPE="Key1"><VALUE>A</VALUE></FIER> <FIER TYPE="Key2"><VALUE>2</VALUE></FIER> </CIDENT> <DATA>Item A-2</DATA> </LINE> </ITEM> </Node> </Root>
当前问题XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:key name="itemKey1" match="Node/ITEM" use="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/> <xsl:template match="/"> <Root> <Node> <!-- 仅处理了ITEM节点,完全忽略LINE节点 --> <xsl:for-each select="Node/ITEM[generate-id() = generate-id(key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)[1])]"> <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/> <xsl:for-each select="key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)"> <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key2']/VALUE"/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:for-each> </Node> </Root> </xsl:template> </xsl:stylesheet>
问题排查
当前XSLT只编写了Node/ITEM的排序逻辑,完全没有处理Node/LINE节点,导致这部分节点在输出中丢失。同时缺少身份模板,无法保留XML的其他原有结构。
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 为ITEM按Key1分组的键 --> <xsl:key name="itemKey1" match="Node/ITEM" use="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/> <!-- 为LINE按Key1分组的键 --> <xsl:key name="lineKey1" match="Node/LINE" use="CIDENT/FIER[@TYPE='Key1']/VALUE"/> <!-- 身份模板:原样复制未被特殊处理的节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 专门处理Node节点,分别排序LINE和ITEM --> <xsl:template match="Node"> <xsl:copy> <!-- 处理Node/LINE的分组排序 --> <xsl:for-each select="LINE[generate-id() = generate-id(key('lineKey1', CIDENT/FIER[@TYPE='Key1']/VALUE)[1])]"> <xsl:sort select="CIDENT/FIER[@TYPE='Key1']/VALUE"/> <xsl:for-each select="key('lineKey1', CIDENT/FIER[@TYPE='Key1']/VALUE)"> <xsl:sort select="CIDENT/FIER[@TYPE='Key2']/VALUE"/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:for-each> <!-- 处理Node/ITEM的分组排序(仅当存在ITEM时执行) --> <xsl:if test="ITEM"> <xsl:for-each select="ITEM[generate-id() = generate-id(key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)[1])]"> <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/> <xsl:for-each select="key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)"> <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key2']/VALUE"/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:for-each> </xsl:if> </xsl:copy> </xsl:template> </xsl:stylesheet>
修正说明
- 添加身份模板:这是XSLT的常规操作,确保XML中除LINE、ITEM外的其他节点和属性都能原样复制,避免结构丢失。
- 新增LINE分组键:创建
lineKey1键,和ITEM的itemKey1对应,实现LINE按Key1分组的逻辑。 - 重写Node节点处理逻辑:在Node标签内先处理LINE的分组排序,再处理ITEM的排序,保证两类节点都被保留并按规则排序。
- 添加ITEM存在判断:避免当没有ITEM节点时输出空内容,提升代码严谨性。
内容的提问来源于stack exchange,提问作者Pavan
相关产品推荐
相关产品推荐

