Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.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 如何使用XSLT将操作重复X次_Xml_Xslt_Forms - Fatal编程技术网

Xml 如何使用XSLT将操作重复X次

Xml 如何使用XSLT将操作重复X次,xml,xslt,forms,Xml,Xslt,Forms,我必须用XSLT填充总共20个元素。在我的XML代码中,我有一个带有值的,无论如何都不能写20个表单 我的XML: <output> <select> <id>1</id> <name>One</name> </select> <select> <id>2</id> <name>

我必须用XSLT填充总共20个元素。在我的XML代码中,我有一个带有值的
,无论如何都不能写20个表单

我的XML:

<output>
    <select>
        <id>1</id>
        <name>One</name>
    </select>
    <select>
        <id>2</id>
        <name>Two</name>
    </select>
    <select>
        <id>3</id>
        <name>Three</name>
    </select>
    <!-- An more -->
</output>

1.
一个
2.
两个
3.
三
我的XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">   
    <xsl:template match="/">
        <html>

            <body>
        <select name="values[]">
            <option value="0"> </option>
            <xsl:for-each select="output/select">
                <option>
                    <xsl:attribute name="value"><xsl:value-of select="id"></xsl:attribute>
                    <xsl:value-of select="name" />
                </option>
            </xsl:for-each>
        </select>
            </body>

        </html>
    </xsl:template>
</xsl:stylesheet>

期望输出:

<html>
    <body>

        <select name="values[]">
            <option value="0"> </option>
            <option value="1">One</option>
            <option value="2">Two</option>
            <option value="3">Three</option>
        </select>
        <!-- But 20 times -->   

    </body>
</html>

一个
两个
三

首先,对每个使用模板而不是
,然后可以使用递归模板调用来模拟for循环(如图所示):


1.
20

解决此问题的一种方法是使用XPath
document()
函数将选项设置加载到变量中,然后使用递归模板:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:variable name="options" select="document('options.xml')" />

  <xsl:template match="/">
    <html>
      <body>
        <xsl:call-template name="InsertOptions">
          <xsl:with-param name="count" select="20" />
        </xsl:call-template>
      </body>
    </html>
  </xsl:template>

  <xsl:template name="InsertOptions">
    <xsl:param name="index" select="1"/>
    <xsl:param name="count" select="1"/>

    <xsl:if test="$index &lt;= $count">
      <select name="{concat('values', count, '[]')}">
        <option value="0"> </option>
        <xsl:for-each select="$options/output/select">
          <option value="{id}"><xsl:value-of select="name" /></option>
        </xsl:for-each>
      </select>
      <xsl:call-template name="InsertOptions">
        <xsl:with-param name="index" select="$index + 1" />
        <xsl:with-param name="count" select="$count" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

I.XSLT 1.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:template match="/">
  <html>
    <body>
      <xsl:apply-templates select="*" mode="iter">
       <xsl:with-param name="pCount" select="20"/>
      </xsl:apply-templates>
    </body>
  </html>
 </xsl:template>

 <xsl:template match="/*" mode="iter">
  <xsl:param name="pCount" select="0"/>

  <xsl:if test="$pCount > 0">
      <select name="values[]">
      <xsl:apply-templates/>
      </select>
    <xsl:apply-templates select="." mode="iter">
      <xsl:with-param name="pCount" select="$pCount -1"/>
    </xsl:apply-templates>
  </xsl:if>
 </xsl:template>

 <xsl:template match="select">
  <option value="{id}"><xsl:value-of select="name"/></option>
 </xsl:template>
</xsl:stylesheet>
<output>
    <select>
        <id>0</id>
        <name> </name>
    </select>
    <select>
        <id>1</id>
        <name>One</name>
    </select>
    <select>
        <id>2</id>
        <name>Two</name>
    </select>
    <select>
        <id>3</id>
        <name>Three</name>
    </select>
</output>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="f xs"
 >
 <xsl:import href="../f/func-repeat.xsl"/>
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vSelects" as="element()">
   <select name="values[]">
    <xsl:apply-templates select="/*/select"/>
   </select>
 </xsl:variable>

  <xsl:template match="/">
    <html>
      <body>
       <xsl:sequence select="f:repeat($vSelects, 20)"/>
      </body>
    </html>
  </xsl:template>

 <xsl:template match="select">
  <option value="{id}"><xsl:value-of select="name"/></option>
 </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="xs f"
>

  <xsl:function name="f:repeat" as="item()+">
    <xsl:param name="pThis" as="item()"/>
    <xsl:param name="pTimes" as="xs:integer"/>

    <xsl:for-each select="1 to $pTimes">
      <xsl:sequence select="$pThis"/>
    </xsl:for-each>
  </xsl:function>
</xsl:stylesheet>
这里我们使用一个非常通用的函数,它将重复第一个参数
N
(第二个参数的值)次

函数
f:repeat()
本身非常简单

<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:template match="/">
  <html>
    <body>
      <xsl:apply-templates select="*" mode="iter">
       <xsl:with-param name="pCount" select="20"/>
      </xsl:apply-templates>
    </body>
  </html>
 </xsl:template>

 <xsl:template match="/*" mode="iter">
  <xsl:param name="pCount" select="0"/>

  <xsl:if test="$pCount > 0">
      <select name="values[]">
      <xsl:apply-templates/>
      </select>
    <xsl:apply-templates select="." mode="iter">
      <xsl:with-param name="pCount" select="$pCount -1"/>
    </xsl:apply-templates>
  </xsl:if>
 </xsl:template>

 <xsl:template match="select">
  <option value="{id}"><xsl:value-of select="name"/></option>
 </xsl:template>
</xsl:stylesheet>
<output>
    <select>
        <id>0</id>
        <name> </name>
    </select>
    <select>
        <id>1</id>
        <name>One</name>
    </select>
    <select>
        <id>2</id>
        <name>Two</name>
    </select>
    <select>
        <id>3</id>
        <name>Three</name>
    </select>
</output>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="f xs"
 >
 <xsl:import href="../f/func-repeat.xsl"/>
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vSelects" as="element()">
   <select name="values[]">
    <xsl:apply-templates select="/*/select"/>
   </select>
 </xsl:variable>

  <xsl:template match="/">
    <html>
      <body>
       <xsl:sequence select="f:repeat($vSelects, 20)"/>
      </body>
    </html>
  </xsl:template>

 <xsl:template match="select">
  <option value="{id}"><xsl:value-of select="name"/></option>
 </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="xs f"
>

  <xsl:function name="f:repeat" as="item()+">
    <xsl:param name="pThis" as="item()"/>
    <xsl:param name="pTimes" as="xs:integer"/>

    <xsl:for-each select="1 to $pTimes">
      <xsl:sequence select="$pThis"/>
    </xsl:for-each>
  </xsl:function>
</xsl:stylesheet>

带有“如果使用此模式,您将下地狱”的其他解决方案:


如果您的xml结构在$structure中至少包含$n个元素(甚至嵌套):

<xsl:for-each select="$structure//*[position() < $n]">
   <!-- do whatever you want -->
</xsl:for-each>


是的,它很粗糙,但在概念上比递归函数更容易。

好问题(+1)。有关特定XSLT 1.0解决方案和另一个通用XSLT 2.0解决方案,请参见我的答案。如果将计数减为0,则不需要传入$count参数