使用XSLT基于Type字段排序XML记录时丢失头部字段的问题求助
问题分析
你遇到的问题根源很清晰:当前匹配root节点的XSLT模板只遍历并处理了Access子节点,完全漏掉了ID、Allocation、Year这些同级的头部字段。当你重写root节点的模板时,必须手动处理所有需要保留的子节点,而不仅仅是要排序的Access。
修正后的XSLT代码
这里提供两种实用的修正方案,你可以根据场景选择:
方案1:明确保留指定头部节点,再处理排序后的Access
这种方式逻辑直白,适合节点数量固定的场景:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 身份转换模板:默认复制所有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="root"> <xsl:copy> <!-- 先复制所有需要保留的头部节点 --> <xsl:apply-templates select="ID | Allocation | Year"/> <!-- 再对Access节点按Type排序输出 --> <xsl:apply-templates select="Access"> <xsl:sort select="Type"/> <!-- 注意:Type是字符串类型,原代码的datatype="number"会导致排序异常,这里去掉该属性 --> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet>
方案2:批量保留非Access节点,再处理排序后的Access
这种方式更灵活,适合子节点较多或后续可能新增节点的场景:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 身份转换模板 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="root"> <xsl:copy> <!-- 保留所有非Access的子节点,按原顺序输出 --> <xsl:apply-templates select="*[not(local-name()='Access')]"/> <!-- 对Access节点按Type排序输出 --> <xsl:apply-templates select="Access"> <xsl:sort select="Type"/> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键改动说明
- 补全头部节点处理:在
root模板中新增了对非Access节点的复制逻辑,确保ID、Allocation、Year不会丢失。 - 修正排序数据类型:原代码中给
<xsl:sort>添加的datatype="number"是错误的——Type的值是IO、MC这类字符串,该属性会导致排序异常,因此移除了它(默认就是字符串排序,符合需求)。 - 对齐输出编码:在
<xsl:output>里添加encoding="UTF-8",让输出XML的编码和原输入保持一致。
验证输出
修正后的XSLT处理输入XML后,会得到包含完整头部字段且Access按Type排序的输出:
<?xml version="1.0" encoding="UTF-8"?> <root> <ID>134</ID> <Allocation>9</Allocation> <Year>2021</Year> <Access> <Code>12</Code> <PCode>13</PCode> <Type>IO</Type> </Access> <Access> <Code>15</Code> <PCode>16</PCode> <Type>IO</Type> </Access> <Access> <Code>30</Code> <PCode>31</PCode> <Type>IO</Type> </Access> <Access> <Code>35</Code> <PCode>36</PCode> <Type>IO</Type> </Access> <Access> <Code>19</Code> <PCode>20</PCode> <Type>MC</Type> </Access> <Access> <Code>22</Code> <PCode>25</PCode> <Type>MC</Type> </Access> </root>
内容的提问来源于stack exchange,提问作者janardhan d
相关产品推荐
相关产品推荐

