如何用XSL将XML转换为通用垂直表格?
解决动态生成垂直XML到HTML表格的问题
你的问题在于原XSL是逐个遍历每个Book的子元素,导致每个元素会随着Book重复出现,而我们需要的是按元素名分组,每个元素名对应一行,然后将所有Book的对应值作为列展示。
在XSLT 1.0中,我们可以用Muenchian分组来获取所有唯一的元素名,然后为每个元素名生成一行,再遍历所有Book提取对应的值。下面是完整的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义键:按元素的本地名称分组 --> <xsl:key name="element-names" match="Book/*" use="local-name()" /> <xsl:template match="/Library"> <table border="1"> <!-- 遍历所有唯一的元素名:取每个分组的第一个节点 --> <xsl:for-each select="Book/*[generate-id() = generate-id(key('element-names', local-name())[1])]"> <tr> <!-- 第一列:元素名称 --> <td><xsl:value-of select="local-name()" /></td> <!-- 遍历所有Book,提取当前元素名对应的值 --> <xsl:for-each select="/Library/Book"> <td><xsl:value-of select="*[local-name() = current()/local-name()]" /></td> </xsl:for-each> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
代码解释:
- Muenchian分组:通过
<xsl:key>定义了一个基于元素本地名称的分组,这样我们可以快速找到所有同名的元素。 - 获取唯一元素名:
Book/*[generate-id() = generate-id(key('element-names', local-name())[1])]这个选择器会筛选出每个元素名称对应的第一个节点,从而得到所有不重复的元素名。 - 生成每行数据:对于每个唯一元素名,先输出元素名作为第一列,然后遍历所有
Book节点,找到当前元素名对应的子元素并输出其值作为后续列。
测试你的输入XML,输出的HTML表格结构如下:
<table border="1"> <tr> <td>Title</td> <td>Foo</td> <td>Bar</td> </tr> <tr> <td>ThisMaybeHere</td> <td>Some Value</td> <td>Some Value</td> </tr> <tr> <td>DontKnowAboutThis</td> <td>Also Value</td> <td>Also Value</td> </tr> </table>
这个结果完全符合你期望的垂直表格布局,而且即使后续新增了IBAN这类所有Book都包含的元素,代码也会自动将其作为新的一行加入表格,不需要修改XSL代码。
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

