我觉得有一个明显的解决方案,但我想不出来。使用XSLT2.0,我想标记一个分布在子元素中的字符串,所以它有点像
<line>
<font style="big">
<text color="blue">wha</text>
</font>
<font style="small">
<text color="red">t is o</text>
</font>
<font style="small">
<text color="blue">n </text>
</font>
<font style="small">
<text color="blue">his </text>
</font>
<font style="small">
<text color="blue">mind.</text>
</font>
</line>
我想将字符串的值标记化,即将字符串拆分为空格和标点符号,但仍将每个段保留在其树结构中。所以我想要的是:
<line>
<token>
<font style="big">
<text color="blue">wha</text>
</font>
<font style="small">
<text color="red">t</text>
</font>
</token>
<token>
<font style="small">
<text color="red">is</text>
</font>
</token>
<token>
<font style="small">
<text color="red">o</text>
</font>
<font style="small">
<text color="blue">n</text>
</font>
</token>
<token>
<font style="small">
<text color="blue">his</text>
</font>
</token>
<token>
<font style="small">
<text color="blue">mind</text>
</font>
</token>
<token>
<font style="small">
<text color="blue">.</text>
</font>
</token
</line>
也就是说,将每个单词和标点符号移动到一个单独的标记元素中。现在,只需要一个字符串,这很容易,我可以使用analysis string或matches()中的一个,但我找不到一个优雅而健壮的解决方案来完成这项任务。
我会很高兴听到你的想法,Ruprecht
这只完成了一半的工作,对字符串进行标记,它不会添加<token>
标记,就好像我理解正确一样,这需要字典查找来识别单词。它产生
<line>
<font style="big">
<text color="blue">wha</text>
</font>
<font style="small">
<text color="red">t</text>
</font>
<font style="small">
<text color="red">is</text>
</font>
<font style="small">
<text color="red">o</text>
</font>
<font style="small">
<text color="blue">n</text>
</font>
<font style="small">
<text color="blue">his</text>
</font>
<font style="small">
<text color="blue">mind.</text>
</font>
</line>
样式表:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="font">
<xsl:variable name="fa" select="@*"/>
<xsl:for-each select="text">
<xsl:variable name="ta" select="@*"/>
<xsl:for-each select="text()/tokenize(.,'s+')[.]">
<font>
<xsl:copy-of select="$fa"/>
<text>
<xsl:copy-of select="$ta"/>
<xsl:value-of select="."/>
</text>
</font>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
OK在评论中澄清后更新,现在生成
<line>
<token>
<font style="big">
<text color="blue">wha</text>
</font>
<font style="small">
<text color="red">t</text>
</font>
</token>
<token>
<font style="small">
<text color="red">is</text>
</font>
</token>
<token>
<font style="small">
<text color="red">o</text>
</font>
<font style="small">
<text color="blue">n</text>
</font>
</token>
<token>
<font style="small">
<text color="blue">his</text>
</font>
</token>
<token>
<font style="small">
<text color="blue">mind</text>
</font>
</token>
<token>
<font style="small">
<text color="blue">.</text>
</font>
</token>
</line>
xslt:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[font]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:variable name="p1">
<xsl:apply-templates/>
</xsl:variable>
<xsl:for-each-group select="$p1/*" group-starting-with="tok">
<token>
<xsl:copy-of select="current-group() except self::tok"/>
</token>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="font">
<xsl:variable name="fa" select="@*"/>
<xsl:for-each select="text">
<xsl:variable name="ta" select="@*"/>
<xsl:if test="position()=1 and matches(.,'^s')"><tok/></xsl:if>
<xsl:for-each select="text()/tokenize(.,'s+')[.]">
<xsl:if test="position()!=1"><tok/></xsl:if>
<xsl:analyze-string regex="[.,;?]" select=".">
<xsl:matching-substring>
<tok/>
<font>
<xsl:copy-of select="$fa"/>
<text>
<xsl:copy-of select="$ta"/>
<xsl:value-of select="."/>
</text>
</font>
</xsl:matching-substring>
<xsl:non-matching-substring>
<font>
<xsl:copy-of select="$fa"/>
<text>
<xsl:copy-of select="$ta"/>
<xsl:value-of select="."/>
</text>
</font>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:for-each>
<xsl:if test="position()=last() and matches(.,'s$')"><tok/></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>