在特定长度之后切割最接近的字边界

时间:2017-12-07 17:18:34

标签: xml xslt xslt-1.0 xslt-2.0

输入

<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>

要求

  • &#34;切&#34; 特定长度后的最接近的字词,例如25个字符(包括空格)
  • 之前的所有nodes() 该位置未受影响
  • 之后的所有* 获得属性foo="bar"
  • {/ 1}}之后的所有text() 该位置由template with mode='xy'处理(此模板将对文本进行处理);模板将text() +本身中的所有相邻<o foo="bar"> - 节点包装为&#39;#&#39;
  • 如果text() - 节点属于特定可读/未经授权的*,则这些text() - 节点将包含在新元素<o foo="bar">中[参见条目[4] = &GT; &#34; aliquyam erat&#34;] +本身作为&#39;#&#39;
  • IF 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,但有人可能会告诉我一种满足要求的方法。感谢任何帮助,我希望在我的例子中涵盖所有可能的情况。

2 个答案:

答案 0 :(得分:1)

我已设法插入ERROR in Entry module not found: Error: Can't resolve 'application.ts' in 'C:\Projects\Github\Aureus\Aureus.Web\scripts' resolve 'application.ts' in 'C:\Projects\Github\Aureus\Aureus.Web\scripts' Parsed request is a module using description file: C:\Projects\Github\Aureus\Aureus.Web\package.json (relative path: ./scripts) Field 'browser' doesn't contain a valid alias configuration after using description file: C:\Projects\Github\Aureus\Aureus.Web\package.json (relative path: ./scripts) resolve as module C:\Projects\Github\Aureus\Aureus.Web\scripts\node_modules doesn't exist or is not a directory C:\Projects\Github\Aureus\node_modules doesn't exist or is not a directory C:\Projects\Github\node_modules doesn't exist or is not a directory C:\Projects\node_modules doesn't exist or is not a directory C:\node_modules doesn't exist or is not a directory looking for modules in C:\Projects\Github\Aureus\Aureus.Web\node_modules using description file: C:\Projects\Github\Aureus\Aureus.Web\package.json (relative path: ./node_modules) Field 'browser' doesn't contain a valid alias configuration after using description file: C:\Projects\Github\Aureus\Aureus.Web\package.json (relative path: ./node_modules) using description file: C:\Projects\Github\Aureus\Aureus.Web\package.json (relative path: ./node_modules/application.ts) no extension Field 'browser' doesn't contain a valid alias configuration C:\Projects\Github\Aureus\Aureus.Web\node_modules\application.ts doesn't exist .js Field 'browser' doesn't contain a valid alias configuration C:\Projects\Github\Aureus\Aureus.Web\node_modules\application.ts.js doesn't exist .json Field 'browser' doesn't contain a valid alias configuration C:\Projects\Github\Aureus\Aureus.Web\node_modules\application.ts.json doesn't exist as directory C:\Projects\Github\Aureus\Aureus.Web\node_modules\application.ts doesn't exist 元素,然后按如下方式处理修改后的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>

答案 1 :(得分:0)

我认为最简单的方法是成为只有一个共同特殊字符的字符串,以消除所有其他特征。 。,&#39;,请看下面的内容:

<?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>

希望它会有所帮助。