XSLT中的regex-group(last())

时间:2019-01-29 09:42:42

标签: regex xslt-2.0 xslt-3.0 xslkey analyze-string

正在将输入中的某些文本与分析字符串链接起来,但无法检索脚本中的regex-group(last())

您可以在https://xsltfiddle.liberty-development.net/bnnZVG

上检查转换

如您所见,当前输出

<?xml version="1.0" encoding="UTF-8"?>
<TEST>
    <P>Check <Link ID="ID0001">AbC,2013</Link>AbC,2013Marking</P>
    <P>Check <Link ID="ID0001">ABc, 2013</Link>ABc, 2013Marking</P>
    <P>Check <Link ID="ID0001">ABC 2013</Link>ABC 2013Marking</P>
    <P>Check <Link ID="ID0001">ABC</Link>ABCMarking</P>
    <P>Check <Link ID="ID0002">BCA,2013</Link>BCA,2013Marking</P>
    <P>Check <Link ID="ID0002">bcA, 2013</Link>bcA, 2013Marking</P>
    <P>Check <Link ID="ID0002">BCa 2013</Link>BCa 2013Marking</P>
    <P>Check <Link ID="ID0002">bcA</Link>bcAMarking</P>
</TEST>

但预期输出是

<?xml version="1.0" encoding="UTF-8"?>
<TEST>
    <P>Check <Link ID="ID0001">AbC,2013</Link> Marking</P>
    <P>Check <Link ID="ID0001">ABc, 2013</Link> Marking</P>
    <P>Check <Link ID="ID0001">ABC 2013</Link> Marking</P>
    <P>Check <Link ID="ID0001">ABC</Link> Marking</P>
    <P>Check <Link ID="ID0002">BCA,2013</Link> Marking</P>
    <P>Check <Link ID="ID0002">bcA, 2013</Link> Marking</P>
    <P>Check <Link ID="ID0002">BCa 2013</Link> Marking</P>
    <P>Check <Link ID="ID0002">bcA</Link> Marking</P>
</TEST>

预先感谢

1 个答案:

答案 0 :(得分:1)

last()内部调用xsl:analyze-string,您期望获得什么价值?如果您查看https://www.w3.org/TR/xslt-30/#element-analyze-string中的最后一段,则会显示:

  

使用xsl:matching-substring处理匹配的子字符串   元素,使用xsl:non-matching-substring的不匹配子字符串   元件。这些元素中的每一个都将序列构造器作为其   内容。如果元素不存在,则效果与元素相同   存在空内容。在处理每个子字符串时,   子字符串的内容将是上下文项(作为type的值   xs:string);子串在以下序列中的位置   匹配和不匹配的子字符串将成为上下文位置;和   匹配和不匹配子字符串的数量将作为上下文   大小。

因此,last()返回上下文大小时,它应等于匹配和不匹配子字符串的数量。

我意识到这不是一个完整的答案,但是太长了,无法用作评论。您可能还想编辑您的问题,并以简单的方式告诉我们您链接到的XSLT应该达到的目标,那么我们也许可以帮助建议合适的XSLT解决方案。

还请注意,带有XPath 3的XSLT 3具有一个analyze-string函数,该函数返回具有匹配项和组的XML结构,因此处理/使用它可以帮助您提取所需的内容:

<?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:fn="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="#all"
    version="3.0">

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:key name="testkey" match="link" use="linkname"/>

    <xsl:variable name="testcheck">
        <link name="ID0001">
            <linkname>abc, 2013</linkname>
            <linkname>abc</linkname>
        </link>
        <link name="ID0002">
            <linkname>bca, 2013</linkname>
            <linkname>bca</linkname>
        </link>
    </xsl:variable>

    <xsl:variable name="test">
        <xsl:text>(</xsl:text>
        <xsl:for-each select="$testcheck//linkname">
            <xsl:if test="position() ne 1"><xsl:text>|</xsl:text></xsl:if>
            <xsl:value-of select="."/>
        </xsl:for-each>
        <xsl:text>)</xsl:text>
    </xsl:variable>

    <xsl:variable name="regex" as="xs:string"
      select="concat('(^|\W)', replace($test, ', ([0-9][0-9][0-9][0-9])', '(, $1|,$1| $1)?'), '($|\W)')"/>

    <xsl:template match="text()[matches(., $regex, 'i')]">
         <xsl:apply-templates select="analyze-string(., $regex, 'i')" mode="extract"/>
    </xsl:template>

    <xsl:mode name="extract" on-no-match="text-only-copy"/>

    <xsl:template match="fn:match/fn:group[@nr = 2]" mode="extract">
        <Link ID="{$testcheck//key('testkey', lower-case(replace(current(), '(, |,| )([0-9][0-9][0-9][0-9])', ', $2')))/@name}">
            <xsl:value-of select="."/>
        </Link>          
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bnnZVG/2给出

<TEST>
    <P>Check <Link ID="ID0001">AbC,2013</Link> Marking</P>
    <P>Check <Link ID="ID0001">ABc, 2013</Link> Marking</P>
    <P>Check <Link ID="ID0001">ABC 2013</Link> Marking</P>
    <P>Check <Link ID="ID0001">ABC</Link> Marking</P>
    <P>Check <Link ID="ID0002">BCA,2013</Link> Marking</P>
    <P>Check <Link ID="ID0002">bcA, 2013</Link> Marking</P>
    <P>Check <Link ID="ID0002">BCa 2013</Link> Marking</P>
    <P>Check <Link ID="ID0002">bcA</Link> Marking</P>
</TEST>