在XSL中将字符附加到字符串

时间:2013-04-03 17:21:58

标签: xml xslt xslt-1.0

此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(字符串长度&lt;指定长度){  连接(char,string) } 其他 {截断字符串到指定的长度}

<?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。你能帮我识别一下这段代码中的缺陷吗?提前感谢您的帮助。

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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>

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

<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中经常出现递归技术,并且对于学习很有用,但在这种特殊情况下并不是必需的。

答案 2 :(得分:0)

当我尝试使用XSLT时,我没有得到任何文本输出,主要是因为在您的代码中,您的命名追加模板需要字符串的参数len ,但您分别使用参数 field length 调用它。此外,您的命名模板也会与顶级文档元素匹配,因此它会多次输出 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)"/>