使用XSLT基于字符串模式自动创建xml模板

时间:2011-12-23 19:54:40

标签: xml xslt xpath xslt-2.0 xpath-2.0

我在下面的模式中有字符串

  

作者〜时间〜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>

我可以为此提供可能的解决方案。

1 个答案:

答案 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(/*, ' &#9;&#xA;&#xD;', ''),
            '~')
               [.]
  "/>

  <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>

解释

  1. “段”序列的标记化。使用tokenize()

  2. 使用属性xsl:for-each-groupgroup-adjacent分组为第一个“子细分”作为分组键。

  3. 对于每个以递归方式构建XML子树的组。使用current-grouping-key()current-group()