1

我真的很感激这个任务的解决方案,它让我发疯。

我有一个 xml 元素,里面有自由文本,它可以有 2 个字符或整个段落

<Description>text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </Description>

我需要一个 XSL 模板来生成这个输出:

11 行,每行 80 个字符。

例如对于上述元素,结果将是这样的:

在此处输入图像描述

我一直在尝试使用标记化功能,但根本没有成功。提前致谢。

杰拉尔多

4

2 回答 2

1

I. 这是一个 XSLT 1.0 解决方案(XSLT 2.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:variable name="vLine" select=
"concat('**********',
        '**********',
        '**********',
        '**********',
        '**********',
        '**********',
        '**********',
        '**********'
        )
"/>

 <xsl:template match="/*">
     <xsl:copy>
       <xsl:variable name="vsplitResult">
           <xsl:call-template name="split">
             <xsl:with-param name="pText" select="translate(., '&#xA;', '')"/>
           </xsl:call-template>
       </xsl:variable>

       <xsl:variable name="vnumLines" select=
       "ceiling(string-length($vsplitResult) div 81)"/>

       <xsl:choose>
        <xsl:when test="$vnumLines > 11">
          <xsl:value-of select="substring($vsplitResult, 1, 81*11 -1)"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:variable name="vremLines" select="11 - $vnumLines"/>

          <xsl:value-of select="substring($vsplitResult, 1, 81*($vnumLines -1))"/>

          <xsl:call-template name="padRight">
           <xsl:with-param name="pText" select="substring($vsplitResult,81*($vnumLines -1)+1)"/>
          </xsl:call-template>

          <xsl:for-each select="(document('')//node())[not(position() > $vremLines)]">
            <xsl:value-of select="concat('&#xA;', $vLine)"/>
          </xsl:for-each>
        </xsl:otherwise>
       </xsl:choose>
     </xsl:copy>
 </xsl:template>

 <xsl:template name="split">
  <xsl:param name="pText" select="."/>
  <xsl:param name="pLineLength" select="80"/>

  <xsl:if test="$pText">
   <xsl:value-of select="substring($pText, 1, $pLineLength)"/>
   <xsl:if test="string-length($pText) > $pLineLength">
    <xsl:text>&#xA;</xsl:text>
   </xsl:if>

   <xsl:call-template name="split">
     <xsl:with-param name="pText" select="substring($pText, $pLineLength+1)"/>
     <xsl:with-param name="pLineLength" select="$pLineLength"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>

 <xsl:template name="padRight">
  <xsl:param name="pText"/>
  <xsl:param name="pTotatLength" select="80"/>

  <xsl:value-of select=
  "concat($pText,
          substring($vLine, 1, $pTotatLength - string-length($pText))
          )"/>
 </xsl:template>
</xsl:stylesheet>

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

<Description>
text text text text text text text text text text text text text
text text text text text text text text text text text text text text text
text text text text </Description>

产生了想要的正确结果(我正在使用该*字符以查看究竟生成了什么)

<Description>text text text text text text text text text text text text texttext text text t
ext text text text text text text text text text text texttext text text text **
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************</Description>

二、XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pLineLength" select="80" as="xs:integer"/>
 <xsl:param name="pTotalLines" select="11"  as="xs:integer"/>
 <xsl:param name="pPadChar" select="'*'" as="xs:string"/>

 <xsl:variable name="vLine" as="xs:string" select=
      "string-join(
                   (for $i in 1 to $pLineLength
                     return $pPadChar
                    ),
                   ''
                   )
     "/>
  <xsl:template match="/*">
   <xsl:variable name="vText" select="translate(., '&#xA;', '')"/>

   <xsl:copy>
     <xsl:value-of separator="&#xA;" select=
       "(for $numlines in string-length($vText) idiv $pLineLength +1,
             $line in 1 to $numlines
          return
             if($line ne $numlines)
               then substring($vText, 
                              1 + ($line -1)*$pLineLength, 
                              $pLineLength)
               else
                for $lastLine in substring($vText, 
                                           1 + ($line -1)*$pLineLength, 
                                           $pLineLength)
                 return
                   concat($lastLine, 
                          substring($vLine, 
                                    1, 
                                    $pLineLength - string-length($lastLine))
         ),

        (for $numlines in string-length($vText) idiv $pLineLength +1,
             $rem in 1 to $pTotalLines - $numlines
          return
             $vLine)
          )
       "/>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档(如上)时,会产生相同的正确结果

<Description>text text text text text text text text text text text text texttext text text t
ext text text text text text text text text text text texttext text text text **
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************</Description>
于 2012-08-07T03:27:24.977 回答
0

这是最终的解决方案:

    ...
    <xsl:variable name="lineCount" select="11"/>
    <xsl:variable name="charPerLine" select="20"/>
    ...

<ElementX>
                        <xsl:call-template name="Texts">
                                    <xsl:with-param name="string" select="bi:fillText(../bi:SalesOrder/bi:Notes/bi:Description,$charPerLine*$lineCount)"/>
                                    <xsl:with-param name="Position">1</xsl:with-param>
                                    <xsl:with-param name="charLength" select="$charPerLine"/>
                                    <xsl:with-param name="lineCount" select="$lineCount"/>
                            </xsl:call-template>
                        </ElementX>

<!--Template to fill string. ..example 11 lines, 80 characters each.--> 
<xsl:template name="Texts">
    <xsl:param name="string"/>
    <xsl:param name="Position"/>
    <xsl:param  name="charLength" />
    <xsl:param name="lineCount"/>

    <xsl:variable name="line" select="substring($string,1,$charLength)"/>
    <xsl:variable name="rest" select="substring($string, $charLength+1)"/>
    <xsl:if test="$line">
        <xsl:value-of select="$line"/>
        <xsl:if test="$Position != $lineCount"> 
                <xsl:text>&#x0A;</xsl:text> 
        </xsl:if>
    </xsl:if>
    <xsl:if test="$rest and $Position &lt; $lineCount">
        <xsl:call-template name="Texts">
            <xsl:with-param name="string" select="$rest"/>
            <xsl:with-param name="Position" select="$Position+1"/>
            <xsl:with-param name="charLength"  select="$charLength"/>
            <xsl:with-param name="lineCount" select="$lineCount"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:function name="bi:fillText">
    <xsl:param name="value"/>
    <xsl:param name="lengthMax"/>
    <xsl:variable name="j" select="$lengthMax - string-length($value)"/>

    <xsl:value-of select="concat($value,string-join(
               (for $i in 1 to $j
                 return ' '
                ),
               ''
               ) )"/>
</xsl:function>
于 2012-08-07T15:44:52.287 回答