2

此 XML 包含要附加的字符串、字符串长度和要附加的字符的详细信息。

<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
    <input>
        <string>Auckland</string>
        <len>12</len>   
        <char>#</char>
    </input>

    <input>
        <string>Ohio</string>
        <len>3</len>    
        <char>*</char>
    </input>
 </data>

我还有一个 XSLT,它应该(理想情况下)使用这个逻辑:while(字符串长度 < 指定长度){ concatenate(char, string) } else { 将字符串截断到指定长度}

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

<xsl:template name="append" match="/">
    <xsl:param name="char"></xsl:param>
    <xsl:param name="string"></xsl:param>
    <xsl:param name="len"></xsl:param>
    <xsl:value-of select="$string" />
    <html>
    <body>
    <xsl:for-each select="data/input">
        <xsl:choose>
            <xsl:when test="string-length(string) &lt; len" >
                <xsl:call-template name="append">
                    <xsl:with-param name="char" select="char" />
                    <xsl:with-param name="string" select="concat(char,string)" />
                    <xsl:with-param name="len" select="len" />
                </xsl:call-template>
            </xsl:when>
        </xsl:choose>
    </xsl:for-each>
    </body>
    </html>
</xsl:template>
</xsl:stylesheet>

出于某种原因,循环没有按预期工作。循环执行一次并显示结果。

例如,对于第一个 XML 输入,输出应该是####Auckland,但结果是#Auckland。你能帮我找出这段代码中的缺陷吗?提前感谢您的帮助。

4

3 回答 3

2

这是一个简单、高效且非递归的 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:param name="pFiller" select=
 "'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'"/>


   <xsl:template match="/">
      <html>
         <body>
            <xsl:apply-templates select="data/input"/>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="input">
    <div>
     <xsl:value-of select=
     "concat(string, substring(translate($pFiller,'$', char), 1, len))"/>
    </div>
   </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<data>
    <input>
        <string>Auckland</string>
        <len>12</len>
        <char>#</char>
    </input>
    <input>
        <string>Ohio</string>
        <len>3</len>
        <char>*</char>
    </input>
</data>

产生了想要的正确结果:

<html>
   <body>
      <div>Auckland############</div>
      <div>Ohio***</div>
   </body>
</html>
于 2013-04-04T03:43:27.550 回答
1

我假设您指定使用 XSLT 1.0;这将是 2.0 中微不足道的单行代码。但是,如果您愿意假设字符串的最大长度,我们仍然可以做一些简单的事情。

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

    <xsl:template name="append" match="/">
        <html>
            <body>
                <xsl:for-each select="data/input">
                    <xsl:value-of select="substring(concat(char,char,char,char,char,char,char,char,char,char,.), 10 + string-length() - len, len)"/>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

如果您对最大长度的假设不满意,您可以随时使用 hack:

<xsl:variable name="char" select="char"/>
<xsl:variable name="chars">
    <xsl:for-each select="//*[position() &lt;= $len]">
        <xsl:value-of select="$char"/>
    </xsl:for-each>
</xsl:variable>

len除非大于输入文档中的节点数,否则哪个有效。然后你可以做

<xsl:for-each select="data/input">
    <xsl:value-of select="substring($chars,.), string-length(), len)"/>
</xsl:for-each>

归根结底,尽管递归技术在 XSLT 1.0 中很常见,而且学习起来很有用,但在这种特殊情况下它并不是真正需要的。

于 2013-04-03T17:56:20.043 回答
0

当我尝试您的 XSLT 时,我没有得到任何文本输出,主要是因为在您的代码中,您命名的附加模板需要字符串len参数,但您分别使用字段长度参数调用它。此外,您的命名模板还匹配顶级文档元素,并且就目前而言,它将多次输出html 。

拥有一个同时也是命名模板的匹配模板是非常好的。试试这个 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="/">
      <html>
         <body>
            <xsl:apply-templates select="data/input"/>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="input" name="append">
      <xsl:param name="char" select="char"/>
      <xsl:param name="string" select="string"/>
      <xsl:param name="length" select="number(len)"/>
      <xsl:choose>
         <xsl:when test="string-length($string) &lt; $length">
            <xsl:call-template name="append">
               <xsl:with-param name="char" select="$char"/>
               <xsl:with-param name="string" select="concat($char,$string)"/>
               <xsl:with-param name="length" select="$length"/>
            </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
            <div>
               <xsl:value-of select="$string"/>
            </div>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

当应用于您的 XML 时,将输出以下内容

<html>
<body>
<div>####Auckland</div>
<div>Ohio</div>
</body>
</html>

注意参数的默认值的使用。第一次访问模板时,通过模板匹配,值将默认为相关元素的值。当您随后将其作为命名模板调用时,它将使用您传递给它的值作为参数。

编辑:如果您希望截断超过所需长度的值,只需<xsl:value-of select="$string"/>用此行替换现有值:

<xsl:value-of select="substring($string, 1, $length)"/>
于 2013-04-03T17:47:13.220 回答