在特定长度之后切下最接近的单词边界



input

<items>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy tempor magna aliquyam erat. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy<br/>tempor magna aliquyam erat. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy <b>tempor magna aliquyam erat</b>. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy <b>tempor <i>magna</i> aliquyam erat</b>. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet.</item>
</items>

要求

  • " cut" 在特定长度之后的最接近的单词,例如25个字符(包括壁画)
  • 所有nodes() 该位置未触及
  • 所有* 该位置获得属性foo="bar"
  • 所有text() 该位置由template with mode='xy'处理(此模板将丑化文本);该模板将所有相邻的text() -NODE包装在<o foo="bar"> 本身中,为'#'
  • 如果 text() -nodes在尤其可读/ugifified的 *中,则这些 text() -nodes包裹在新元素<o foo="bar">中[请参见item [4] =>" aliquyam erat"] 本身为'#'#'
  • 如果string-length(text()) le $visibleChars,那么什么都没有发生

输出

<!-- middle of word "temppor" -->
<xsl:variable name="visibleChars" select="number(48)"/>
<items>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy tempor<o foo="bar"> #</o></item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy<br/>tempor<o foo="bar"> #</o></item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy <b>tempor<o foo="bar">#</o></b><o foo="bar">#</o></item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy <b>tempor <i foo="bar">#</i><o foo="bar"> #</o></b><o foo="bar">#</o></item>
    <item>Lorem ipsum dolor sit amet.</item>
</items>

伪XSLT

<xsl:templates match="item">
  WHEN count(text()) eq count(node())
  THEN
     Create a $temp of <item> AND insert a <cut/> at position ($visibleChars + CharsTillNextDelimiter)
     <!-- chars to stay visible -->
     <xsl:apply-templates select="$temp/text()[following-sibling::cut]"/>
     <!-- chars to uglify -->
     <xsl:apply-templates select="$temp/text()[preceding-sibling::cut]" mode="xy"/>
  WHEN (*)
  THEN
     NoIDEAToTackleMixedContentFields
...
<xsl:template match="text()" mode="xy">
    <xsl:analyze-string select="." regex="[a-zA-Z0-9]">
        <xsl:matching-substring>
            <xsl:text>#</xsl:text>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
            <xsl:value-of select="."/>
        </xsl:non-matching-substring>
    </xsl:analyze-string>
</xsl:template>
...

我没有运行的XSLT,但是有人可能会向我展示一种满足要求的方法。对任何帮助得到赞赏,希望我在示例中涵盖所有可能的情况。

我已经设法插入cut元素,然后处理修改后的item如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:functx="http://www.functx.com"
    exclude-result-prefixes="xs functx" version="2.0">
    <xsl:param name="length" select="48"/>
    <xsl:function name="functx:escape-for-regex" as="xs:string">
        <xsl:param name="arg" as="xs:string?"/>
        <xsl:sequence
            select="
                replace($arg,
                '(.|[|]|\|||-|^|$|?|*|+|{|}|(|))', '\$1')
                "/>
    </xsl:function>
    <xsl:template match="@* | node()" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item[string-length() gt $length]">
        <xsl:variable name="head" as="xs:string" select="substring(., 1, $length)"/>
        <xsl:variable name="head-pattern" as="xs:string"
            select="concat('^', functx:escape-for-regex($head), 'S*')"/>
        <xsl:variable name="text-to-cut" as="text()"
            select="descendant::text()[matches(string-join((preceding::text()[. >> current()], .), ''), $head-pattern)][1]"/>
        <xsl:variable name="splitted-text" as="xs:string*">
            <xsl:analyze-string select="$text-to-cut"
                regex="{if ($text-to-cut is (current()//text())[1]) then $head-pattern else '^S+'}">
                <xsl:matching-substring>
                    <xsl:sequence select="."/>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:sequence select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
        </xsl:variable>
        <xsl:variable name="modified-copy" as="element(item)">
            <xsl:copy>
                <xsl:apply-templates mode="modify">
                    <xsl:with-param name="text-to-cut" as="text()" select="$text-to-cut"
                        tunnel="yes"/>
                    <xsl:with-param name="splitted-text" as="xs:string*" select="$splitted-text"
                        tunnel="yes"/>
                </xsl:apply-templates>
            </xsl:copy>
        </xsl:variable>
        <xsl:message select="'modified-copy', $modified-copy"/>
        <xsl:apply-templates select="$modified-copy" mode="cut"/>
    </xsl:template>
    <xsl:template match="item//text()" mode="modify">
        <xsl:param name="text-to-cut" as="text()" tunnel="yes"/>
        <xsl:param name="splitted-text" as="xs:string*" tunnel="yes"/>
        <xsl:choose>
            <xsl:when test=". is $text-to-cut">
                <xsl:value-of select="$splitted-text[1]"/>
                <cut/>
                <xsl:value-of select="$splitted-text[2]"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:next-match/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="cut" mode="cut"/>
    <xsl:template match="*[preceding-sibling::cut]" mode="cut">
        <xsl:copy>
            <xsl:attribute name="foo">bar</xsl:attribute>
            <xsl:apply-templates mode="#current"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="text()[preceding::cut]" mode="cut">
        <o foo="bar">
            <xsl:analyze-string select="." regex="[a-zA-Z0-9]+">
                <xsl:matching-substring>
                    <xsl:text>#</xsl:text>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
        </o>
    </xsl:template>
</xsl:stylesheet>

我为您的输入而获得的结果不是您发布的内容,但我希望您能适应它:

<items>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy tempor<o foo="bar"> # # #. # # #.</o></item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy<br/>tempor<o foo="bar"> # # #. # # #.</o></item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy <b>tempor<o foo="bar"> # # #</o></b><o foo="bar">. # # #.</o></item>
    <item>Lorem ipsum dolor sit amet, sed diam nonumy <b>tempor<o foo="bar"> </o><i foo="bar"><o foo="bar">#</o></i><o foo="bar"> # #</o></b><o foo="bar">. # # #.</o></item>
    <item>Lorem ipsum dolor sit amet.</item>
</items>

我认为最简单的方法是用一个普通特殊字符作为弦乐,以消除所有其他特殊字符,例如'。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >    
<xsl:output method="xml" version="4.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />    
<xsl:template match="/">
    <items>
        <xsl:for-each select="items/item">
            <item>
                <xsl:variable name="main.string" select="."/>
                <!--transform string with only one delimiter-->
                <xsl:variable name="format.string" select="translate(normalize-space($main.string), ' ,.', '|')"/>
                <!--get string till 25th character-->
                <xsl:variable name="format.limit.string" select="substring(normalize-space($main.string), 0, 24)"/>
                <!--get 25th character-->
                <xsl:variable name="format.last.char" select="translate($format.limit.string, substring($format.limit.string, 0, 23), '')"/>      
                <!--check if the 25th character is delimiter or part of the word-->
                <xsl:choose>
                    <xsl:when test="$format.last.char = '|'">
                        <xsl:value-of select="substring(normalize-space($format.limit.string), 0, 23)"/>
                        <xsl:element name="o">
                        <xsl:attribute name="foo"><xsl:value-of select="'bar'"/></xsl:attribute>
                        </xsl:element>
                        <xsl:value-of select="substring($main.string, 24, string-length($main.string))"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <!--if cut in the middle of the word then rest part will be added-->
                        <xsl:variable name="final.string" select="concat($format.limit.string, substring-before(substring($format.string, 24, string-length($format.string)), '|'))"/>
                        <xsl:value-of select="$final.string"/>                        
                        <xsl:element name="o">
                        <xsl:attribute name="foo"><xsl:value-of select="'bar'"/></xsl:attribute>
                        </xsl:element>
                        <xsl:value-of select="substring($main.string, string-length($final.string)+1, string-length($main.string))"/>
                    </xsl:otherwise>        
                </xsl:choose>
            </item>
        </xsl:for-each>
   </items>            
</xsl:template>
</xsl:stylesheet>

因此,您将使用25个字符(直到单词)受到限制 - 其他化妆品可以通过我的代码中的Concat函数添加:

<items>
    <item>Lorem ipsum dolor sit amet<o foo="bar"/>, sed diam nonumy tempor magna aliquyam erat. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet<o foo="bar"/>, sed diam nonumytempor magna aliquyam erat. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet<o foo="bar"/>, sed diam nonumy tempor magna aliquyam erat. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet<o foo="bar"/>, sed diam nonumy tempor magna aliquyam erat. Ssed diam voluptua.</item>
    <item>Lorem ipsum dolor sit amet<o foo="bar"/>.</item>
</items>

希望它会有所帮助。

相关内容

  • 没有找到相关文章

最新更新