2013-02-19 97 views
1

我有一個具有組織層次結構的XML結構。 <pkEntity>元素是org的父級ID,<entityParent>是org的子級。我不知道父母/孩子組合的深度。我需要在下述狀態變換:XSLT父子組織層次結構不能正常工作

<EntityDimCollection> 
<EntityDim> 
<pkEntity>-9</pkEntity> 
<entityParent>-7</entityParent> 
<entityCode>Own_CP</entityCode> 

<entityType>OT</entityType> 
<essEntityCode>un.Own_CP</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>-8</pkEntity> 
<entityParent>-7</entityParent> 
<entityCode>Alternatives</entityCode> 

<entityType>OT</entityType> 
<essEntityCode>un.Alternatives</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>8555</pkEntity> 
<entityParent>-8</entityParent> 
<entityCode>Ex_BABRO</entityCode> 

<entityType>CF</entityType> 
<essEntityCode>un.Ex_BABRO</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>8752</pkEntity> 
<entityParent>-8</entityParent> 
<entityCode>Ex_SY</entityCode> 

<entityType>CF</entityType> 
<essEntityCode>un.Ex_SY</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>9731</pkEntity> 
<entityParent>-8</entityParent> 
<entityCode>NOR</entityCode> 

<entityType>LE</entityType> 
<essEntityCode>un.NOR</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1649940</pkEntity> 
<entityParent>9731</entityParent> 
<entityCode>NO</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.NO</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1838293</pkEntity> 
<entityParent>1649940</entityParent> 
<entityCode>UKONORWAY</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.UKONORWAY</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1127251</pkEntity> 
<entityParent>1838293</entityParent> 
<entityCode>2BUS</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.2BUS</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1127274</pkEntity> 
<entityParent>1127251</entityParent> 
<entityCode>3BUS_B</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.3BUS_B</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1988187</pkEntity> 
<entityParent>1127274</entityParent> 
<entityCode>4BUS_B</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.4BUS_B</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1988188</pkEntity> 
<entityParent>1988187</entityParent> 
<entityCode>5ADM_B</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.5ADM_B</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1988189</pkEntity> 
<entityParent>1988187</entityParent> 
<entityCode>5FVK_B</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.5FVK_B</essEntityCode> 

</EntityDim> 
<EntityDim> 
<pkEntity>1988190</pkEntity> 
<entityParent>1988189</entityParent> 
<entityCode>61_FVK_B</entityCode> 

<entityType>CG</entityType> 
<essEntityCode>un.NOR.61_FVK_B</essEntityCode> 

</EntityDim> 
</EntityDimCollection> 

並用馬克Veenstra溶液我得到輸出這樣

<?xml version="1.0" encoding="UTF-8"?> 
<client:LMSDetails xmlns:client="http://foo/bar"> 
    <client:ParentID>-9</client:ParentID> 
    <client:ChildID>-7</client:ChildID> 
    <client:name/> 
    <client:identifier>OT</client:identifier> 
    <client:isActive/> 
    <client:ParentID>-8</client:ParentID> 
    <client:ChildID>-7</client:ChildID> 
    <client:name/> 
    <client:identifier>OT</client:identifier> 
    <client:isActive/> 
    <client:children> 
     <client:ParentID>8555</client:ParentID> 
     <client:ChildID>-8</client:ChildID> 
     <client:name/> 
     <client:identifier>CF</client:identifier> 
     <client:isActive/> 
    </client:children> 
    <client:children> 
     <client:ParentID>8752</client:ParentID> 
     <client:ChildID>-8</client:ChildID> 
     <client:name/> 
     <client:identifier>CF</client:identifier> 
     <client:isActive/> 
    </client:children> 
    <client:children> 
     <client:ParentID>9731</client:ParentID> 
     <client:ChildID>-8</client:ChildID> 
     <client:name/> 
     <client:identifier>LE</client:identifier> 
     <client:isActive/> 
     <client:children> 
     <client:ParentID>1649940</client:ParentID> 
     <client:ChildID>9731</client:ChildID> 
     <client:name/> 
     <client:identifier>CG</client:identifier> 
     <client:isActive/> 
     <client:children> 
      <client:ParentID>1838293</client:ParentID> 
      <client:ChildID>1649940</client:ChildID> 
      <client:name/> 
      <client:identifier>CG</client:identifier> 
      <client:isActive/> 
      <client:children> 
       <client:ParentID>1127251</client:ParentID> 
       <client:ChildID>1838293</client:ChildID> 
       <client:name/> 
       <client:identifier>CG</client:identifier> 
       <client:isActive/> 
       <client:children> 
        <client:ParentID>1127274</client:ParentID> 
        <client:ChildID>1127251</client:ChildID> 
        <client:name/> 
        <client:identifier>CG</client:identifier> 
        <client:isActive/> 
        <client:children> 
        <client:ParentID>1988187</client:ParentID> 
        <client:ChildID>1127274</client:ChildID> 
        <client:name/> 
        <client:identifier>CG</client:identifier> 
        <client:isActive/> 
        <client:children> 
         <client:ParentID>1988188</client:ParentID> 
         <client:ChildID>1988187</client:ChildID> 
         <client:name/> 
         <client:identifier>CG</client:identifier> 
         <client:isActive/> 
        </client:children> 
        <client:children> 
         <client:ParentID>1988189</client:ParentID> 
         <client:ChildID>1988187</client:ChildID> 
         <client:name/> 
         <client:identifier>CG</client:identifier> 
         <client:isActive/> 
         <client:children> 
          <client:ParentID>1988190</client:ParentID> 
          <client:ChildID>1988189</client:ChildID> 
          <client:name/> 
          <client:identifier>CG</client:identifier> 
          <client:isActive/> 
         </client:children> 
        </client:children> 
        </client:children> 
       </client:children> 
      </client:children> 
     </client:children> 
     </client:children> 
    </client:children> 
    <client:ParentID>8555</client:ParentID> 
    <client:ChildID>-8</client:ChildID> 
    <client:name/> 
    <client:identifier>CF</client:identifier> 
    <client:isActive/> 
    <client:ParentID>8752</client:ParentID> 
    <client:ChildID>-8</client:ChildID> 
    <client:name/> 
    <client:identifier>CF</client:identifier> 
    <client:isActive/> 
    <client:ParentID>9731</client:ParentID> 
    <client:ChildID>-8</client:ChildID> 
    <client:name/> 
    <client:identifier>LE</client:identifier> 
    <client:isActive/> 
    <client:children> 
     <client:ParentID>1649940</client:ParentID> 
     <client:ChildID>9731</client:ChildID> 
     <client:name/> 
     <client:identifier>CG</client:identifier> 
     <client:isActive/> 
     <client:children> 
     <client:ParentID>1838293</client:ParentID> 
     <client:ChildID>1649940</client:ChildID> 
     <client:name/> 
     <client:identifier>CG</client:identifier> 
     <client:isActive/> 
     <client:children> 
      <client:ParentID>1127251</client:ParentID> 
      <client:ChildID>1838293</client:ChildID> 
      <client:name/> 
      <client:identifier>CG</client:identifier> 
      <client:isActive/> 
      <client:children> 
       <client:ParentID>1127274</client:ParentID> 
       <client:ChildID>1127251</client:ChildID> 
       <client:name/> 
       <client:identifier>CG</client:identifier> 
       <client:isActive/> 
       <client:children> 
        <client:ParentID>1988187</client:ParentID> 
        <client:ChildID>1127274</client:ChildID> 
        <client:name/> 
        <client:identifier>CG</client:identifier> 
        <client:isActive/> 
        <client:children> 
        <client:ParentID>1988188</client:ParentID> 
        <client:ChildID>1988187</client:ChildID> 
        <client:name/> 
        <client:identifier>CG</client:identifier> 
        <client:isActive/> 
        </client:children> 
        <client:children> 
        <client:ParentID>1988189</client:ParentID> 
        <client:ChildID>1988187</client:ChildID> 
        <client:name/> 
        <client:identifier>CG</client:identifier> 
        <client:isActive/> 
        <client:children> 
         <client:ParentID>1988190</client:ParentID> 
         <client:ChildID>1988189</client:ChildID> 
         <client:name/> 
         <client:identifier>CG</client:identifier> 
         <client:isActive/> 
        </client:children> 
        </client:children> 
       </client:children> 
      </client:children> 
     </client:children> 
     </client:children> 
    </client:children> 
</client:LMSDetails> 
+0

你可以發佈你當前的XSLT樣式表嗎? – 2013-02-19 13:42:42

+0

我現在沒有xslt。我必須建立,但不知道如何開始,請你幫助我。 – Sarah 2013-02-19 14:14:12

+0

您使用的是XSLT 1.0還是XSLT 2.0? – 2013-02-19 15:55:33

回答

2

XSLT 1.0(和XSLT 2.0)溶液

它是基於在使用< xsl:key>安排父母和孩子的同時提高解決方案的性能。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:client="http://client.org"> 

    <xsl:output method="xml" indent="yes" /> 

    <!-- Use keys to boost performance --> 
    <xsl:key name="entity-key" match="EntityDim" use="pkEntity" /> 
    <xsl:key name="parent-key" match="EntityDim" use="entityParent" /> 

    <!-- Process root element --> 
    <xsl:template match="EntityDimCollection"> 
     <client:LMSDetails> 
      <!-- Apply template to root entities, i.e. entities with no parent nodes --> 
      <xsl:apply-templates select="EntityDim[not(key('entity-key', entityParent))]" /> 
     </client:LMSDetails> 
    </xsl:template> 

    <!-- First one to use for the real parent --> 
    <xsl:template match="EntityDim"> 
     <!-- Obtain the relevant information --> 
     <client:ParentID><xsl:value-of select="pkEntity" /></client:ParentID> 
     <client:ChildID><xsl:value-of select="entityParent" /></client:ChildID> 
     <client:name/> 
     <client:identifier><xsl:value-of select="entityType" /></client:identifier> 
     <client:isActive/> 
     <client:costCenter> 
      <!-- Obtain the expression after the last dot in essEntityCode --> 
      <xsl:call-template name="get-suffix"> 
       <xsl:with-param name="text" select="essEntityCode" /> 
      </xsl:call-template> 
     </client:costCenter> 
     <!-- Outputs the children for this node : we just search which entities have the 
      current pkEntity as their entityParent--> 
     <xsl:for-each select="key('parent-key', pkEntity)"> 
      <client:children> 
       <xsl:apply-templates select="." /> 
      </client:children> 
     </xsl:for-each> 
    </xsl:template> 

    <!-- Recursive template to obtain the suffix from essEntityCode (the part after 
     the last dot) --> 
    <xsl:template name="get-suffix"> 
     <xsl:param name="text" /> 

     <!-- Check whether the current text contains a dot --> 
     <xsl:choose> 
      <!-- Case CONTAINS_DOT: recurse until there is not more dots in the string --> 
      <xsl:when test="contains($text, '.')"> 
       <xsl:call-template name="get-suffix"> 
        <xsl:with-param name="text" select="substring-after($text, '.')" /> 
       </xsl:call-template>    
      </xsl:when> 
      <!-- Case WITHOUT_DOTS : output suffix --> 
      <xsl:otherwise> 
       <xsl:value-of select="$text" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

XSLT 2.0只溶液

構建層次結構的方式是一樣的,唯一不同的是獲得來自essEntityCode後綴的方式。在XSLT 1.0中,我們必須構建一個遞歸模板來檢測最後一個點並提取後綴。但是,在XSLT 2.0中,我們可以使用函數tokenize,它使用給定的正則表達式來分割給定的字符串。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:client="http://client.org"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:key name="entity-key" match="EntityDim" use="pkEntity" /> 
    <xsl:key name="parent-key" match="EntityDim" use="entityParent" /> 

    <xsl:template match="EntityDimCollection"> 
     <client:LMSDetails> 
      <xsl:apply-templates select="EntityDim[not(key('entity-key', entityParent))]" /> 
     </client:LMSDetails> 
    </xsl:template> 

    <xsl:template match="EntityDim"> 
     <client:ParentID><xsl:value-of select="pkEntity" /></client:ParentID> 
     <client:ChildID><xsl:value-of select="entityParent" /></client:ChildID> 
     <client:name/> 
     <client:identifier><xsl:value-of select="entityType" /></client:identifier> 
     <client:isActive/> 
     <client:costCenter> 
      <!-- This is the only difference from the XSLT 1.0 solution, instead 
       of calling the recursive template we tokenize the expression and 
       obtain the last element (which is the suffix) --> 
      <xsl:value-of select="tokenize(essEntityCode, '\.')[last()]" /> 
     </client:costCenter> 
     <xsl:for-each select="key('parent-key', pkEntity)"> 
      <client:children> 
       <xsl:apply-templates select="." /> 
      </client:children> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stelesheet> 

編輯:我認爲每個孩子一個新的<客戶:兒童>創建,該行爲可以通過調整代碼在<的for-each>循環變化。

+1

我還沒有意識到的使用很好,所以從來沒有使用它或者在現在看過它。我只是看了一下http://www.w3schools.com/xsl/el_key.asp,確實令人印象深刻。仍在學習... Upvoted你的答案。感謝您的學習! – 2013-02-19 17:39:46

+2

我很高興你發現代碼有用。 通常用於在必須重複訪問同一組元素時和/或從樣式表中的不同位置(它就像索引)訪問同一組元素。有一種XSLT 1.0技術用於對元素進行分組,並依賴於元素。這項技術被稱爲「Muenchian分組」。 – 2013-02-19 18:50:19