2013-02-14 52 views
0

在此需要您的指導。XSL從非規格化數據集創建父級層次結構

我想創建一個父子XML的是被非規範化的XML的:

FROM:

<Parent>Parent1</Parent> 
<Child>Child1</Child> 
<Parent>Parent2</Parent> 
<Child>Child1</Child> 
<Child>Child2</Child> 
<Parent>Parent3</Parent> 
<Child>Child1</Child> 

TO:

<Parent> 
<ParentValue>Parent1</ParentValue> 
<Child> 
    <ChildValue>Child1</ChildValue> 
</Child> 
</Parent> 
<Parent> 
<ParentValue>Parent2</ParentValue> 
<Child> 
    <ChildValue>Child1</ChildValue> 
</Child> 
<Child> 
    <ChildValue>Child2</ChildValue> 
</Child> 
</Parent> 
<Parent> 
<ParentValue>Parent3</ParentValue> 
<Child> 
    <ChildValue>Child1</ChildValue> 
</Child> 
</Parent> 

的問題是,我不能找出要說的邏輯,獲取每個父元素之間的所有Child元素。

任何幫助表示讚賞。

非常感謝您關注此事。

+0

Y ou可能會檢查[這個類似的問題](http://stackoverflow.com/questions/14780330/how-to-turn-flat-xml-array-into-tree)。 – 2013-02-14 20:09:08

+0

您使用的是XSLT1.0還是XSLT2.0? – 2013-02-14 20:49:05

回答

4

在XSLT1.0中,您可以使用鍵實現此目的。您有效分組兒童通過他們的第一元素之前父元素,這樣你就可以定義以下項:

<xsl:key name="child" match="Child" use="generate-id(preceding-sibling::Parent[1])"/> 

然後,該元素相匹配的模板中,你可以得到所有的相關兒童元素,像這樣:

<xsl:apply-templates select="key('child', generate-id())"/> 

下面是在這種情況下,全XSLT。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:key name="child" match="Child" use="generate-id(preceding-sibling::Parent[1])"/> 

    <xsl:template match="Family"> 
     <Family> 
     <xsl:apply-templates select="Parent"/> 
     </Family> 
    </xsl:template> 

    <xsl:template match="Parent"> 
     <Parent> 
     <ParentValue> 
      <xsl:value-of select="."/> 
     </ParentValue> 
     <xsl:apply-templates select="key('child', generate-id())"/> 
     </Parent> 
    </xsl:template> 

    <xsl:template match="Child"> 
     <Child> 
     <ChildValue> 
      <xsl:value-of select="."/> 
     </ChildValue> 
     </Child> 
    </xsl:template> 
</xsl:stylesheet> 

當適用於您XML中的以下輸出:

<Family> 
    <Parent> 
     <ParentValue>Parent1</ParentValue> 
     <Child> 
     <ChildValue>Child1</ChildValue> 
     </Child> 
    </Parent> 
    <Parent> 
     <ParentValue>Parent2</ParentValue> 
     <Child> 
     <ChildValue>Child1</ChildValue> 
     </Child> 
     <Child> 
     <ChildValue>Child2</ChildValue> 
     </Child> 
    </Parent> 
    <Parent> 
     <ParentValue>Parent3</ParentValue> 
     <Child> 
     <ChildValue>Child1</ChildValue> 
     </Child> 
    </Parent> 
</Family> 

在XSLT2.0您可以利用的xsl:對,每個組。在你的情況下,你想分組元素開始

<xsl:for-each-group select="*" group-starting-with="Parent"> 

然後選擇兒童元素,你可以使用使用當前組功能:

<xsl:apply-templates select="current-group()[position() &gt; 1]" /> 

這裏是2.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/Family"> 
    <Family> 
     <xsl:for-each-group select="*" group-starting-with="Parent"> 
     <Parent> 
      <ParentValue> 
       <xsl:value-of select="."/> 
      </ParentValue> 
      <xsl:apply-templates select="current-group()[position() &gt; 1]" /> 
     </Parent> 
     </xsl:for-each-group> 
    </Family> 
    </xsl:template> 

    <xsl:template match="Child"> 
     <Child> 
     <ChildValue> 
      <xsl:value-of select="."/> 
     </ChildValue> 
     </Child> 
    </xsl:template> 
</xsl:stylesheet> 

這充分XSLT也應該輸出相同的結果:

+0

謝謝蒂姆!你是一個拯救生命的人!您的XSLT 2.0示例爲我做了訣竅。 – rafter 2013-02-17 01:04:34