能否通过XSLT转换将交叉表结构XML转为列表形式XML?
需求说明
我在应用中有如下中间XML文档:
示例源XML数据
<?xml version="1.0" standalone="yes"?> <DocumentElement> <Car> <COL1>Name</COL1> <COL2>White</COL2> <COL3>Black</COL3> <COL4>Red</COL4> </Car> <Car> <COL1>BMW</COL1> <COL2>20</COL2> <COL3>10</COL3> <COL4>10</COL4> </Car> <Car> <COL1>TOYOTA</COL1> <COL2>15</COL2> <COL3>18</COL3> <COL4>22</COL4> </Car> <Car> <COL1>MERCEDES</COL1> <COL2>20</COL2> <COL3>*</COL3> <COL4>12</COL4> </Car> </DocumentElement>
其表格形式如下:
| Name | White | Black | Blue | | -------- | ----- | ----- | ---- | | BMW | 15 | 18 | 22 | | TOYOTA | 15 | 18 | 22 | | MERCEDES | 20 | - | 12 |
我希望将该XML文档转换为包含Name、Colour、Quantity的简单列表,表格形式如下:
| Name | Colour | Quantity | | -------- | ------ | -------- | | BMW | White | 20 | | BMW | Black | 10 | | BMW | Blue | 10 | | TOYOTA | White | 15 | | TOYOTA | Black | 18 | | TOYOTA | Blue | 22 | | MERCEDES | White | 20 | | MERCEDES | Blue | 12 |
转换后的XML应如下所示:
示例转换后XML数据
<?xml version="1.0" encoding="UTF-8"?> <DocumentElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:my="put-your-namespace-uri-here"> <Car> <Name>BMW</Name> <Colour>White</Colour> <Quantity>20</Quantity> </Car> <Car> <Name>BMW</Name> <Colour>Black</Colour> <Quantity>10</Quantity> </Car> <Car> <Name>BMW</Name> <Colour>Blue</Colour> <Quantity>10</Quantity> </Car> <Car> <Name>TOYOTA</Name> <Colour>White</Colour> <Quantity>15</Quantity> </Car> <Car> <Name>TOYOTA</Name> <Colour>Black</Colour> <Quantity>18</Quantity> </Car> <Car> <Name>TOYOTA</Name> <Colour>Blue</Colour> <Quantity>22</Quantity> </Car> <Car> <Name>MERCEDES</Name> <Colour>White</Colour> <Quantity>20</Quantity> </Car> <Car> <Name>MERCEDES</Name> <Colour>Blue</Colour> <Quantity>12</Quantity> </Car> </DocumentElement>
请问能否通过XSLT转换实现该需求?恳请指导。
谢谢,
Amit
XSLT实现方案
可以通过XSLT完全实现该转换需求,以下是对应的XSLT代码:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 捕获第一行Car节点作为颜色表头 --> <xsl:variable name="headers" select="/DocumentElement/Car[1]/*"/> <xsl:template match="/"> <DocumentElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:my="put-your-namespace-uri-here"> <!-- 遍历除第一行外的所有Car节点(对应各品牌数据) --> <xsl:for-each select="/DocumentElement/Car[position() > 1]"> <xsl:variable name="currentBrand" select="COL1"/> <!-- 遍历当前品牌下除名称外的所有颜色数量节点 --> <xsl:for-each select="*[position() > 1]"> <xsl:variable name="colPos" select="position()"/> <!-- 获取对应表头的颜色名称 --> <xsl:variable name="colourName" select="$headers[$colPos + 1]"/> <!-- 过滤掉值为*的无效条目 --> <xsl:if test="normalize-space(.) != '*'"> <Car> <Name><xsl:value-of select="$currentBrand"/></Name> <Colour><xsl:value-of select="$colourName"/></Colour> <Quantity><xsl:value-of select="."/></Quantity> </Car> </xsl:if> </xsl:for-each> </xsl:for-each> </DocumentElement> </xsl:template> </xsl:stylesheet>
代码说明
- 先通过
headers变量提取第一个Car节点的所有子元素,作为颜色名称的表头; - 遍历从第二个开始的
Car节点,每个节点对应一个汽车品牌; - 对每个品牌节点,遍历除
COL1(名称列)外的子元素,将子元素值作为数量,对应表头的内容作为颜色字段; - 用
xsl:if过滤掉值为*的条目,不生成无效的Car节点; - 输出的XML结构完全匹配需求,包含指定的命名空间。
内容的提问来源于stack exchange,提问作者Amit
相关产品推荐
相关产品推荐

