我在下面的模式中有字符串
作者〜时间〜assignedAuthor〜assignedAuthor / ID〜assignedAuthor /地址〜assignedAuthor /电信〜assignedAuthor / assignedPerson /名称〜
第一个元素一直是root(在上面的字符串模式中,它是 author ),其余部分是用字符'〜'删除的子元素。我想通过使用上面的字符串模式使用XSLT 2.0创建XML,我想生成以下XML。
<author>
<time/>
<assignedAuthor>
<id/>
<addr/>
<telecom/>
<assignedPerson>
<name/>
</assignedPerson>
</assignedAuthor>
</author>
我可以为此提供可能的解决方案。
答案 0 :(得分:3)
此转化:
<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()