2012-01-06 57 views
1

我有以下形式的XML數據創建XML數據的TreeView:如何使用XSLT

<table> 
<col> 
    <name>Addresses</name> 
</col> 
<col> 
    <name>Addresses/Address1</name> 
</col> 
<col> 
    <name>Addresses/Address2</name> 
</col> 
<col> 
    <name>Addresses/Address1/Flat Number</name> 
</col> 
<col> 
    <name>Employee Name</name> 
</col> 
<col> 
    <name>Phone Number</name> 
</col> 
<col> 
    <name>Profession</name> 
</col> 
<col> 
    <name>Employee Name/First Name</name> 
</col> 
<col> 
    <name>Employee Name/Last Name</name> 
</col> 
<col> 
    <name>Employee Name/First_Name</name> 
</col> 
<col> 
    <name>Accounts/Account Name/First/Saving</name> 
</col> 
<col> 
    <name>Accounts/Account_Name/Second</name> 
</col> 
</table> 

現在我想創建像在使用這個XML XSLT HTML結構的樹形。樹視圖的結構將類似於以下結構:

  • 地址
    • 地址1
    • 地址2
  • 員工姓名
  • 帳戶
    • 帳戶名稱

請注意,「/」是樹狀的第一級節點和第一次出現後的子字符串「/」是第一次出現之前子匹配的第一級節點的第二級節點,這只是一個2級樹視圖。

此外,顯示的值是唯一的值。即使這些值在XML中重複,我們也只需要選擇唯一的一個值。需要考慮的另一個條件是,在示例中給出的「」的值與「」中的值不相同,因此我們需要在用「」替換「 - 」後顯示值。

<xsl:variable name="currentNode" select="//table/col" /> 
<xsl:key name="uniqueCategoryKey" match="record" use="name"/> 
<xsl:key name="uniqueSubCategoryKey" match="record" use="substring-before(substring-after(concat(name,'/'),'/'),'/')"/> 
<xsl:template match="/"> 
<xsl:call-template name="treeTemplate" /> 
</xsl:template> 

<xsl:template name="treeTemplate"> 


    <div id ="newtreeview"> 
    <ul> 
     <xsl:for-each select="$currentNode[generate-id() = generate-id(key('uniqueCategoryKey', name))]"> 

     <xsl:variable name="category" select="name"/> 

     <xsl:if test="string-length($category) > 0 and not(contains($category,'/'))"> 
      <li> 
      <a href="#"> 
       <xsl:value-of select="$category"/> 
      </a> 
      <xsl:if test="//record[contains(name, concat($category,'/'))]"> 
       <ul> 

       <xsl:for-each select="$currentNode[generate-id() = generate-id(key('uniqueSubCategoryKey', substring-before(substring-after(concat(name,'/'),'/'),'/')))]"> 

        <li> 
        <a href="#"> 
         <xsl:variable name="subcat"> 
         <xsl:call-template name="string-replace-all"> 
          <xsl:with-param name="text" select="string(substring-before(substring-after(concat(name,'/'),'/'),'/'))" /> 
          <xsl:with-param name="replace" select="'_'" /> 
          <xsl:with-param name="by" select="' '" /> 
         </xsl:call-template> 
         </xsl:variable> 
         <xsl:value-of select="$subcat"/> 


        </a> 
        </li> 
       </xsl:for-each> 
       </ul> 
      </xsl:if> 
      </li> 
     </xsl:if> 
     </xsl:for-each> 
    </ul> 
    </div> 

</xsl:template> 
<xsl:template name="string-replace-all"> 
<xsl:param name="text" /> 
<xsl:param name="replace" /> 
<xsl:param name="by" /> 
<xsl:choose> 
    <xsl:when test="contains($text, $replace)"> 
    <xsl:value-of select="substring-before($text,$replace)" /> 
    <xsl:value-of select="$by" /> 
    <xsl:call-template name="string-replace-all"> 
     <xsl:with-param name="text" 
     select="substring-after($text,$replace)" /> 
     <xsl:with-param name="replace" select="$replace" /> 
     <xsl:with-param name="by" select="$by" /> 
    </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:value-of select="$text" /> 
    </xsl:otherwise> 
</xsl:choose> 
</xsl:template> 

的問題是,這個代碼是給我像

  • 地址
      • 輸出 -
    • 地址1
    • 地址2
  • 員工姓名
      • -
  • 賬戶
    • 帳戶名稱
    • 帳戶名稱

請幫我解決這個問題。

在此先感謝。

+0

您可以提供可能的工作示例XML! – Treemonkey 2012-01-06 14:49:32

回答

2

此XSLT 1。0變換

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="kCatFromName" match="name" 
     use="substring-before(concat(.,'/'), '/')"/> 

    <xsl:key name="kValFromName" match="name[contains(., '/')]" 
     use="concat(substring-before(.,'/'), 
      '+', 
      translate(
       substring-before 
       (concat(substring-after(.,'/'), '/'), 
        '/' 
       ), 
       '_', 
       ' ' 
         ) 
       ) 
      "/> 

    <xsl:template match="/*"> 
     <ul> 
     <xsl:apply-templates mode="cat" select= 
      "*/name 
      [generate-id() 
      = 
       generate-id(key('kCatFromName', 
           substring-before(concat(.,'/'), '/') 
           )[1] 
         ) 
      ] 
      "/> 
     </ul> 
    </xsl:template> 

    <xsl:template match="name" mode="cat"> 
     <xsl:variable name="vCat" select= 
     "substring-before(concat(.,'/'), '/')"/> 
     <li><xsl:value-of select="$vCat"/></li> 

     <xsl:variable name="vInThisCat" select= 
     "key('kCatFromName', $vCat) 
     [generate-id() 
     = 
      generate-id(key('kValFromName', 
          concat(substring-before(.,'/'), 
           '+', 
           translate(
              substring-before 
              (concat(substring-after(.,'/'), '/'), 
              '/' 
              ), 
              '_', 
              ' ' 
              ) 
           ) 
         )[1] 
        ) 
     ]"/> 

     <xsl:if test="$vInThisCat"> 
     <ul> 
      <xsl:apply-templates mode="val" select="$vInThisCat"/> 
     </ul> 
     </xsl:if> 
    </xsl:template> 

     <xsl:template match="name" mode="val"> 
     <li> 
      <xsl:value-of select= 
      "translate(substring-before 
       (concat(substring-after(.,'/'), '/'), 
       '/' 
       ), 
       '_', 
       ' ' 
       ) 
      "/> 
     </li> 
     </xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔施加:

<table> 
    <col> 
     <name>Addresses</name> 
    </col> 
    <col> 
     <name>Addresses/Address1</name> 
    </col> 
    <col> 
     <name>Addresses/Address2</name> 
    </col> 
    <col> 
     <name>Addresses/Address1/Flat Number</name> 
    </col> 
    <col> 
     <name>Employee Name</name> 
    </col> 
    <col> 
     <name>Phone Number</name> 
    </col> 
    <col> 
     <name>Profession</name> 
    </col> 
    <col> 
     <name>Employee Name/First Name</name> 
    </col> 
    <col> 
     <name>Employee Name/Last Name</name> 
    </col> 
    <col> 
     <name>Employee Name/First_Name</name> 
    </col> 
    <col> 
     <name>Accounts/Account Name/First/Saving</name> 
    </col> 
    <col> 
     <name>Accounts/Account_Name/Second</name> 
    </col> 
</table> 

產生想要的,正確的結果

<ul> 
    <li>Addresses</li> 
    <ul> 
     <li>Address1</li> 
     <li>Address2</li> 
    </ul> 
    <li>Employee Name</li> 
    <ul> 
     <li>First Name</li> 
     <li>Last Name</li> 
    </ul> 
    <li>Phone Number</li> 
    <li>Profession</li> 
    <li>Accounts</li> 
    <ul> 
     <li>Account Name</li> 
    </ul> 
</ul> 

,它是由顯示瀏覽器爲

  • 地址
    • 地址1
    • 地址2
  • 員工姓名
  • 電話號碼
  • 職業
  • 賬戶
    • 帳戶名稱
+0

Navatchev,非常感謝:) ...您的XSLT代碼工作很好,但它顯示如下結果:

  • 地址
    • 地址1
    • 地址2
。在第一個列表項停止後,什麼都不顯示。我也有我的計劃有序列表作爲
  • 地址
    • 地址1
    • 地址2
...能否請你幫我顯示它新的這種格式,也是所有列表項不只是第一個。 – manishekhawat 2012-01-06 16:51:50

+0

對不起,我的問題是,爲什麼你的代碼不適合我,我正在更新XML,因爲我們沒有想過通過一個場景,然後我們可以再次嘗試獲得所需的結果。希望這次也能幫助我。 :) – manishekhawat 2012-01-06 16:59:58

+0

@manishekhawat:該代碼已經過測試,使用多個XSLT 1.0處理器(MSXML3/4,.NET XslCompledTransform,Saxon 6.5.4和AltovaXML(XML-SPY))正常工作並生成相同的* complete *結果。得到的結果不完整,要麼是更改了XML文檔,要麼是XSLT代碼,或者兩者都使用了,或者使用的是錯誤的,不兼容的XSLT處理器。 – 2012-01-06 17:07:38