将样式应用于动态XML

时间:2014-07-02 10:51:48

标签: xml xslt

我是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元素并将其放入表头并选择相应的值? enter image description here

1 个答案:

答案 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>