Как отформатировать строку в регистр Pascal в XSLT? - PullRequest
10 голосов
/ 15 апреля 2010

Я пытаюсь отформатировать строки в XSLT, которые должны быть в паскале для правильного использования в приложении, с которым я работаю.

Например:

this_text станет ThisText
this_long_text станет ThisLongText

Можно ли также установить это, где я могу отправить входные данные в формат, чтобы мне не приходилось повторно создавать формат несколько раз?

Ответы [ 5 ]

8 голосов
/ 15 апреля 2010

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vLower" select=
  "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vUpper" select=
  "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:call-template name="Pascalize">
   <xsl:with-param name="pText" select="concat(., '_')"/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="Pascalize">
  <xsl:param name="pText"/>

  <xsl:if test="$pText">
   <xsl:value-of select=
    "translate(substring($pText,1,1), $vLower, $vUpper)"/>

   <xsl:value-of select="substring-before(substring($pText,2), '_')"/>

   <xsl:call-template name="Pascalize">
     <xsl:with-param name="pText"
       select="substring-after(substring($pText,2), '_')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

при применении к этому документу XML :

<t>
  <a>this_text</a>
  <b>this_long_text</b>
</t>

дает желаемый результат :

<t>
    <a>ThisText</a>
    <b>ThisLongText</b>
</t>

Кстати, это camelCase , а это PascalCase

6 голосов
/ 20 октября 2012

Здесь, спустя два года, есть решение XSLT 2.0:

<xsl:function name="fn:pascal-case">
    <xsl:param name="string"/>
    <xsl:value-of select="string-join(for $s in tokenize($string,'\W+') return concat(upper-case(substring($s,1,1)),substring($s,2)),'')"/>
</xsl:function>

Он будет паскализировать 'this_long_text' или 'this-long-text' в 'ThisLongText', потому что он разбивается на любые несловесные символы.

В разновидностях регулярных выражений, с которыми я наиболее знаком (perl, pcre и т. Д.), Подчеркивание считается частью класса символов '\ w' (следовательно, не частью \ W), но для XSLT 2.0 - типы данных XSD используются (http://www.w3.org/TR/xmlschema-2/) и '\ w' определяется как:

[#x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] (all characters except the set of "punctuation", "separator" and "other" characters)

поэтому '\ W' включает в себя подчеркивание.

4 голосов
/ 22 июня 2010

Эта версия работала для меня.Я добавил выбор, который выводит «остаток» строки, когда больше нет подчеркивания.

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

<xsl:template name="Pascalize">
    <xsl:param name="pText" />
    <xsl:if test="$pText">
        <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)" />
        <xsl:choose>
            <xsl:when test="contains($pText, '_')"> 
                <xsl:value-of select="substring-before(substring($pText,2), '_')" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="substring($pText,2)" />
            </xsl:otherwise>
        </xsl:choose>
        <xsl:call-template name="Pascalize">
            <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

Кроме того, на случай, если кто-нибудь придет сюда в поисках процесса reverse (который яслучайно потребовал и сегодня и не может найти ни одного примера в любом месте) ...

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

<xsl:template name="TitleCase">
    <xsl:param name="pText" />
    <xsl:call-template name="TitleCase_recurse">
        <xsl:with-param name="pText" select="concat(translate(substring($pText,1,1), $vLower, $vUpper), substring($pText,2))" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="TitleCase_recurse">
    <xsl:param name="pText" />
    <xsl:if test="string-length($pText) &gt; 1">
        <xsl:if test="not(substring($pText,1,1) = ' ' and substring($pText,1,1) = ' ')">
            <xsl:value-of select="substring($pText,1,1)" />
        </xsl:if>
        <xsl:if test="translate(substring($pText,1,1), $vLower, $vUpper) != substring($pText,1,1)">
            <xsl:if test="translate(substring($pText,2,1), $vLower, $vUpper) = substring($pText,2,1)">
                <xsl:text> </xsl:text>
            </xsl:if>
        </xsl:if>
        <xsl:call-template name="TitleCase_recurse">
            <xsl:with-param name="pText" select="substring($pText,2)" />
        </xsl:call-template>
    </xsl:if>
    <xsl:if test="string-length($pText) = 1">
        <xsl:value-of select="$pText" />
    </xsl:if>
</xsl:template>

Мне нравится, когда мое подсознание выдает ответ через несколько часов после того, как я 'мы полностью сдались сознательно.; -)

1 голос
/ 08 августа 2010

Я пытался добиться «паскализации» с помощью следующего вызова функции XLST:

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\U$1')"/>

К сожалению, процессор выдает сообщение об ошибке «Недопустимая строка замены в replace (): \ символ должен сопровождаться \ или $ "

проблема в том, что модификатор \ U должен выполнять преобразование сопоставленного шаблона в верхнем регистре. Если я изменю это на

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\\U$1')"/>

выходная строка содержит последовательность '\ U', потому что она теперь удалена, но я не хочу ее избегать, я хочу, чтобы она была эффективной ;-). Я сделал тест

<xsl:value-of select="fn:replace(@name,'_(\w{1})','$1')"/>

(без преобразования соответствия в верхний регистр), и это прекрасно работает. Но, конечно, он не использует заглавные буквы, а только удаляет подчеркивания и заменяет букву после подчеркивания на себя, а не на заглавную. Я что-то не так делаю или модификатор \ U просто не поддерживается в реализации regex моего процессора XSLT?

0 голосов
/ 16 апреля 2010

Благодаря Димитру, я смог пройти большую часть пути туда. При запуске моих строк через шаблон Pascalize, бит после последнего '_' обрезался. Вероятно, есть более чистый способ сделать это, но вот код, который я использовал:

<xsl:template name="Pascalize">
    <xsl:param name="pText"/>

    <xsl:if test="$pText">
        <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)"/>

        <xsl:value-of select="substring-before(substring($pText,2), '_')"/>

        <xsl:call-template name="Pascalize">
            <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')"/>
        </xsl:call-template>

        <xsl:call-template name="GrabLastPart">
            <xsl:with-param name="pText" select="$pText"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template name="GrabLastPart">
    <xsl:param name="pText"/>

    <xsl:choose>
        <xsl:when test="contains($pText, '_')">
            <xsl:call-template name="GrabLastPart">
                <xsl:with-param name="pText" expr="substring-after($pText, '_')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="substring($pText, 2)"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
...