2011-04-18 258 views
1

我试图使用XSLT从平面XML文件创建分层XML文件,但不确定最佳方法是什么。使用XSLT将平面XML结构更改为层次结构

例如我需要

<root> 
<inventory bag="1" fruit="apple"/> 
<inventory bag="1" fruit="banana"/> 
<inventory bag="2" fruit="apple"/> 
<inventory bag="2" fruit="orange"/> 
</root> 

转换为

<inventory> 
<baglist> 
<bag id="1"/> 
<bag id="2"/> 
</baglist> 

<bag id="1"> 
<fruit id="apple"/> 
<fruit id="banana"/> 
</bag> 

<bag id="2"> 
<fruit id="apple"/> 
<fruit id="orange"/> 
</bag> 
</inventory> 

N个袋/水果

回答

0

inventory元件基于它们bag属性的值:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="byBag" match="root/inventory" use="@bag" /> 
    <xsl:template match="/"> 
     <inventory> 
      <baglist> 
       <xsl:apply-templates mode="baglist" /> 
      </baglist> 
      <xsl:apply-templates /> 
     </inventory> 
    </xsl:template> 
    <xsl:template 
     match="root/inventory[generate-id() = 
          generate-id(key('byBag', @bag)[1])]" 
         mode="baglist"> 
     <bag id="{@bag}" /> 
    </xsl:template> 

    <xsl:template 
     match="root/inventory[generate-id() = 
          generate-id(key('byBag', @bag)[1])]"> 
     <bag id="{@bag}"> 
      <xsl:apply-templates select="key('byBag', @bag)" 
       mode="details" /> 
     </bag> 
    </xsl:template> 

    <xsl:template match="inventory" mode="details"> 
     <fruit id="{@fruit}" /> 
    </xsl:template> 
</xsl:stylesheet> 
+1

谢谢,所以如果我明白这个正确,生成-ID()返回一个唯一的ID为当前节点,并且生成-ID (key(stuff)[1])用给定的bagid返回第一个节点的唯一标识符。这样,每个独特的bagid只有一个节点将与模板匹配。 – 2011-04-18 19:30:30

+0

@N。岸 - 正是。然后,当我们将模板应用到'key('byBag',@bag)'时,我们指定一个'mode',这样我们就可以处理组中的所有项目,而无需重新匹配仅选择第一个项目的模板。这种技术被称为Muenchian方法进行分组。 – 2011-04-18 19:47:42

+0

+1正确答案。 – 2011-04-18 20:44:38

0

的xsl:for-each您的节点两次,或使用xsl:template不同的模式。