javascript - 使用 XSLT 或任何其他方法的 XML 到 HTML 表
问题描述
我有一个包含以下 XML 数据的 XML 文件。
<group1>
<item1>val1</item1>
<item2>val2</item2>
<group2>
<item3>val3</item3>
<item4>val4</item4>
<group3>
<item5>val5</item5>
</group3>
</group2>
<group2>
<item3>val6</item3>
<item4>val7</item4>
<group3>
<item5>val8</item5>
</group3>
</group2>
<group4>
<item6>val9</item6>
<item7>val10</item7>
</group4>
<group4>
<item6>val11</item6>
<item7>val12</item7>
</group4>
像 HTML 表格一样
<table --for group1>
<tr>
<th>item1</th>
<th>item2</th>
</tr>
<tr>
<td>val1</td>
<td>val2</td>
</tr>
</table>
<table --for group2>
<tr>
<th>item3</th>
<th>item4</th>
</tr>
<tr>
<td>val3</td>
<td>val4</td>
</tr>
</table>
<table --for group3>
<tr>
<th>item5</th>
</tr>
<tr>
<td>val5</td>
</tr>
</table>
<table --for group2>
<tr>
<th>item3</th>
<th>item4</th>
</tr>
<tr>
<td>val6</td>
<td>val7</td>
</tr>
</table>
<table --for group3>
<tr>
<th>item5</th>
</tr>
<tr>
<td>val8</td>
</tr>
</table>
<table --for group4>
<tr>
<th>item6</th>
<th>item7</th>
</tr>
<tr>
<td>val9</td>
<td>val10</td>
</tr>
<tr>
<td>val11</td>
<td>val12</td>
</tr>
</table>
在 group1 中有两个 group2,其中有 group3。因此,每个 group2 应该是一个单独的表,后面有 group3 表。有两个 group4,但其中没有另一个组。所以两个 group4 应该在一个表中。
注意:每个组中可以嵌套任意数量的组。
我想要实现的是在 Oracle bi 发布者数据模型表视图中显示查询结果。
能够通过为不同的深度使用不同的 XSL 模板来实现固定的深度,但不知道在深度不固定时如何做。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<HTML>
<BODY>
<xsl:apply-templates />
</BODY>
</HTML>
</xsl:template>
<xsl:template match="/*">
<TABLE BORDER="1">
<TR>
<xsl:for-each select="*/*">
<xsl:choose>
<xsl:when test="child::*">
<!-- <h1>
<xsl:value-of select="local-name()" />
</h1> -->
</xsl:when>
<xsl:otherwise>
<!-- <h1>
<xsl:value-of select="local-name()" />
</h1> -->
<xsl:for-each select=".">
<TD>
<xsl:value-of select="local-name()" />
</TD>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:apply-templates />
</TR>
</TABLE>
</xsl:template>
<xsl:template match="/*/*">
<TR>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="child::*">
<h1>
<xsl:value-of select="local-name()" />
</h1>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:apply-templates select="." />
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</TR>
</xsl:template>
<!-- <xsl:template match="/*/*/*">
<xsl:choose>
<xsl:when test="child::*">
<TABLE BORDER="1">
<TR>
<xsl:for-each select="*/*">
<TD>
<xsl:value-of select="local-name()" />
</TD>
</xsl:for-each>
</TR>
</TABLE>
<xsl:value-of select="." />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template> -->
解决方案
在大多数情况下,您似乎只想展平嵌套层次结构,因此为此使用递归。此外,要合并/分组最深的级别,请使用分组,例如在 XSLT 1 中,使用 Muenchian 分组和键:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>
<xsl:key name="table-group"
match="*[* and not(*/*)]"
use="concat(generate-id(..), '|', local-name())"/>
<xsl:template match="*[*]">
<table>
<thead>
<tr>
<xsl:apply-templates select="*[not(*)]" mode="header"/>
</tr>
</thead>
<tbody>
<tr>
<xsl:apply-templates select="*[not(*)]"/>
</tr>
</tbody>
</table>
<xsl:apply-templates select="*[*/*]"/>
<xsl:apply-templates
select="*[* and not(*/*)][generate-id() = generate-id(key('table-group', concat(generate-id(..), '|', local-name()))[1])]" mode="merge-groups"/>
</xsl:template>
<xsl:template match="*[not(*)]" mode="header">
<th>
<xsl:value-of select="local-name()"/>
</th>
</xsl:template>
<xsl:template match="*[not(*)]">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
<xsl:template match="*[*]" mode="merge-groups">
<table>
<thead>
<tr>
<xsl:apply-templates select="*[not(*)]" mode="header"/>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="key('table-group', concat(generate-id(..), '|', local-name()))" mode="row"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="*" mode="row">
<tr>
<xsl:apply-templates select="*"/>
</tr>
</xsl:template>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/ncnu9AZ/1
如果您不熟悉 XSLT 1 中的 Muenchian 分组,请使用任何有关 XSLT 1 中 Muenchian 分组的教科书或在线介绍来熟悉该方法,一个在线资源是http://www.jenitennison.com/xslt/grouping/muenchian .html。
在上述样式表中,由于需要对仅在父容器上下文中未进一步嵌套的元素进行分组,因此使用的键包括父元素的生成 id ( generate-id(...)
)。因此,在元素的上下文中调用key('table-group', concat(generate-id(..), '|', local-name()))
为我们提供了一个节点集,其中包含一组在同一个父节点中具有相同名称的元素。通过整个谓词[generate-id() = generate-id(key('table-group', concat(generate-id(..), '|', local-name()))[1])]
,我们只需确定该节点集中文档顺序中的第一个元素当前正在被处理。这generate-id() = generate-id(key(...)[1])
基本上是一种 XSLT 1 的方式,将 XSLT 2 或更高版本中可以执行的操作. is key(...)[1]
表示为 ,即检查谓词中上下文元素的节点身份以及该key(...)
调用返回的第一个节点。
推荐阅读
- angular - 从 json 中获取数据以进行 p-dropdown
- python - 如何将此字典列表转换为字典?
- r - 使用 expand_limits 的 ggplot 结合使用 get 函数的 facet_wrap 崩溃
- kubernetes - Kubernetes Admin 没有相应地显示 pod
- c# - How to cut data from a file?
- safari - WebGL:getUniformLocation 在 Safari 上失败
- codenameone - ContactsManager 缺少方法?
- javascript - TypeScript error when passing parameters between functions
- python - 蜘蛛IDE;由于奇怪的日志记录问题而重置 IPython 控制台状态
- python - Python SSH Library