Регулярное выражение (last()) в XSLT

Работает над связыванием некоторого текста на входе с анализом-строкой, но не может извлечь 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 ответ

Решение

Какую ценность вы ожидаете от звонка last() Внутри xsl:analyze-string? Если вы посмотрите на последний абзац в https://www.w3.org/TR/xslt-30/, он говорит:

Соответствующая подстрока обрабатывается с использованием элемента xsl: match-substring, несоответствующей подстроки с использованием элемента xsl: non-Matching substring. Каждый из этих элементов принимает конструктор последовательности в качестве своего содержимого. Если элемент отсутствует, эффект такой же, как если бы он присутствовал с пустым содержимым. При обработке каждой подстроки содержимым подстроки будет элемент контекста (как значение типа xs:string); позиция подстроки в последовательности совпадающих и несоответствующих подстрок будет позицией контекста; и количество совпадающих и несоответствующих подстрок будет размером контекста.

Таким образом last() возвращает размер контекста, он должен быть равен количеству совпадающих и несовпадающих подстрок.

Я понимаю, что это не совсем ответ, но он слишком длинный, чтобы использовать его в качестве комментария. Вы также можете отредактировать свой вопрос и сообщить нам, чего именно должен достичь XSLT, с которым вы связались, в простых словах, и тогда мы сможем предложить подходящее решение XSLT.

Также обратите внимание, что XSLT 3 с XPath 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>
Другие вопросы по тегам