2009-09-13 3 views
5

Можно ли разделить тег на границе нижнего и верхнего регистров, то есть , например, тег 'UserLicenseCode' должен быть преобразован в «Код лицензии пользователя» , чтобы заголовки столбцов выглядели немного лучше.Комплекс XSLT сплит?

Я сделал что-то подобное в прошлом, используя регулярные выражения Perl, , но XSLT - это совершенно новая игра для меня.

Любые указатели при создании такого шаблона были бы очень признательны!

Благодаря Кришна

+1

+1, потому что XSLT остается для меня загадкой, поэтому пока я не могу помочь *, я определенно наблюдаю за развитием событий здесь. –

+0

+1 для мышления это сложно, а на самом деле это просто код. :-) Ничто не сложно, когда вы знаете, как это сделать. –

ответ

2

Используя рекурсию, можно пройти через строку в XSLT для оценки каждого символа. Для этого создайте новый шаблон, который принимает только один строковый параметр. Проверьте первый символ, и если это символ верхнего регистра, напишите пробел. Затем напишите символ. Затем снова вызовите шаблон с остальными символами внутри одной строки. Это приведет к тому, что вы хотите сделать.

Это будет ваша указатель. Мне нужно некоторое время, чтобы выработать шаблон. :-)


Прошло некоторое тестирование, особенно, чтобы получить пространство внутри всего. (Я неправильно символ для этого!) Но этот код должен дать вам идею ...

Я использовал этот XML:

<?xml version="1.0" encoding="UTF-8"?> 
<blah>UserLicenseCode</blah> 

, а затем эту таблицу стилей:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
    <xsl:output method="text"/> 
    <xsl:variable name="Space">*</xsl:variable> 
    <xsl:template match="blah"> 
    <xsl:variable name="Split"> 
     <xsl:call-template name="Split"> 
      <xsl:with-param name="Value" select="."/> 
      <xsl:with-param name="First" select="true()"/> 
     </xsl:call-template></xsl:variable> 
     <xsl:value-of select="translate($Split, '*', ' ')" /> 
    </xsl:template> 
    <xsl:template name="Split"> 
     <xsl:param name="Value"/> 
     <xsl:param name="First" select="false()"/> 
     <xsl:if test="$Value!=''"> 
      <xsl:variable name="FirstChar" select="substring($Value, 1, 1)"/> 
      <xsl:variable name="Rest" select="substring-after($Value, $FirstChar)"/> 
       <xsl:if test="not($First)"> 
        <xsl:if test="translate($FirstChar, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '..........................')= '.'"> 
         <xsl:value-of select="$Space"/> 
        </xsl:if> 
       </xsl:if> 
       <xsl:value-of select="$FirstChar"/> 
       <xsl:call-template name="Split"> 
        <xsl:with-param name="Value" select="$Rest"/> 
       </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

и I получил это как результат:

User License Code 

ли иметь в виду, что пробелы и другие пробельные символы имеют тенденцию быть отбрасываются фр om XML, поэтому я использовал вместо этого «*», который я перевел в пространство.

Конечно, этот код можно было бы улучшить. Это то, что я мог придумать за 10 минут работы. На других языках это займет меньше строк кода, но в XSLT все еще довольно быстро, учитывая количество строк кода, которое оно содержит.

+0

Спасибо! Работает как шарм. Я не видел этого сообщения, прежде чем отправил свое решение. Это лучше справляется с граничными условиями. Спасибо за быстрый ответ! – 2009-09-14 04:05:28

1

XSLT + решения FXSL (в XSLT 2.0, но почти тот же код будет работать с XSLT 1.0 и FXSL 1.x:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:f="http://fxsl.sf.net/" 
xmlns:testmap="testmap" 
exclude-result-prefixes="f testmap" 
> 
    <xsl:import href="../f/func-str-dvc-map.xsl"/> 
    <testmap:testmap/> 

    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:template match="/"> 
    <xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/> 

    '<xsl:value-of select="f:str-map($vTestMap, 'UserLicenseCode')" 
     />' 
    </xsl:template> 

    <xsl:template name="mySplit" match="*[namespace-uri() = 'testmap']" 
    mode="f:FXSL"> 
     <xsl:param name="arg1"/> 

     <xsl:value-of select= 
     "if(lower-case($arg1) ne $arg1) 
     then concat(' ', $arg1) 
     else $arg1 
     "/> 
    </xsl:template> 
</xsl:stylesheet> 

Когда выше преобразование применяется на любом документе XML источник (не используется), ожидаемый правильный результат получается:

'Лицензионный код'

Обратите внимание:

  1. Мы используем версию DVC функции FXSL/шаблон str-map(). Это функция высшего порядка (HOF), которая принимает два аргумента: другую функцию и строку. str-map() применяет функцию к каждому символу строки и возвращает конкатенацию результатов.

  2. Поскольку используется функция нижнего регистра() в версии XSLT 2.0, мы не ограничены только латинским алфавитом.