Преобразование имен элементов XML в формат camelCase с использованием XSLT - PullRequest
0 голосов
/ 19 февраля 2019

Мне нужно преобразовать все имена элементов в XML в стратегию именования camelCase с помощью XSLT.

Вот ответ от следующего сервера:

<ROOT_ELEMENT>
        <ELEMENT_1>2595959584</ELEMENT_1>
        <Element_Two>Lorem</Element_Two>
        <eLement_Three>Ipsum</eLement_Three>

        <BIRTH_date>
           <Day>21</Day>
           <Month>09</Month>
           <Year>1955</Year>
        </BIRTH_date>
 </ROOT_ELEMENT>

Вот что я хочу преобразовать:

<rootElement>
        <element1>2595959584</element1>
        <elementTwo>Lorem</elementTwo>
        <elementThree>Ipsum</elementThree>      
        <birthDate>
           <day>21</day>
           <month>09</month>
           <year>1955</year>
        </birthDate>
</rootElement>

Любая помощь будет высоко ценится.

Ответы [ 4 ]

0 голосов
/ 20 февраля 2019
<xsl:template match="*">
    <xsl:choose>
        <xsl:when test="contains(name(), '_')">
            <xsl:element name="{concat(substring-before(lower-case(name()), '_'), substring(substring-after(upper-case(name()), '_'), 1,1), substring(substring-after(lower-case(name()), '_'), 2))}">
                <xsl:apply-templates/>
            </xsl:element>
        </xsl:when>
        <xsl:otherwise>
                <xsl:element name="{lower-case(name())}">
                    <xsl:apply-templates/>
                </xsl:element>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Еще один ответ, если это возможно, используйте этот код.

0 голосов
/ 19 февраля 2019

Предполагая, что в имени элемента будет не более одного _ разделителя, и предполагая, что имена не содержат не-ASCII символов, вы можете использовать:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*">
    <xsl:param name="upper-case" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
    <xsl:param name="lower-case" select="'abcdefghijklmnopqrstuvwxyz'"/>
    <xsl:variable name="name" select="name()" />
    <xsl:variable name="word2" select="substring-after($name, '_')" />
    <xsl:variable name="new-name">
        <xsl:value-of select="translate(substring-before(concat($name, '_'), '_'), $upper-case, $lower-case)"/> 
        <xsl:value-of select="translate(substring($word2, 1, 1), $lower-case, $upper-case)"/>   
        <xsl:value-of select="translate(substring($word2, 2), $upper-case, $lower-case)"/>  
    </xsl:variable>
    <xsl:element name="{$new-name}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

Добавлено:

Если (как кажется) вы используете процессор, который поддерживает функцию расширения XSLT str:tokenize(), вы можете сделать:

XSLT 1.0 + EXSLT

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*">
    <xsl:param name="upper-case" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
    <xsl:param name="lower-case" select="'abcdefghijklmnopqrstuvwxyz'"/>
    <xsl:variable name="new-name">
        <xsl:for-each select="str:tokenize(name(), '_')">
            <xsl:choose>
                <xsl:when test="position() = 1">
                    <xsl:value-of select="translate(., $upper-case, $lower-case)"/>   
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="translate(substring(., 1, 1), $lower-case, $upper-case)"/>   
                    <xsl:value-of select="translate(substring(., 2), $upper-case, $lower-case)"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each> 
    </xsl:variable>
    <xsl:element name="{$new-name}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

Снимает ограничение на количество разделителей _, которое может иметь имя элемента.Остается другое ограничение: все возможные символы, которые могут присутствовать в имени элемента и имеют прописные и строчные буквы, должны быть указаны в параметрах $upper-case и $lower-case.

0 голосов
/ 19 февраля 2019

Еще один способ заглавной буквы в XSLT 1.0 представлен ниже:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes" />

<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

<xsl:template match="*">
    <xsl:variable name="convertElementName">
        <xsl:choose>
            <xsl:when test="contains(local-name(.),'_')">
                <xsl:value-of
                    select="concat(translate(substring-before(local-name(.),'_'), $uppercase, $smallcase),
                            translate(substring(substring-after(local-name(.),'_'),1,1), $smallcase, $uppercase),
                            translate(substring(substring-after(local-name(.),'_'),2,string-length(local-name(.))-1), $uppercase, $smallcase))" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="translate(local-name(.), $uppercase, $smallcase)" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <xsl:element name="{$convertElementName}">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:attribute name="{local-name(.)}">
        <xsl:value-of select="." />
    </xsl:attribute>
</xsl:template>
</xsl:stylesheet>
0 голосов
/ 19 февраля 2019

В XSLT 3.0 это

string-join(tokenize(name(), '_') ! 
  (upper-case(substring(., 1, 1)) || lower-case(substring(., 2))))

В 1.0 это намного сложнее, но все же возможно (по крайней мере, если в именах ваших элементов используются только буквы ASCII).Вам понадобится рекурсивный именованный шаблон для выполнения токенизации (вы можете найти его в http://www.exslt.org, ищите str:tokenize в модуле strings), и в пределах именованного шаблона, где вы обрабатываете один токен, вынеобходимо использовать translate($x, 'abc...z', 'ABC...Z') для преобразования регистра.

Вы можете избежать рекурсии и упростить логику, если знаете, что в имени будет только одно подчеркивание;в этом случае вы можете использовать substring-before() и substring-after(), чтобы получить две части имени.

...