请求编写XSLT实现按学生分组拆分XML数据
问题:将连续- 节点按学生信息分组包裹为
节点
现有一份XML数据,<root>下的<item>节点按顺序每3个为一组,对应一名学生的StudentID、StudentName、City信息。需要编写XSLT,将每组三个<item>节点包裹到<Record>节点中输出。
输入XML
<?xml version="1.0" encoding="UTF-8" ?> <root> <item> <columnName>StudentID</columnName> <value>2356</value> </item> <item> <columnName>StudentName</columnName> <value>Java</value> </item> <item> <columnName>City</columnName> <value>Chicago</value> </item> <item> <columnName>StudentID</columnName> <value>4578</value> </item> <item> <columnName>StudentName</columnName> <value>Net</value> </item> <item> <columnName>City</columnName> <value>NewYork</value> </item> <item> <columnName>StudentID</columnName> <value>5892</value> </item> <item> <columnName>StudentName</columnName> <value>Office</value> </item> <item> <columnName>City</columnName> <value>Dallas</value> </item> </root>
期望输出XML
<?xml version="1.0" encoding="UTF-8" ?> <root> <Record> <item> <columnName>StudentID</columnName> <value>2356</value> </item> <item> <columnName>StudentName</columnName> <value>Java</value> </item> <item> <columnName>City</columnName> <value>Chicago</value> </item> </Record> <Record> <item> <columnName>StudentID</columnName> <value>4578</value> </item> <item> <columnName>StudentName</columnName> <value>Net</value> </item> <item> <columnName>City</columnName> <value>NewYork</value> </item> </Record> <Record> <item> <columnName>StudentID</columnName> <value>5892</value> </item> <item> <columnName>StudentName</columnName> <value>Office</value> </item> <item> <columnName>City</columnName> <value>Dallas</value> </item> </Record> </root>
现有未完成XSLT代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" encoding="utf-8" indent="yes"/> <xsl:template match="root"> <root> <Record> <xsl:apply-templates select="data"/> </Record> <Record/> </root> </xsl:template> <xsl:template match="data"> <data> <xsl:apply-templates select="columnName"/> <xsl:apply-templates select="value"/> </data> </xsl:template> <xsl:template match="columnName"> <columnName> <xsl:value-of select="."/> </columnName> </xsl:template> <xsl:template match="value"> <value> <xsl:value-of select="."/> </value> </xsl:template> </xsl:stylesheet>
正确XSLT实现方案
以下是可以实现需求的XSLT代码:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" encoding="utf-8" indent="yes"/> <!-- 处理根节点,遍历每个学生的起始item(StudentID) --> <xsl:template match="root"> <root> <xsl:apply-templates select="item[columnName='StudentID']" mode="record"/> </root> </xsl:template> <!-- 为每个学生生成Record节点,包含当前item及后续两个兄弟item --> <xsl:template match="item" mode="record"> <Record> <xsl:copy-of select="."/> <xsl:copy-of select="following-sibling::item[1]"/> <xsl:copy-of select="following-sibling::item[2]"/> </Record> </xsl:template> <!-- 屏蔽默认文本节点处理,避免输出多余空白 --> <xsl:template match="text()"/> </xsl:stylesheet>
实现思路
- 定位分组起始点:选择所有
columnName为StudentID的<item>节点,这些节点是每个学生信息的第一个节点。 - 生成Record节点:对每个起始
<item>,生成<Record>节点,并复制当前节点以及后面两个兄弟<item>,刚好组成一个学生的完整信息。 - 清理多余内容:添加空模板匹配文本节点,防止XML中的空白字符被错误输出。
如果不想依赖columnName的值,也可以通过节点位置来分组,将<xsl:apply-templates>的选择器改为item[position() mod 3 = 1],这样每3个<item>为一组,取第一个作为起始点,效果相同。
内容的提问来源于stack exchange,提问作者user20463275
相关产品推荐
相关产品推荐

