2016-08-16 6 views
0

Используя Saxon 9.7, XSLT 3.0, я пытаюсь выбрать квадратные скобки с помощью строки текста и затем удалить повторяющиеся значения терминов.Соответствие шаблону XSLT REGEX

До сих пор я нашел шаблон, который выбирает подстроки, которые я хочу, и функцию, которая токенизирует строку, а затем удаляет повторяющиеся значения. Однако я не смог получить правильное регулярное выражение для токенизации строки.

Вот мой XML полного текста

<column> 
    <columnDerivationPrompt>Option 1: (No visit windowing)</columnDerivationPrompt> 
    <columnDerivationDescription>Set to collected visit name [EG.VISIT] Set to 'POST-BASELINE MINIMUM' for the new observation generated for derviation type minimum [ADEG.DTYPE] = 'MINIMUM' 
    Set to 'POST-BASELINE MAXIMUM' for the new observation generated for derviation type maximum [ADEG.DTYPE]= 'MAXIMUM' 
    </columnDerivationDescription> 
    <columnDerivationPrompt>Option 2: (User defined visit windows)</columnDerivationPrompt> 
    <columnDerivationDescription>Set to a re-defined visit range based on user-defined input, using formatting of Analysis Relative Day [ADEG.ADY] range in conjunction with Analysis Window Target [ADEG.AWTARGET] and Analysis Window Diff from Target [ADEG.AWTDIFF] to determine analysis visit. 
    Set to 'POST-BASELINE MINIMUM' for the new observation generated for derviation type minimum [ADEG.DTYPE] = 'MINIMUM' 
    Set to 'POST-BASELINE MAXIMUM' for the new observation generated for derviation type maximum [ADEG.DTYPE]= 'MAXIMUM' 
    </columnDerivationDescription> 
</column> 

Строка терминов, взятых из текста, который нужно удалить дубликаты из

EG.VISIT ADEG.DTYPE ADEG.DTYPE ADEG.ADY ADEG.AWTARGET ADEG.AWTDIFF ADEG.DTYPE ADEG.DTYPE 

То, что я хотел бы видеть

EG.VISIT ADEG.DTYPE ADEG.ADY ADEG.AWTARGET ADEG.AWTDIFF 

мой XSLT шаблон и функция

<xsl:variable name="test"> 
    <xsl:if test="contains($string,'[')"> 
     <xsl:variable name="relevant-part" select="substring-before(substring-after($string,'['),']')"/> 
     <xsl:variable name="remainder" select="substring-after($string,']')"/> 

     <xsl:value-of select="$relevant-part"/> 
     <xsl:if test="contains($remainder,'[')"> 
      <xsl:text disable-output-escaping="yes"> </xsl:text> 
     </xsl:if> 
     <xsl:call-template name="find-relevant-text"> 
      <xsl:with-param name="string" select="$remainder"/> 
     </xsl:call-template> 
    </xsl:if> 
    </xsl:variable> 


    <xsl:value-of select="myfn:sortCSV($test)"/> 
</xsl:template> 



<xsl:function name="myfn:sortCSV" as="xs:string*"> 
    <xsl:param name="csvString" as="xs:string"/> 

    <!-- Split up string and remove duplicates --> 
    <xsl:variable name="values" select="distinct-values(tokenize($csvString,'\W+\.\W+'))" as="xs:string*"/> 
    <!-- Return all elements, sorted --> 
    <xsl:for-each select="$values"> 
     <xsl:sort/> 
     <!-- We don't return empty strings --> 
     <xsl:sequence select=".[.!='']"/> 
    </xsl:for-each> 
</xsl:function> 

\W+\.\W+ является регулярным выражением я использую, чтобы определить, например, EG.VISIT или ADEG.DTYPE. Таким образом, любой шаблон, включая CC.CCCC, для CCCC.CCCCCCCC (где C - char [A-Z]).

Выход я получаю

EG.VISIT ADEG.DTYPE ADEG.DTYPE ADEG.ADY ADEG.AWTARGET ADEG.AWTDIFF ADEG.DTYPE ADEG.DTYPE 

Так никаких дубликатов не были удалены.

ВОПРОС: Может ли кто-нибудь увидеть, где я ошибаюсь в своем выражении или коде?

+0

Используйте '\ w + \. \ W +'. '\ W' соответствует символу без слова. '\ w' соответствует символу слова. Лучше всего ограничить его '[A-Z] + \. [A-Z] +', поскольку вы говорите, что элементы, которые вы хотите сопоставить, следуют шаблону 'uppercase' +'. '+' Uppercase'. –

ответ

1

Я хотел бы использовать analyze-string, либо с помощью XSLT 2.0 XSLT xsl:anyalyze-string или с помощью XSLT 3.0 функция с тем же именем, используя этот подход, это один вкладыш:

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

    <xsl:template match="column"> 
     <xsl:value-of select="distinct-values(analyze-string(., '\[([A-Z]+\.[A-Z]+)\]')//fn:match/fn:group[@nr = 1])"/> 
    </xsl:template> 

</xsl:stylesheet> 

Выход EG.VISIT ADEG.DTYPE ADEG.ADY ADEG.AWTARGET ADEG.AWTDIFF.

Если вы хотите отсортировать извлеченные строки, используйте <xsl:value-of select="sort(distinct-values(analyze-string(., '\[([A-Z]+\.[A-Z]+)\]')//fn:match/fn:group[@nr = 1]))"/>.

+0

Работал отлично. Спасибо, Мартин! – Huw

2

Что касается вашего регулярного выражения, обратите внимание, что \W соответствует неглавным символом и не может совпадать с прописными буквами (или строчными буквами). \w соответствует слову char.

Однако, лучше всего ограничить его [A-Z]+\.[A-Z]+, так как вы говорите, элементы, которые вы хотите, чтобы соответствовать следовать схеме uppercase + . + uppercase.

Смотрите regex demo

Смежные вопросы