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>
希望它会有所帮助。