xml – 使用XSLT,如何在节点属性的位置生成包含元素的表?

给出以下 XML

<items>
    <item>
        <name>A</name>
        <address>0</address>
        <start>0</start>
        <size>2</size>
    </item>
    <item>
        <name>B</name>
        <address>1</address>
        <start>2</start>
        <size>4</size>
    </item>
    <item>
        <name>C</name>
        <address>2</address>
        <start>5</start>
        <size>2</size>
    </item>
</items>

我想生成以下输出,包括colspan的

+---------+------+------+------+------+------+------+------+------+
| Address | 7    | 6    | 5    | 4    | 3    | 2    | 1    | 0    |
+---------+------+------+------+------+------+------+------+------+
| 0       |      |      |      |      |      |      | A           |
+---------+------+------+------+------+------+------+------+------+
| 1       |      |      | B                         |      |      |
+---------+------+------+------+------+------+------+------+------+
| 2       |      | C           |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+
| 3       |      |      |      |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+

我想我可以用一个可变的xslt变量来完成这个,但是,唉,没有这样的事情.

它甚至可能吗?怎么样?

编辑:

还有两个要求:

>也必须有两个项目存在于同一地址
>可能存在空地址,必须在输出生成

例如:

<items>
    <item>
        <name>D</name>
        <address>0</address>
        <start>0</start>
        <size>2</size>
    </item>
    <item>
        <name>E</name>
        <address>0</address>
        <start>3</start>
        <size>4</size>
    </item>
    <item>
        <name>F</name>
        <address>7</address>
        <start>5</start>
        <size>2</size>
    </item>
</items>

应该产量:

+---------+------+------+------+------+------+------+------+------+
| Address | 7    | 6    | 5    | 4    | 3    | 2    | 1    | 0    |
+---------+------+------+------+------+------+------+------+------+
| 0       |      | E                         |      | D           |
+---------+------+------+------+------+------+------+------+------+
| 1       |      |      |      |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+
| 2       |      |      |      |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+
| 3       |      |      |      |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+
| 4       |      |      |      |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+
| 5       |      |      |      |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+
| 6       |      |      |      |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+
| 7       |      | F           |      |      |      |      |      |
+---------+------+------+------+------+------+------+------+------+

输出格式(text / html)并不重要.

解决方法

这是修订后的问题的新XSLT 2.0样式表.在我看来它有点难看,但它应该做的工作:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xsd"
  version="2.0">

  <xsl:output method="html" indent="yes"/>

  <xsl:variable name="cols" as="xsd:integer*"
    select="reverse(0 to (max(/items/item/xsd:integer((start + size - 1))) + 1))"/>

  <xsl:variable name="addresses" as="xsd:integer*"
    select="0 to max(/items/item/xsd:integer(address))"/>

  <xsl:template match="/">
    <html lang="en">
      <head>
        <title>Example</title>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="items">
    <table border="1">
      <thead>
        <tr>
          <th>Address</th>
          <xsl:for-each select="$cols">
            <th width="100">
              <xsl:value-of select="."/>
            </th>
          </xsl:for-each>
        </tr>
      </thead>
      <tbody>
        <xsl:variable name="items" as="element(item)*" select="item"/>
        <xsl:for-each select="$addresses">
          <tr>
            <th>
              <xsl:value-of select="."/>
            </th>
            <xsl:variable name="cells" as="element(cell)*">
              <xsl:for-each select="$items[address = current()]">
                <xsl:sort select="xsd:integer(start) + xsd:integer(size)" order="descending"/>
                <cell>
                  <xsl:copy-of select="name"/>
                  <start><xsl:value-of select="start + size - 1"/></start>
                  <colspan><xsl:value-of select="size"/></colspan>
                </cell>
              </xsl:for-each>
            </xsl:variable>
            <xsl:for-each select="$cols">
              <xsl:variable name="cell" select="$cells[start = current()]"/>
              <xsl:choose>
                <xsl:when test="$cell">
                  <td colspan="{$cell/colspan}">
                    <xsl:value-of select="$cell/name"/>
                  </td>
                </xsl:when>
                <xsl:when test="$cells[current() &lt; start and current() &gt;= (start - colspan + 1)]"></xsl:when>
                <xsl:otherwise>
                  <td>&#160;</td>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:for-each>
          </tr>
        </xsl:for-each>
      </tbody>
    </table>
  </xsl:template>

</xsl:stylesheet>

当将Saxon 9应用于最新的XML输入时,结果如下:

<html lang="en">
   <head>
      <Meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Example</title>
   </head>
   <body>
      <table border="1">
         <thead>
            <tr>
               <th>Address</th>
               <th width="100">7</th>
               <th width="100">6</th>
               <th width="100">5</th>
               <th width="100">4</th>
               <th width="100">3</th>
               <th width="100">2</th>
               <th width="100">1</th>
               <th width="100">0</th>
            </tr>
         </thead>
         <tbody>
            <tr>
               <th>0</th>
               <td>&nbsp;</td>
               <td colspan="4">E</td>
               <td>&nbsp;</td>
               <td colspan="2">D</td>
            </tr>
            <tr>
               <th>1</th>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
            </tr>
            <tr>
               <th>2</th>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
            </tr>
            <tr>
               <th>3</th>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
            </tr>
            <tr>
               <th>4</th>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
            </tr>
            <tr>
               <th>5</th>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
            </tr>
            <tr>
               <th>6</th>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
            </tr>
            <tr>
               <th>7</th>
               <td>&nbsp;</td>
               <td colspan="2">F</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
               <td>&nbsp;</td>
            </tr>
         </tbody>
      </table>
   </body>
</html>

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念