Как использовать шаблон замены case с функцией замены Xpath - PullRequest
0 голосов
/ 19 июня 2020

У меня есть демонстрация шаблонов регулярного выражения и подстановки , и мне нужно использовать его в контексте xpath с функцией fn: replace, но я не могу понять, как правильно написать заменяющую строку Возможно ли ? мой наивный тест был

replace ("dsfjkljsdfjlsjdfABCDdfsfsdff",
             "(\p{Lu})(\p{Lu}+)",
             "$1\L$2")

, но он жалуется на FORX0004: недопустимая строка замены в replace (): за символом \ должен следовать \ или $

Ответы [ 2 ]

1 голос
/ 20 июня 2020

Я думаю, вы хотите, например,

<xsl:function name="mf:lower-case-match">
  <xsl:param name="input" as="xs:string"/>
  <xsl:param name="regex" as="xs:string"/>
  <xsl:analyze-string select="$input" regex="{$regex}">
    <xsl:matching-substring>
      <xsl:value-of select="concat(regex-group(1), lower-case(regex-group(2)))"/>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
      <xsl:value-of select="."/>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
</xsl:function>

mf:lower-case-match("dsfjkljsdfjlsjdfABCDdfsfsdff", "(\p{Lu})(\p{Lu}+)")

или, чтобы использовать as="xs:string" в качестве объявленного типа функции:

<xsl:function name="mf:lower-case-match" as="xs:string">
  <xsl:param name="input" as="xs:string"/>
  <xsl:param name="regex" as="xs:string"/>
  <xsl:value-of>
      <xsl:analyze-string select="$input" regex="{$regex}">
        <xsl:matching-substring>
          <xsl:value-of select="concat(regex-group(1), lower-case(regex-group(2)))"/>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
          <xsl:value-of select="."/>
        </xsl:non-matching-substring>
      </xsl:analyze-string>          
  </xsl:value-of>
</xsl:function>

Вам необходимо объявить пространство имен для любого пользователя - определенная функция, например xmlns:mf="http://example.com/mf" в xsl:stylesheet или xsl:transform root.

В XSLT 3 вы также можете просто pu sh результат функции analyze-string через режим, который затем выполняет любое преобразование в группах, которые вы хотите:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

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

  <xsl:template match="text">
      <xsl:copy>
          <xsl:apply-templates select="analyze-string(., '(\p{Lu})(\p{Lu}+)')" mode="lower-case"/>
      </xsl:copy>
  </xsl:template>
  
  <xsl:template match="*:group[@nr = 2]" mode="lower-case">
      <xsl:value-of select="lower-case(.)"/>
  </xsl:template>
  
</xsl:stylesheet>
0 голосов
/ 20 июня 2020

Я не думаю, что свойство \L regex поддерживается XPath. Ответ @Martin Honnen, вероятно, лучший, но вот полное решение XPath 2.0:

С:

dsfjkljsdfjlsjdfABCDdfsfsdff

XPath:

replace(replace("dsfjkljsdfjlsjdfABCDdfsfsdff","(\p{Lu})(\p{Lu}+)","$1___$2___"),"_{3}.+_{3}",lower-case(substring-before(substring-after(replace("dsfjkljsdfjlsjdfABCDdfsfsdff","(\p{Lu})(\p{Lu}+)","$1___$2___"),"___"),"___")))

Описание:

P1: Мы добавляем ___, чтобы идентифицировать нижнюю часть с помощью:

replace("dsfjkljsdfjlsjdfABCDdfsfsdff","(\p{Lu})(\p{Lu}+)","$1___$2___")

P2: Мы генерируем нижнюю часть с помощью:

lower-case(substring-before(substring-after(resultofP1,"___"),"___"))

Мы присоединяемся к два предыдущих выражения с:

replace(resultofP1,"_{3}.+_{3}",resultofP2)

Вывод:

dsfjkljsdfjlsjdfAbcddfsfsdff
...