Мой текущий проект вращается вокруг перевода нескольких тестовых примеров в документ в формате XML, совместимого с системой управления тестовыми случаями. Во многих из этих случаев заголовок имеет префикс с несколькими идентификаторами билетов, номерами документов и т. Д., Которые необходимо удалить, прежде чем они могут быть загружены в систему.XSLT - анализ регулярных выражений
Учитывая, что многие из этих идентификаторов билетов могут существовать в другом месте в названии и быть полностью действительными, я написал перевод в его текущей форме, так что для обычного выражения проверяется только начало строки. Я написал два подхода с различными результатами.
Пример ввода
1.
<case-name>3.1.6 (C0) TID#EIIY CHM-2213 BZ-7043 Client side Java Upgrade R8</case-name>
2.
<case-name>4.2.7 (C1) TID#F1DR – AIP - EHD-319087 - BZ6862 - Datalink builder res...</case-name>
Желаемая Выход
1.
<tr:summary>Client side Java Upgrade R8</tr:summary>
2.
<tr:summary>Datalink builder res...</tr:summary>
Первый подход
<xsl:template match="case-name">
<tr:summary>
<xsl:variable name="start">
<xsl:apply-templates/>
</xsl:variable>
<xsl:variable name="start" select="normalize-space($start)"/>
<xsl:variable name="noFloat" select="normalize-space(fn:remFirstRegEx($start, '^[0-9]+([.][0-9]+)*' ))"/>
<xsl:variable name="noFloatDash" select="normalize-space(fn:remFirstRegEx($noFloat, '^[\p{Pd}]' ))"/>
<xsl:variable name="noC" select="normalize-space(fn:remFirstRegEx($noFloatDash, '^\(C[0-2]\)' ))"/>
<xsl:variable name="noCDash" select="normalize-space(fn:remFirstRegEx($noC, '^[\p{Pd}]' ))"/>
<xsl:variable name="noTID" select="normalize-space(fn:remFirstRegEx($noCDash, '^(TID)(#|\p{Pd})(\w+)' ))"/>
<xsl:variable name="noTIDDash" select="normalize-space(fn:remFirstRegEx($noTID, '^[\p{Pd}]' ))"/>
<xsl:variable name="noAIP" select="normalize-space(fn:remFirstRegEx($noTIDDash, '^AIP' ))"/>
<xsl:variable name="noAIPDash" select="normalize-space(fn:remFirstRegEx($noAIP, '^[\p{Pd}]' ))"/>
<xsl:variable name="noCHM" select="normalize-space(fn:remFirstRegEx($noAIPDash, '^(CHM)[\p{Pd}]([0-9]+)' ))"/>
<xsl:variable name="noCHMDash" select="normalize-space(fn:remFirstRegEx($noCHM, '^[\p{Pd}]' ))"/>
<xsl:variable name="noEHD" select="normalize-space(fn:remFirstRegEx($noCHMDash, '^(EHD)[\p{Pd}]([0-9]+)' ))"/>
<xsl:variable name="noEHDDash" select="normalize-space(fn:remFirstRegEx($noEHD, '^[\p{Pd}]' ))"/>
<xsl:variable name="noBZ" select="normalize-space(fn:remFirstRegEx($noEHDDash, '^(BZ)(((#|\p{Pd})[0-9]+)|[0-9]+)' ))"/>
<xsl:variable name="noBZDash" select="normalize-space(fn:remFirstRegEx($noBZ, '^[\p{Pd}]' ))"/>
<xsl:variable name="noTT" select="normalize-space(fn:remFirstRegEx($noBZDash, '^(TT)[#](\w)+' ))"/>
<xsl:variable name="noTTDash" select="normalize-space(fn:remFirstRegEx($noTT, '^[\p{Pd}]' ))"/>
<xsl:variable name="nobrack" select="normalize-space(fn:remFirstRegEx($noTTDash, '^\[(.*?)\]' ))"/>
<xsl:variable name="noBrackDash" select="normalize-space(fn:remFirstRegEx($nobrack, '^[\p{Pd}]' ))"/>
<xsl:value-of select="normalize-space($noBrackDash)"/>
</tr:summary>
</xsl:template>
<xsl:function name="fn:remFirstRegEx">
<xsl:param name="inString"/>
<xsl:param name="regex"/>
<xsl:variable name="words" select="tokenize($inString, '\p{Z}')"/>
<xsl:variable name="outString">
<xsl:for-each select="$words">
<xsl:if test="not(matches(., $regex)) or index-of($words, .) > 1">
<xsl:value-of select="."/><xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="string-join($outString, '')">
</xsl:function>
Примечание: Пространство имен сноска, для целей этого перевода, является просто «функцией/пространством имен», используемым для написания моих собственных функций.
Первые результаты
1. Успех
<tr:summary>Client side Java Upgrade R8</tr:summary>
2. Отказ
<tr:summary>- EHD-319087 - BZ6862 - Datalink builder resolution selector may drop leading zeros on coordinate seconds</tr:summary>
Второй подход
<xsl:function name="fn:remFirstRegEx">
<xsl:param name="inString"/>
<xsl:param name="regex"/>
<xsl:analyze-string select="$inString" regex="$regex">
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:function>
Этот подход полностью не подходит, я включаю его здесь, потому что это более очевидное решение и не работает вообще.
Следует отметить, что в приведенном выше решении имеется большое количество регулярных выражений, это учет всех возможных идентификаторов, которые могут пройти. К счастью, идентификаторы, похоже, поступают в последовательном порядке.
Проблема, как я уже сказал, связана с тире. Я отметил, что в каждом случае в документах, в которых перевод не удался, идентификатору сбоя предшествовали и, а затем тире.Если это только предшествует, оно пройдет отлично. Если это только следует, проблем нет. Оба - это то место, где он падает, и, как ни странно, черта все еще появляется, хотя она уже, казалось бы, была исключена из строки.
Здесь есть два вида тире: обычная тире (–
) и знак минуса (-
).
Парадоксально: извините за длинный вопрос, и дайте мне знать, если я что-то пропустил.
EDIT: Забыл сказать, все регулярные выражения, за исключением тире были испытаны в другом месте и, как известно, работают на всех входных вещи.
EDIT II: После решения @ acheong87, я попытался запустить следующее:
<xsl:template match="case-name">
<tr:summary>
<xsl:variable name="regEx" select=
"'^[\s\p{Pd}]*(\d+([.]\d+)*)?[\s\p{Pd}]*(\(C[0-2]\))?([\s\p{Pd}]*(TID|AIP|CHM|EHD|BZ|TT)((#|\p{Pd}|)\w+|))*[\s\p{Pd}]*(\[.*?\])?'"/>
<xsl:analyze-string select="string(.)" regex="{$regEx}">
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</tr:summary>
</xsl:template>
И Saxon дает мне следующую ошибку:
Error at xsl:analyze-string at line (for our purposes, 5):
XTDE1150: The regular expression must not be one that matches a zero-length string
я могу получить, почему это придет при условии, что все не является обязательным. Есть ли другой способ его запуска, который не даст мне эту ошибку?
Еще раз спасибо.
Итак, что вы на самом деле ищете, достаточно разумное регулярное выражение, чтобы иметь дело с вашим (надеюсь, ограниченным) количеством форматов входных строк? – Tomalak
@ acheong87 Регулярное выражение 'находится в конце строк в шаблоне первого решения, второе решение использует тот же шаблон. –
@ Томалак Я не уверен, если это возможно, если честно. Полный список регулярных выражений есть, если вы можете найти регулярное выражение, чтобы решить их все, не зачерпывая что-либо еще, кроме того, что (а) вы являетесь мастером, и (b) это будет оценено по достоинству. –