使用xslt将结构化对象的xml列表转换为具有多列的html表

时间:2011-05-19 10:50:12

标签: xml xslt

我有以下XML文件:

<PASS>
<FIRMWARE Unit="1" Group="FIRM">
  <test name="ACPI" ID="ACPI" />
</FIRMWARE>
<NETWORK Unit="2" Group="NTWK">
  <test name="Controller Test" ID="Ctlr" />
</NETWORK>
<NETWORK Unit="1" Group="NTWK">
  <test name="Controller Test" ID="Ctlr" />
</NETWORK>
<ATA Unit="1" Group="ATA-">
  <test name="Serial Controllers" ID="SATA" />
</ATA>
<PARALLEL_PORT Unit="1" Group="LPT-">
  <test name="Verify Controller" ID="Ctrl" />
  <test name="Check Status Port" ID="Stat" />
  <test name="Interrupt Test" ID="Int-" />
</PARALLEL_PORT>
<SERIAL_PORT Unit="4" Group="COM-">
  <test name="Interrupt" ID="Intr" />
  <test name="Line Control" ID="Line" />
  <test name="Test Loopback" ID="LpBk" />
  <test name="Test Internal FIFO" ID="FIFO" />
  <test name="Test Internal Loopback" ID="ILBk" />
</SERIAL_PORT>
<SERIAL_PORT Unit="3" Group="COM-">
  <test name="Interrupt" ID="Intr" />
  <test name="Line Control" ID="Line" />
  <test name="Test Loopback" ID="LpBk" />
  <test name="Test Internal FIFO" ID="FIFO" />
  <test name="Test Internal Loopback" ID="ILBk" />
</SERIAL_PORT>
</PASS>

使用现有的XSL文件,我将所有测试结果都放在一列中。这对于打印等不太实用。如何创建包含2列或更多列的表?

<xsl:template match="PASS">
<div class="component">
  <h4>PASSED</h4>
  <xsl:call-template name="outputtable">
    <xsl:with-param name="result" select="'PASSED'" />
  </xsl:call-template>
</div>
</xsl:template>

<xsl:template name="outputtable">
<div class="attributes">
  <xsl:variable name="resultlist" select="*" />
  <xsl:variable name="index" select="count(child::*)" />
  <xsl:for-each select="$resultlist">
    <xsl:variable name="Unit" select="@Unit" />
    <xsl:variable name="Group" select="@Group" />
    <p class="attrtitle">
      <xsl:value-of select="name()" />
      Unit:
      <xsl:value-of select="$Unit" />
    </p>
    <xsl:variable name="testtype" select="*" />
    <xsl:for-each select="$testtype">
      <p class="attribute">
        <xsl:value-of select="@name" />
      </p>
    </xsl:for-each>
    <p />
  </xsl:for-each>
</div>

我已经搜索过解决方案并找到以下链接: Use xslt to convert xml list into html table with multiple columnshttp://blogs.msdn.com/b/kaevans/archive/2003/04/03/4754.aspx

我所拥有的情况相当不同我有结构对象而不是简单的“Item”或“ComputerName”,另一个缺点是那些测试不是同一类型(等等)。此XML报告由非OSS软件自动构建,因此我无法在创建时更改它。

我会很高兴得到任何想法!

1 个答案:

答案 0 :(得分:0)

此转化

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="pnumCols" select="3"/>

    <xsl:template match="PASS">
        <div class="component">
            <h4>PASSED</h4>
            <div class="attributes">
             <table border="1">
                <xsl:apply-templates select=
                  "*[position() mod $pnumCols = 1]"/>
             </table>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="PASS/*">
     <tr>
      <xsl:apply-templates mode="process" select=
       ".|following-sibling::*[not(position() > $pnumCols -1)]"/>
     </tr>
    </xsl:template>

    <xsl:template match="PASS/*" mode="process">
     <xsl:variable name="Unit" select="@Unit" />
     <xsl:variable name="Group" select="@Group" />
     <td>
         <p class="attrtitle">
            <xsl:value-of select="name()" />       Unit:
            <xsl:value-of select="$Unit" />
         </p>
         <xsl:variable name="testtype" select="*" />
         <xsl:for-each select="$testtype">
            <p class="attribute">
                <xsl:value-of select="@name" />
            </p>
         </xsl:for-each>
         <p />
     </td>
    </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<PASS>
    <FIRMWARE Unit="1" Group="FIRM">
        <test name="ACPI" ID="ACPI" />
    </FIRMWARE>
    <NETWORK Unit="2" Group="NTWK">
        <test name="Controller Test" ID="Ctlr" />
    </NETWORK>
    <NETWORK Unit="1" Group="NTWK">
        <test name="Controller Test" ID="Ctlr" />
    </NETWORK>
    <ATA Unit="1" Group="ATA-">
        <test name="Serial Controllers" ID="SATA" />
    </ATA>
    <PARALLEL_PORT Unit="1" Group="LPT-">
        <test name="Verify Controller" ID="Ctrl" />
        <test name="Check Status Port" ID="Stat" />
        <test name="Interrupt Test" ID="Int-" />
    </PARALLEL_PORT>
    <SERIAL_PORT Unit="4" Group="COM-">
        <test name="Interrupt" ID="Intr" />
        <test name="Line Control" ID="Line" />
        <test name="Test Loopback" ID="LpBk" />
        <test name="Test Internal FIFO" ID="FIFO" />
        <test name="Test Internal Loopback" ID="ILBk" />
    </SERIAL_PORT>
    <SERIAL_PORT Unit="3" Group="COM-">
        <test name="Interrupt" ID="Intr" />
        <test name="Line Control" ID="Line" />
        <test name="Test Loopback" ID="LpBk" />
        <test name="Test Internal FIFO" ID="FIFO" />
        <test name="Test Internal Loopback" ID="ILBk" />
    </SERIAL_PORT>
</PASS>

$pnumCols - 列格式生成结果,在此特定情况下,pnumCols为3:

<div class="component">
   <h4>PASSED</h4>
   <div class="attributes">
      <table border="1">
         <tr>
            <td>
               <p class="attrtitle">FIRMWARE       Unit:
            1</p>
               <p class="attribute">ACPI</p>
               <p/>
            </td>
            <td>
               <p class="attrtitle">NETWORK       Unit:
            2</p>
               <p class="attribute">Controller Test</p>
               <p/>
            </td>
            <td>
               <p class="attrtitle">NETWORK       Unit:
            1</p>
               <p class="attribute">Controller Test</p>
               <p/>
            </td>
         </tr>
         <tr>
            <td>
               <p class="attrtitle">ATA       Unit:
            1</p>
               <p class="attribute">Serial Controllers</p>
               <p/>
            </td>
            <td>
               <p class="attrtitle">PARALLEL_PORT       Unit:
            1</p>
               <p class="attribute">Verify Controller</p>
               <p class="attribute">Check Status Port</p>
               <p class="attribute">Interrupt Test</p>
               <p/>
            </td>
            <td>
               <p class="attrtitle">SERIAL_PORT       Unit:
            4</p>
               <p class="attribute">Interrupt</p>
               <p class="attribute">Line Control</p>
               <p class="attribute">Test Loopback</p>
               <p class="attribute">Test Internal FIFO</p>
               <p class="attribute">Test Internal Loopback</p>
               <p/>
            </td>
         </tr>
         <tr>
            <td>
               <p class="attrtitle">SERIAL_PORT       Unit:
            3</p>
               <p class="attribute">Interrupt</p>
               <p class="attribute">Line Control</p>
               <p class="attribute">Test Loopback</p>
               <p class="attribute">Test Internal FIFO</p>
               <p class="attribute">Test Internal Loopback</p>
               <p/>
            </td>
         </tr>
      </table>
   </div>
</div>

解释:我们使用两个模板 - 一个用于连续排列一组$pnumCols个连续结果,另一个用于mode="process",以实际生成内容在那一行内。