这种转变:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my" exclude-result-prefixes="my xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vSegments" select=
"tokenize(translate(/*, ' 	

', ''),
'~')
[.]
"/>
<xsl:template match="/*">
<xsl:sequence select="my:buildXml($vSegments)"/>
</xsl:template>
<xsl:function name="my:buildXml">
<xsl:param name="pSegments" as="xs:string*"/>
<xsl:element name="{$pSegments[1]}">
<xsl:sequence select="my:buildXml2($pSegments[position() >1])"/>
</xsl:element>
</xsl:function>
<xsl:function name="my:buildXml2">
<xsl:param name="pSegments" as="xs:string*"/>
<xsl:for-each-group select="$pSegments"
group-adjacent="substring-before(concat(.,'/'),'/')">
<xsl:element name="{current-grouping-key()}">
<xsl:variable name="vsubSegments" select=
"for $subSeg in current-group(),
$subSeqTail in substring-after($subSeg, '/')
return
$subSeqTail[.]
"/>
<xsl:sequence select=
"my:buildXml2($vsubSegments)"/>
</xsl:element>
</xsl:for-each-group>
</xsl:function>
</xsl:stylesheet>
当应用于以下 XML 文档时(使用稍微复杂的字符串使其更具挑战性):
<t>
author
~time
~assignedAuthor
~assignedAuthor/id
~assignedAuthor/addr
~assignedAuthor/telecom
~assignedAuthor/assignedPerson/name
~assignedAuthor/assignedPerson/address~
</t>
产生想要的正确结果:
<author>
<time/>
<assignedAuthor>
<id/>
<addr/>
<telecom/>
<assignedPerson>
<name/>
<address/>
</assignedPerson>
</assignedAuthor>
</author>
说明:
“段”序列的标记化。的使用tokenize()
。
xsl:for-each-group
将属性分组 ( )group-adjacent
使用作为分组键的第一个“子段”。
对于以递归方式构建 XML 子树的每个组。使用current-grouping-key()
和current-group()