我的目标是分析给定XML文档的text()节点并识别大写单词以及该单词长度是否> 3在3,4个字符(6,7和9,10 .....)之间添加'*'
个字符
例如,
输入XML:
<chap>
<para>The BEGINNING of this COLUMN shows the INPUT and output</para>
</chap>
期望的输出:
<chap>
<para>The BEG*INN*ING of this COL*UMN shows the INP*UT and output</para>
</chap>
我已经在xsl之后编写了这项任务,
<xsl:template match="para">
<xsl:analyze-string select="." regex="[(A-Z)]">
<xsl:matching-substring>
<xsl:variable name="reg" select="string(regex-group(0))"/>
<xsl:call-template name="add-star">
<xsl:with-param name="str" select="$reg"/>
</xsl:call-template>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template name="add-star">
<xsl:param name="str" as="xs:string"/>
<xsl:if test="string-length($str)>3">
<xsl:call-template name="add-star">
<xsl:with-param name="str" select="substring($str,4,200)"/>
</xsl:call-template>
</xsl:if>
<xsl:sequence select="string-join(substring($str,1,3),'*')"/>
</xsl:template>
但它没有按预期工作。因为没有像oop语言这样的变量我在XSLT中努力完成这项任务,有人可以建议我如何修改我的代码来完成这项任务?
答案 0 :(得分:1)
怎么样:
<xsl:template match="para">
<xsl:copy>
<xsl:analyze-string select="." regex="([A-Z]+)(\s|$)">
<xsl:matching-substring>
<xsl:variable name="sub" as="xs:string*">
<xsl:for-each select="0 to (string-length(regex-group(1)) - 1) idiv 3">
<xsl:sequence select="substring(regex-group(1), (. ) * 3 + 1, 3)" />
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="string-join($sub, '*')"/>
<xsl:value-of select="regex-group(2)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:copy>
</xsl:template>
答案 1 :(得分:1)
这是另一个支持exslt的xslt-1.0解决方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:my="http://my.org/xsl"
extension-element-prefixes="fn str func">
<xsl:output method="xml" version="1.0" indent="yes"/>
<func:function name="my:to-upper">
<xsl:param name="str" select="''"/>
<func:result select="translate($str, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
</func:function>
<func:function name="my:is-upper">
<xsl:param name="str" select="''"/>
<func:result select="my:to-upper($str) = $str"/>
</func:function>
<xsl:template match="/">
<xsl:apply-templates select="/node()"/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="./@*"/>
<xsl:apply-templates select="./node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:if test="string-length(normalize-space(.)) > 0">
<xsl:for-each select="str:tokenize(., ' ')">
<xsl:choose>
<xsl:when test="my:is-upper(.)">
<xsl:choose>
<xsl:when test="string-length(.) > 3">
<xsl:for-each select="str:tokenize(., '')">
<xsl:value-of select="."/>
<xsl:if test="0 = position() mod 3 and not(position() = last())">
<xsl:text>*</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="not(position() = last())">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
在线Demo