我是XML和XSL的新手 创建了一个XML,它的内容可以是动态的,即在某些情况下,某些元素可能不存在,我想将它作为HTML表输出,我该如何编写这样的XSL?
示例XML,在某些情况下,配置元素可能不完全存在,
<Stat>
<Name></Name>
<Hardware></Hardware>
<Software></Version>
<Version></Version>
<State></State>
</Stat>
<Configuration>
<Up>
<Option1>2000</Option1>
<Option2>2500000</Option2>
<Option3>0</Option3>
<Option4>0</Option4>
<Option5>NA</Option5>
</Uplink>
<Down>
<Option1>2000</Option1>
<Option2>2500000</Option2>
<Option3>0</Option3>
<Option4>0</Option4>
<Option5>NA</Option5>
</Down>
</Configuration>
预期产出: 带有行和列的HTML表, 是否可以使用某种递归解决方案自动转到每个XML元素并将其放入表头并选择相应的值?
答案 0 :(得分:1)
假设您的XML格式正确并且有一个根元素,那么您对标题的那种情况就像这样
<th colspan="{count(Stat/*)}">
<xsl:if test="Configuration[*]">
<xsl:attribute name="rowspan">2</xsl:attribute>
<xsl:text>Stat</xsl:text>
</xsl:if>
</th>
这将输出“Stat”标题的标题单元格。请注意在执行colspan时使用“属性值模板”。花括号表示要计算的表达式,而不是字面输出。
xsl:if 测试是否存在配置项,如果存在,则添加rowspan。
同样,“配置”的标题也是如此
<xsl:if test="Configuration[*]">
<th colspan="{count(Configuration/*/*)}">
<xsl:text>Configuration</xsl:text>
</th>
</xsl:if>
对于包含“UP”和“DOWN”的标题行,您可以迭代配置的子元素
<tr>
<xsl:for-each select="Configuration/*">
<th colspan="{count(*)}">
<xsl:value-of select="local-name()" />
</th>
</xsl:for-each>
</tr>
执行下一行,只需要选择“Stat”的子元素和“Configuration”的子元素
<xsl:apply-templates select="Stat/*" mode="header" />
<xsl:apply-templates select="Configuration/*/*" mode="header" />
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="/*">
<table>
<tr>
<th colspan="{count(Stat/*)}">
<xsl:if test="Configuration[*]">
<xsl:attribute name="rowspan">2</xsl:attribute>
<xsl:text>Stat</xsl:text>
</xsl:if>
</th>
<xsl:if test="Configuration[*]">
<th colspan="{count(Configuration/*/*)}">
<xsl:text>Configuration</xsl:text>
</th>
</xsl:if>
</tr>
<tr>
<xsl:for-each select="Configuration/*">
<th colspan="{count(*)}">
<xsl:value-of select="local-name()" />
</th>
</xsl:for-each>
</tr>
<tr>
<xsl:apply-templates select="Stat/*" mode="header" />
<xsl:apply-templates select="Configuration/*/*" mode="header" />
</tr>
<tr>
<xsl:apply-templates select="Stat/*" mode="row" />
<xsl:apply-templates select="Configuration/*/*" mode="row" />
</tr>
</table>
</xsl:template>
<xsl:template match="*" mode="header">
<th>
<xsl:value-of select="local-name()" />
</th>
</xsl:template>
<xsl:template match="*" mode="row">
<td>
<xsl:value-of select="." />
</td>
</xsl:template>
</xsl:stylesheet>
应用于以下XML
<root>
<Stat>
<Name>A</Name>
<Hardware></Hardware>
<Software></Software>
<Version></Version>
<State></State>
</Stat>
<Configuration>
<Up>
<Option1>2000</Option1>
<Option2>2500000</Option2>
<Option3>0</Option3>
<Option4>0</Option4>
<Option5>NA</Option5>
</Up>
<Down>
<Option1>2000</Option1>
<Option2>2500000</Option2>
<Option3>0</Option3>
<Option4>0</Option4>
<Option5>NA</Option5>
</Down>
</Configuration>
</root>
以下是输出
<table>
<tr>
<th colspan="5" rowspan="2">Stat</th>
<th colspan="10">Configuration</th>
</tr>
<tr>
<th colspan="5">Up</th>
<th colspan="5">Down</th>
</tr>
<tr>
<th>Name</th>
<th>Hardware</th>
<th>Software</th>
<th>Version</th>
<th>State</th>
<th>Option1</th>
<th>Option2</th>
<th>Option3</th>
<th>Option4</th>
<th>Option5</th>
<th>Option1</th>
<th>Option2</th>
<th>Option3</th>
<th>Option4</th>
<th>Option5</th>
</tr>
<tr>
<td>A</td>
<td/>
<td/>
<td/>
<td/>
<td>2000</td>
<td>2500000</td>
<td>0</td>
<td>0</td>
<td>NA</td>
<td>2000</td>
<td>2500000</td>
<td>0</td>
<td>0</td>
<td>NA</td>
</tr>
</table>