Я пытаюсь токенизировать эту строку, чтобы создавать отдельные записи для каждой библиографической ссылки. Загвоздка в том, что иногда точка с запятой отделяет библиографическую статью, а иногда — номера страниц. Я хочу написать токенизатор только для токенизации, если за точкой с запятой не следует пробел и число. То, что у меня есть ниже, вроде как работает, но вырезает первую букву каждой цитаты. (Я использую XSLT 2.0)
Вход:
<zotero>(Leppin 2019; Francisco 2011, 119; van Ginkel 2005, 43–44; 1995, 114–115; 126; 147; 166–67)</zotero>
XSLT:
<xsl:for-each select = "tokenize(zotero,';\s[^\d]')">
<bibl><xsl:value-of select = "."/></bibl>
</xsl:for-each>
Текущий выход:
<bibl>(Leppin 2019</bibl>
<bibl>rancisco 2011, 119</bibl>
<bibl>an Ginkel 2005, 43–44; 1995, 114–115; 126; 147; 166–67)</bibl>
К сожалению, спецификация XPath не позволяет выполнять предварительный просмотр в регулярных выражениях.
Вы можете использовать обходной путь, например:
<xsl:variable name = "preprocess" select = "replace(zotero, ';\s(\D)', '…$1')" />
<xsl:for-each select = "tokenize($preprocess, '…')">
<bibl>
<xsl:value-of select = "."/>
</bibl>
</xsl:for-each>
Или, если вы используете процессор Saxon, вы можете переключиться на стандартный механизм регулярных выражений Java и просто сделать:
<xsl:for-each select = "tokenize(zotero, ';\s(?=\D)', ';j')">
Я хочу написать токенизатор, который будет токенизировать только если точка с запятой без пробела и цифры
С отрицательным прогнозом, который будет выражаться как
<xsl:template match = "zotero">
<xsl:for-each select = "tokenize(., ';(?! [0-9])', ';j')">
<bib>{.}</bib>
</xsl:for-each>
</xsl:template>
Флаги ;j
работают с Saxon Java, SaxonC, Saxon .NET, SaxonCS и SaxonJS, позволяя переключаться со стандартных регулярных выражений XPath на поддерживаемую платформу.
Вместо использования функции tokenize
я бы, вероятно, использовал xsl:analyze-string
вот так:
<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "xml" indent = "true"/>
<xsl:template match = "zotero">
<listBibl>
<!-- each bibl starts with at least one letter \p{L} or space \p{Z},
and continues with an optional sequence of non-letters \P{L} -->
<xsl:analyze-string
select = "substring(., 2, string-length(.) - 2)"
regex = "(\p{{L}}|\p{{Z}})+\P{{L}}*"
>
<xsl:matching-substring>
<bibl><xsl:value-of select = "."/></bibl>
</xsl:matching-substring>
</xsl:analyze-string>
</listBibl>
</xsl:template>
</xsl:stylesheet>
Урожайность:
<listBibl>
<bibl>Leppin 2019; </bibl>
<bibl>Francisco 2011, 119; </bibl>
<bibl>van Ginkel 2005, 43–44; 1995, 114–115; 126; 147; 166–67</bibl>
</listBibl>
Проблема с tokenize()
в том, что он съедает ваши разделители, в отличие от <xsl:analyze-string>
(или в XSLT 3 функции analyze-string()
). Я думаю, что этот подход легче расширить, например. во вложенный набор операторов analyze-string
, которые создают более детальную библиографическую разметку, например, элементы <date>
и <citedRange>
.