Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml xsl:将列表转换为二维表_Xml_Xslt - Fatal编程技术网

Xml xsl:将列表转换为二维表

Xml xsl:将列表转换为二维表,xml,xslt,Xml,Xslt,假设我有一个XML节点: <items> <item>...<item> <item>...<item> <item>...<item> <item>...<item> <item>...<item> ... </items> 我不知道如何实现的部分是 如何为测试当前节点中项元素的#创建谓词 如何获取当

假设我有一个XML节点:

<items>
    <item>...<item>
    <item>...<item>
    <item>...<item>
    <item>...<item>
    <item>...<item>
    ...
</items>
我不知道如何实现的部分是

  • 如何为测试当前节点中
    元素的#创建谓词
  • 如何获取当前节点中的第n个
    元素
根据评论更新

如何将最后一行填充为空
元素,以便每行 是否完全包含所需的单元格


这是我的工作解决方案

由于您没有提供所需的输出,此特定输出可能无法满足您的需要

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes"/>

    <xsl:template match="/*">
        <table>
            <xsl:call-template name="make-columns">
                <xsl:with-param name="nodelist" select="item"/>
            </xsl:call-template>
        </table>
    </xsl:template>

    <xsl:template name="make-columns">
        <xsl:param name="nodelist"/>
        <xsl:param name="columns-number" select="4"/>

        <tr>
            <xsl:apply-templates select="$nodelist[
                            not(position() > $columns-number)
                            ]"/>
        </tr>

        <!-- If some nodes are left, recursively call current
        template, passing only nodes that are left -->
        <xsl:if test="count($nodelist) > $columns-number">
            <xsl:call-template name="make-columns">
                <xsl:with-param name="nodelist" select="$nodelist[
                                        position() > $columns-number
                                        ]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="item">
        <td>
            <xsl:apply-templates/>
        </td>
    </xsl:template>

</xsl:stylesheet>
一、XSLT 1.0解决方案:

<xsl:template match="items">
  <table>
    <xsl:for-each-group select="item" group-by="ceiling(position() div $column_width)">
      <tr>
        <xsl:for-each select="current-group()">
          <td>
            <xsl:apply-templates/>
          </td>
        </xsl:for-each>
      </tr>
    </xsl:for-each-group>
  </table>
</xsl:template>
这里可能是不需要显式递归的最短可能解决方案之一

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="pNumCols" select="4"/>

 <xsl:template match="/*">
  <table>
   <xsl:apply-templates select="*[position() mod $pNumCols =1]"/>
  </table>
 </xsl:template>

 <xsl:template match="item">
  <tr>
    <xsl:apply-templates mode="copy" select=
    ". | following-sibling::*[not(position() >= $pNumCols)]"/>
  </tr>
 </xsl:template>

 <xsl:template match="item" mode="copy">
  <td><xsl:value-of select="."/></td>
 </xsl:template>
</xsl:stylesheet>
<items>
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
    <item>5</item>
    <item>6</item>
    <item>7</item>
    <item>8</item>
    <item>9</item>
    <item>10</item>
    <item>11</item>
    <item>12</item>
    <item>13</item>
    <item>14</item>
    <item>15</item>
    <item>16</item>
    <item>17</item>
    <item>18</item>
    <item>19</item>
    <item>20</item>
    <item>21</item>
    <item>22</item>
    <item>23</item>
    <item>24</item>
    <item>25</item>
    <item>26</item>
    <item>27</item>
</items>
<table>
   <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
      <td>4</td>
   </tr>
   <tr>
      <td>5</td>
      <td>6</td>
      <td>7</td>
      <td>8</td>
   </tr>
   <tr>
      <td>9</td>
      <td>10</td>
      <td>11</td>
      <td>12</td>
   </tr>
   <tr>
      <td>13</td>
      <td>14</td>
      <td>15</td>
      <td>16</td>
   </tr>
   <tr>
      <td>17</td>
      <td>18</td>
      <td>19</td>
      <td>20</td>
   </tr>
   <tr>
      <td>21</td>
      <td>22</td>
      <td>23</td>
      <td>24</td>
   </tr>
   <tr>
      <td>25</td>
      <td>26</td>
      <td>27</td>
   </tr>
</table>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:param name="pNumCols" select="4"/>

    <xsl:template match="items">
        <table>
            <xsl:for-each-group select="item"
            group-by="(position()-1) idiv $pNumCols">
                <tr>
                    <xsl:for-each select="current-group()">
                        <td>
                            <xsl:apply-templates/>
                        </td>
                    </xsl:for-each>
                </tr>
            </xsl:for-each-group>
        </table>
    </xsl:template>
</xsl:stylesheet>
与以前一样应用于同一个XML文档,此转换将产生相同、正确的结果。

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:my="http://localhost"
    exclude-result-prefixes="my">
    <xsl:output method="html" indent="yes"/>

    <my:layout>
        <td/><td/><td/><td/>
        <td/><td/><td/><td/>
        <td/><td/><td/><td/>
        <td/><td/><td/><td/>
    </my:layout>

    <xsl:template match="/*">
        <table>
            <xsl:call-template name="make-columns">
                <xsl:with-param name="nodelist" select="item"/>
            </xsl:call-template>
        </table>
    </xsl:template>

    <xsl:template name="make-columns">
        <xsl:param name="nodelist"/>
        <xsl:param name="columns-number" select="4"/>

        <tr>
            <xsl:apply-templates select="$nodelist[
                            not(position() > $columns-number)
                            ]"/>
            <xsl:if test="count($nodelist) &lt; $columns-number">
                <xsl:copy-of select="document('')/*/my:layout/td[
                    position() &lt;= $columns-number - count($nodelist)
                    ]"/>
            </xsl:if>
        </tr>

        <!-- If some nodes are left, recursively call current
        template, passing only nodes that are left -->
        <xsl:if test="count($nodelist) > $columns-number">
            <xsl:call-template name="make-columns">
                <xsl:with-param name="nodelist" select="$nodelist[
                                        position() > $columns-number
                                        ]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="item">
        <td>
            <xsl:apply-templates/>
        </td>
    </xsl:template>

</xsl:stylesheet>
说明

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="pNumCols" select="4"/>

 <xsl:template match="/*">
  <table>
   <xsl:apply-templates select="*[position() mod $pNumCols =1]"/>
  </table>
 </xsl:template>

 <xsl:template match="item">
  <tr>
    <xsl:apply-templates mode="copy" select=
    ". | following-sibling::*[not(position() >= $pNumCols)]"/>
  </tr>
 </xsl:template>

 <xsl:template match="item" mode="copy">
  <td><xsl:value-of select="."/></td>
 </xsl:template>
</xsl:stylesheet>
<items>
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
    <item>5</item>
    <item>6</item>
    <item>7</item>
    <item>8</item>
    <item>9</item>
    <item>10</item>
    <item>11</item>
    <item>12</item>
    <item>13</item>
    <item>14</item>
    <item>15</item>
    <item>16</item>
    <item>17</item>
    <item>18</item>
    <item>19</item>
    <item>20</item>
    <item>21</item>
    <item>22</item>
    <item>23</item>
    <item>24</item>
    <item>25</item>
    <item>26</item>
    <item>27</item>
</items>
<table>
   <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
      <td>4</td>
   </tr>
   <tr>
      <td>5</td>
      <td>6</td>
      <td>7</td>
      <td>8</td>
   </tr>
   <tr>
      <td>9</td>
      <td>10</td>
      <td>11</td>
      <td>12</td>
   </tr>
   <tr>
      <td>13</td>
      <td>14</td>
      <td>15</td>
      <td>16</td>
   </tr>
   <tr>
      <td>17</td>
      <td>18</td>
      <td>19</td>
      <td>20</td>
   </tr>
   <tr>
      <td>21</td>
      <td>22</td>
      <td>23</td>
      <td>24</td>
   </tr>
   <tr>
      <td>25</td>
      <td>26</td>
      <td>27</td>
   </tr>
</table>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:param name="pNumCols" select="4"/>

    <xsl:template match="items">
        <table>
            <xsl:for-each-group select="item"
            group-by="(position()-1) idiv $pNumCols">
                <tr>
                    <xsl:for-each select="current-group()">
                        <td>
                            <xsl:apply-templates/>
                        </td>
                    </xsl:for-each>
                </tr>
            </xsl:for-each-group>
        </table>
    </xsl:template>
</xsl:stylesheet>
  • 该指令用于选择不同组的
    项目
    元素,其中每组包含必须在一行中表示的元素

  • 为此使用标准XPath 2.0运算符

  • XSLT 2.0函数包含当前行中必须显示的所有项


  • 对于每个组,您都可以获得更优雅的解决方案:

    <xsl:template match="items">
      <table>
        <xsl:for-each-group select="item" group-by="ceiling(position() div $column_width)">
          <tr>
            <xsl:for-each select="current-group()">
              <td>
                <xsl:apply-templates/>
              </td>
            </xsl:for-each>
          </tr>
        </xsl:for-each-group>
      </table>
    </xsl:template>
    

    仅就样式而言,此XSLT 1.0样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:param name="pColumns" select="4"/>
        <xsl:template match="/*">
            <table>
                <xsl:apply-templates select="*[position() mod $pColumns = 1]"/>
            </table>
        </xsl:template>
        <xsl:template match="item">
            <xsl:variable name="vItems"
                          select=".|following-sibling::*[$pColumns > position()]"/>
            <tr>
                <xsl:apply-templates select="$vItems" mode="makeCell"/>
                <xsl:call-template name="fillRow">
                    <xsl:with-param name="pItems" 
                                    select="$pColumns - count($vItems)"/>
                </xsl:call-template>
            </tr>
        </xsl:template>
        <xsl:template match="item" mode="makeCell">
            <td>
                <xsl:value-of select="."/>
            </td>
        </xsl:template>
        <xsl:template name="fillRow">
            <xsl:param name="pItems" select="0"/>
            <xsl:if test="$pItems">
                <td/>
                <xsl:call-template name="fillRow">
                    <xsl:with-param name="pItems" select="$pItems - 1"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>
    
    
    
    使用@Flack的答案输入,输出:

    <table>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
            <td>4</td>
        </tr>
        <tr>
            <td>5</td>
            <td>6</td>
            <td>7</td>
            <td>8</td>
        </tr>
        <tr>
            <td>9</td>
            <td>10</td>
            <td>11</td>
            <td>12</td>
        </tr>
        <tr>
            <td>13</td>
            <td>14</td>
            <td>15</td>
            <td>16</td>
        </tr>
        <tr>
            <td>17</td>
            <td>18</td>
            <td>19</td>
            <td>20</td>
        </tr>
        <tr>
            <td>21</td>
            <td>22</td>
            <td>23</td>
            <td>24</td>
        </tr>
        <tr>
            <td>25</td>
            <td>26</td>
            <td>27</td>
            <td />
        </tr>
    </table>
    
    
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    您如何编辑它,使其在最后一行中填充空元素,使每行包含4个单元格?编辑的更新中的
    副本似乎会在Firefox中导致错误。。。。我想我只需要添加一个
    调用模板
    并传入
    count($nodelist)-$columns number
    @Jason S,在我的3.6版本中运行良好。可能是命名空间uri正在解决问题。是的,你可以使用一个小的有限循环。我将发布更新。我想这是一个更好的方法。@Flack:+1费了很大的力气,除此之外,我认为最后一个正确的解决方案是许多命名模板…@Alejandro。在XSLT中,没有那么多方法进行封装。虽然我同意,但我仍然认为这在很大程度上是一个风格问题。好问题,+1。请参阅我的答案,以获得可能最短的解决方案,该解决方案甚至不使用任何显式递归。:)还添加了XSLT 2.0解决方案。:)这将创建一个有四行的表,而不是一个有四列的表!非常感谢。用天花板(a div b)代替mod b在XPath/XSLT2.0中有一个
    idiv
    操作符(整数除法)
    <table>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
            <td>4</td>
        </tr>
        <tr>
            <td>5</td>
            <td>6</td>
            <td>7</td>
            <td>8</td>
        </tr>
        <tr>
            <td>9</td>
            <td>10</td>
            <td>11</td>
            <td>12</td>
        </tr>
        <tr>
            <td>13</td>
            <td>14</td>
            <td>15</td>
            <td>16</td>
        </tr>
        <tr>
            <td>17</td>
            <td>18</td>
            <td>19</td>
            <td>20</td>
        </tr>
        <tr>
            <td>21</td>
            <td>22</td>
            <td>23</td>
            <td>24</td>
        </tr>
        <tr>
            <td>25</td>
            <td>26</td>
            <td>27</td>
            <td />
        </tr>
    </table>