使用 XSLT 将 XML 元素名称转换为驼峰式格式
Converting XML element names to camelCase format using XSLT
我需要使用 XSLT 将 XML 中的所有元素名称转换为驼峰命名策略。
这是即将到来的服务器的响应:
<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>
如有任何帮助,我们将不胜感激。
在 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
),并且在您处理一个标记的命名模板中,您'将需要使用 translate($x, 'abc...z', 'ABC...Z')
进行大小写转换。
如果知道名称中只有一个下划线,就可以避免递归并简化逻辑;在这种情况下,您可以使用 substring-before()
和 substring-after()
来获取名称的两个部分。
假设元素名称中最多有一个 _
分隔符,并且假设名称中不包含非 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
参数中列出。
另一种在 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>
<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>
如果可以使用此代码,再回答一个问题。
我需要使用 XSLT 将 XML 中的所有元素名称转换为驼峰命名策略。
这是即将到来的服务器的响应:
<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>
如有任何帮助,我们将不胜感激。
在 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
),并且在您处理一个标记的命名模板中,您'将需要使用 translate($x, 'abc...z', 'ABC...Z')
进行大小写转换。
如果知道名称中只有一个下划线,就可以避免递归并简化逻辑;在这种情况下,您可以使用 substring-before()
和 substring-after()
来获取名称的两个部分。
假设元素名称中最多有一个 _
分隔符,并且假设名称中不包含非 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
参数中列出。
另一种在 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>
<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>
如果可以使用此代码,再回答一个问题。