使用XSLT 1.0将String拆分为100个块

时间:2011-10-19 06:48:29

标签: xslt xslt-1.0

我想尝试一些东西。现在我试图将一个字符串分成100个块。所以这就是我得到的:

<xsl:template name="split100check">
    <xsl:param name="input"></xsl:param>
    <xsl:variable name="newInput" select="concat(normalize-space($input), ' ' )"></xsl:variable>
    <xsl:variable name="start" select="substring($input, 1, 100)"></xsl:variable>
    <xsl:variable name="end" select="substring($input, 101)"></xsl:variable>
    <PART>
        <xsl:value-of select="$start"></xsl:value-of>
    </PART>
    <xsl:if test="$end">
        <xsl:call-template name="split100check">
            <xsl:with-param name="input" select="$end"></xsl:with-param>
        </xsl:call-template>
    </xsl:if>9
</xsl:template>

所以这几乎是我想要实现的目标。它需要一个字符串成100个块,但它也分裂了单词。例如:

<main>
    <long>
    A very long text here [....] only for test
    </long>
</main>

假设前100个块以“仅”字结束,但在其中间。所以第一个块将是“非常长的文本[....] on”和第二个块“ly for test”。那么我如何构建该模板来做我想要的呢?

info:我只能使用XSLT 1.0

编辑: 为了更清楚地说明一个包含10个块的例子:

文字:“你好我的朋友” - &gt;用它的方法将它分成10块:

第一个阻止:<PART>Hello my f</PART>

第二块:<PART>riend</PART>

我希望这些词不会像这样分裂:

第一个阻止:<PART>Hello my </PART>

第二块:<PARTR>friend </PART>

第一块ofc现在不再是10个字符长,但这无关紧要。它应该在10个字符块中放入尽可能多的单词。

gz ALeks

1 个答案:

答案 0 :(得分:1)

您可以使用FXSL 中的str-split-to-lines模板。

以下是一个例子:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:ext="http://exslt.org/common"
xmlns:str-split2lines-func="f:str-split2lines-func"
exclude-result-prefixes="xsl f ext str-split2lines-func"
>


   <xsl:import href="dvc-str-foldl.xsl"/>

   <!-- to be applied on text.xml -->

   <str-split2lines-func:str-split2lines-func/>

   <xsl:output indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/">
      <xsl:call-template name="str-split-to-lines">
        <xsl:with-param name="pStr" select="/*"/>
        <xsl:with-param name="pLineLength" select="60"/>
        <xsl:with-param name="pDelimiters" select="' &#9;&#10;&#13;'"/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template name="str-split-to-lines">
      <xsl:param name="pStr"/>
      <xsl:param name="pLineLength" select="60"/>
      <xsl:param name="pDelimiters" select="' &#9;&#10;&#13;'"/>

      <xsl:variable name="vsplit2linesFun"
                    select="document('')/*/str-split2lines-func:*[1]"/>

      <xsl:variable name="vrtfParams">
       <delimiters><xsl:value-of select="$pDelimiters"/></delimiters>
       <lineLength><xsl:copy-of select="$pLineLength"/></lineLength>
      </xsl:variable>

      <xsl:variable name="vResult">
          <xsl:call-template name="dvc-str-foldl">
            <xsl:with-param name="pFunc" select="$vsplit2linesFun"/>
            <xsl:with-param name="pStr" select="$pStr"/>
            <xsl:with-param name="pA0" select="ext:node-set($vrtfParams)"/>
          </xsl:call-template>
      </xsl:variable>
      <xsl:for-each select="ext:node-set($vResult)/line">
        <xsl:for-each select="word">
          <xsl:value-of select="concat(., ' ')"/>
        </xsl:for-each>
        <xsl:value-of select="'&#xA;'"/>
      </xsl:for-each>
    </xsl:template>

    <xsl:template match="str-split2lines-func:*" mode="f:FXSL">
      <xsl:param name="arg1" select="/.."/>
      <xsl:param name="arg2"/>

      <xsl:copy-of select="$arg1/*[position() &lt; 3]"/>
      <xsl:copy-of select="$arg1/line[position() != last()]"/>

      <xsl:choose>
        <xsl:when test="contains($arg1/*[1], $arg2)">
          <xsl:if test="string($arg1/word) or string($arg1/line/word)">
             <xsl:call-template name="fillLine">
               <xsl:with-param name="pLine" select="$arg1/line[last()]"/>
               <xsl:with-param name="pWord" select="$arg1/word"/>
               <xsl:with-param name="pLineLength" select="$arg1/*[2]"/>
             </xsl:call-template>
          </xsl:if>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy-of select="$arg1/line[last()]"/>
          <word><xsl:value-of select="concat($arg1/word, $arg2)"/></word>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

      <!-- Test if the new word fits into the last line -->
    <xsl:template name="fillLine">
      <xsl:param name="pLine" select="/.."/>
      <xsl:param name="pWord" select="/.."/>
      <xsl:param name="pLineLength" />

      <xsl:variable name="vnWordsInLine" select="count($pLine/word)"/>
      <xsl:variable name="vLineLength" 
       select="string-length($pLine) + $vnWordsInLine"/>
      <xsl:choose>
        <xsl:when test="not($vLineLength + string-length($pWord) 
                           > 
                            $pLineLength)">
          <line>
            <xsl:copy-of select="$pLine/*"/>
            <xsl:copy-of select="$pWord"/>
          </line>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy-of select="$pLine"/>
          <line>
            <xsl:copy-of select="$pWord"/>
          </line>
          <word/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

将此转换应用于以下XML文档

<text>
Dec. 13 — As always for a presidential inaugural, security and surveillance were
extremely tight in Washington, DC, last January. But as George W. Bush prepared to
take the oath of office, security planners installed an extra layer of protection: a
prototype software system to detect a biological attack. The U.S. Department of
Defense, together with regional health and emergency-planning agencies, distributed
a special patient-query sheet to military clinics, civilian hospitals and even aid
stations along the parade route and at the inaugural balls. Software quickly
analyzed complaints of seven key symptoms — from rashes to sore throats — for
patterns that might indicate the early stages of a bio-attack. There was a brief
scare: the system noticed a surge in flulike symptoms at military clinics.
Thankfully, tests confirmed it was just that — the flu.
</text>

产生了所需的理由(长度接近但不超过60的行):

Dec. 13 — As always for a presidential inaugural, security 
and surveillance were extremely tight in Washington, DC, 
last January. But as George W. Bush prepared to take the 
oath of office, security planners installed an extra layer 
of protection: a prototype software system to detect a 
biological attack. The U.S. Department of Defense, together 
with regional health and emergency-planning agencies, 
distributed a special patient-query sheet to military 
clinics, civilian hospitals and even aid stations along the 
parade route and at the inaugural balls. Software quickly 
analyzed complaints of seven key symptoms — from rashes to 
sore throats — for patterns that might indicate the early 
stages of a bio-attack. There was a brief scare: the system 
noticed a surge in flulike symptoms at military clinics. 
Thankfully, tests confirmed it was just that — the flu.