我有以下要求:
new FileInputStream("/path/on/my/system/Data.xml")
我需要将其转换为以下XML:
{{1}}
首选XSLT 1.0解决方案。
基本上,元素名称应从大写字母开始,每个字母在下划线应为大写后出现。然后删除下划线。 请注意,这只需要应用于元素名称而不是文本。
答案 0 :(得分:4)
这在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:variable name="new-name">
<xsl:call-template name="PascalCase">
<xsl:with-param name="text" select="name()"/>
</xsl:call-template>
</xsl:variable>
<xsl:element name="{$new-name}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template name="PascalCase">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="'_'"/>
<xsl:param name="upper-case" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:param name="lower-case" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
<xsl:value-of select="translate(substring($token, 1, 1), $lower-case, $upper-case)" />
<xsl:value-of select="translate(substring($token, 2), $upper-case, $lower-case)" />
<xsl:if test="contains($text, $delimiter)">
<!-- recursive call -->
<xsl:call-template name="PascalCase">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
请注意,这只会转换明确列出的字符。
答案 1 :(得分:1)
此解决方案比目前接受的答案略短且效率更高。
在元素具有属性的情况下,它也能正常工作。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:template match="*">
<xsl:variable name="vEName"><xsl:call-template name="PCase"/></xsl:variable>
<xsl:element name="{$vEName}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template name="PCase">
<xsl:param name="pName" select="translate(name(), $vUpper, $vLower)"/>
<xsl:if test="$pName">
<xsl:variable name="vNextToken" select="substring-before(concat($pName, '_'), '_')"/>
<xsl:value-of select=
"concat(translate(substring($vNextToken,1,1), $vLower, $vUpper),
substring($vNextToken,2))"/>
<xsl:call-template name="PCase">
<xsl:with-param name="pName" select="substring-after($pName, '_')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
应用于以下XML文档(提供的具有添加属性的文档):
<TAG_ONE x="y">
<TAG_TWO>Abc</TAG_TWO>
<TAG_THREE>Xyz</TAG_THREE>
</TAG_ONE>
产生了想要的正确结果:
<TagOne x="y">
<TagTwo>Abc</TagTwo>
<TagThree>Xyz</TagThree>
</TagOne>
答案 2 :(得分:0)
使用非常复杂的XPath字符串串联子串,这是可能的。下面提供的实现只有在只有一个'_'下划线时才有效。对于更一般的情况,连接必须放在单独的命名模板中。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" />
<xsl:template match="node()[not(name()='')]">
<xsl:variable name="elemName">
<xsl:call-template name="toLower">
<xsl:with-param name="str" select="name()" />
</xsl:call-template>
</xsl:variable>
<xsl:element name="{concat(substring-before(concat(substring(name(),1,1),substring($elemName,2)),'_'),concat(substring(substring-after(name(),'_'),1,1),substring(substring-after($elemName,'_'),2)))}">
<xsl:apply-templates select="node() | @*" />
</xsl:element>
</xsl:template>
<xsl:template name="toLower">
<xsl:param name="str" />
<xsl:value-of select="translate($str,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')" />
</xsl:template>
</xsl:stylesheet>