输入:
<?xml version="1.0" encoding="utf-8" ?>
<Software>
<MS version="5.2.3.1"/>
<Java version="5.1.0.29" />
<Oracle id="A" version="1.0.1.11" />
<SQL id="P" version="1.0.1.11" />
</Software>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<table>
<tr>
<xsl:for-each select="//*[1]">
<xsl:for-each select="@*">
<td>
<xsl:value-of select="name()"/>
</td>
</xsl:for-each>
</xsl:for-each>
</tr>
<xsl:for-each select="//*">
<tr>
<xsl:value-of select="local-name()"/> ::
<xsl:for-each select="@*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
输出:
当前输出[错误]:
此脚本提供没有列名的输出 “ID”。某些“版本”列值在“id(不可见)”列中添加为 节点中没有属性名称id。例如。 MS节点有版本 仅属性因此在“id”列中输出结果添加版本信息。 请通过输出一次,可能保存并检查html以便正确理解。
<table>
<tr>
<td/>
<td>
<td>version</td>
</td>
</tr>
<tr>
<td>Software ::
</td>
</tr>
<tr>
<td>MS ::
<td>5.2.3.1</td></td>
</tr>
<tr>
<td>Java ::
<td>5.1.0.29</td></td>
</tr>
<tr>
<td>Oracle ::
<td>A</td><td>1.0.1.11</td></td>
</tr>
<tr>
<td>SQL ::
<td>P</td><td>1.0.1.11</td></td>
</tr>
</table>
预期输出:
每个属性都作为columnname / header和all列 有自己的价值。注意:属性MS,JAVA等作为列名称 不应该进行硬编码,因为属性的数量可能会在运行时发生变化。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td/>
<td>
id<td>version</td>
</td>
</tr>
<tr>
<td>MS ::</td>
<td>Not exist</td><td>5.2.3.1</td>
</tr>
<tr>
<td>Java ::</td>
<td>Not exist</td><td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle ::</td>
<td>A</td><td>1.0.1.11</td>
</tr>
<tr>
<td>SQL ::</td>
<td>P</td><td>1.0.1.11</td>
</tr>
</table>
</body>
</html>
答案 0 :(得分:0)
Hummm,我试图解决HTML问题以及您面临的问题。 这有点儿手段,但可以达到您的要求。 以下是XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<table>
<tr>
<td></td>
<td>id</td>
<xsl:for-each select="//*[1]">
<xsl:for-each select="@*">
<td><xsl:value-of select="name()"/></td>
</xsl:for-each>
</xsl:for-each>
</tr>
<xsl:for-each select="//*">
<xsl:if test="position() > 1">
<tr>
<td><xsl:value-of select="local-name()"/> ::</td>
<td>
<xsl:choose>
<xsl:when test="@id"><xsl:value-of select="@id"/></xsl:when>
<xsl:otherwise>Not Exist</xsl:otherwise>
</xsl:choose>
</td>
<td>
<xsl:if test="@version"><xsl:value-of select="@version"/></xsl:if>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
以下是它的输出:
<table>
<tr>
<td/>
<td>id</td>
<td>version</td>
</tr>
<tr>
<td>MS ::</td>
<td>Not Exist</td>
<td>5.2.3.1</td>
</tr>
<tr>
<td>Java ::</td>
<td>Not Exist</td>
<td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle ::</td>
<td>A</td>
<td>1.0.1.11</td>
</tr>
<tr>
<td>SQL ::</td>
<td>P</td>
<td>1.0.1.11</td>
</tr>
</table>
上对其进行了测试
答案 1 :(得分:0)
如果您希望为每个可能的属性名称输出一列,而不是将其限制为 id 和版本,那么(在XSLT 1.0中)您可以使用一种名为Muenchian Grouping的技术来获取不同的属性名称。
首先定义一个键,按名称查找属性
<xsl:key name="columns" match="@*" use="local-name()" />
然后,为了得到不同的名称(或者更确切地说,得到每个不同名称的第一次出现),你可以定义一个这样的变量
<xsl:variable name="columns" select="//@*[generate-id() = generate-id(key('columns', local-name())[1])]" />
然后,要输出列标题,您只需迭代此变量
即可 <xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="local-name()" /></td>
</xsl:for-each>
对于每一行,您都会采用类似的方法。假设您位于子元素上,您可以先定义一个包含当前元素属性的变量。然后,您将再次遍历列变量,并输出当前元素的相应属性的值
<xsl:variable name="attributes" select="@*" />
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="$attributes[local-name() = local-name(current())]" /></td>
</xsl:for-each>
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:key name="columns" match="@*" use="local-name()" />
<xsl:variable name="columns" select="//@*[generate-id() = generate-id(key('columns', local-name())[1])]" />
<xsl:template match="Software">
<table>
<tr>
<td>Software</td>
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="local-name()" /></td>
</xsl:for-each>
</tr>
<xsl:apply-templates select="*" />
</table>
</xsl:template>
<xsl:template match="Software/*">
<tr>
<td><xsl:value-of select="local-name()" /></td>
<xsl:variable name="attributes" select="@*" />
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="$attributes[local-name() = local-name(current())]" /></td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
这应输出以下内容
<table>
<tr>
<td>Software</td>
<td>id</td>
<td>version</td>
</tr>
<tr>
<td>MS</td>
<td/>
<td>5.2.3.1</td>
</tr>
<tr>
<td>Java</td>
<td/>
<td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle</td>
<td>A</td>
<td>1.0.1.11</td>
</tr>
<tr>
<td>SQL</td>
<td>P</td>
<td>1.0.1.11</td>
</tr>
</table>
注意,为简洁起见,我没有在属性不存在的情况下包含输出“Not exists”的代码。但它应该很简单,为此添加一个检查。 (只需将值存储在变量中,然后使用 xsl:choose )
编辑:如果您想将属性专门限制为软件元素,请尝试将密钥更改为:
<xsl:key name="columns" match="Software/*/@*" use="local-name()" />