2015-10-28 146 views
0

我試圖實現XSLT 1.0遞歸(樹)從列表看起來像這樣的XML開始:遞歸XSLT 1.0基於節點值

<list> 
    <row> 
    <icon>http://server/app/icon.gif</icon> 
    <title>Document</title> 
    <location>Root\Formulier</location> 
    </row> 
    <row> 
    <icon>http://server/app/icon.gif</icon> 
    <title>Handleiding1</title> 
    <location>Root\Handleidingen</location> 
    </row> 
    <row> 
    <icon>http://server/app/icon.gif</icon> 
    <title>Form</title> 
    <location>Root\Formulier\Informed consent (IC)</location> 
    </row> 
    <row> 
    <icon>http://server/app/icon.gif</icon> 
    <title>Handleiding2</title> 
    <location>Root\Handleidingen</location> 
    </row> 
</list> 

這必須使用XSLT 1.0,因爲我們SharePoint目前不支持2.0。

它在Windows資源管理器中應該看起來像一棵樹。

電流XSLT代碼我是:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:key name="groups" match="/list/row" use="location" /> 
    <xsl:template match="/list"> 
    <div class="idocument-list"> 
     <xsl:apply-templates select="row[generate-id() = generate-id(key('groups', location)[1])]"/> 
    </div> 
    </xsl:template> 
    <xsl:template match="row"> 
    <div style="margin-bottom:5px;"> 
     <ul> 
     <li> 
      <img border="0" style="align:left;" src="/_layouts/15/images/folder.gif?rev=23" alt="map" /> 
      <span class="ms-textLarge idocumentlist-title"> 
      <xsl:value-of select="substring-after(location,'Root\')"/> 
      </span> 
      <ul style="display:none;"> 
      <xsl:for-each select="key('groups', location)"> 
       <li> 
       <img border="0" style="align:left;"> 
        <xsl:attribute name="src"> 
        <xsl:value-of select="icon"/> 
        </xsl:attribute> 
       </img> 
       <span> 
        <a> 
        <xsl:attribute name="href"> 
         <xsl:value-of select="link"/> 
        </xsl:attribute> 
        <xsl:value-of select="title"/> 
        </a> 
       </span> 
       </li> 
      </xsl:for-each> 
      </ul> 
     </li> 
     </ul> 
    </div> 
    </xsl:template> 
</xsl:stylesheet> 

其示出了像結果:

result

其中例如 'Formulier \知情同意(IC)' 示出的所有文件夾然後將其分開,並將「Formulier」作爲「知情同意書(IC)」的母公司。 (我substringed的「根\」的位置,但是它應該顯示在上面作爲根節點)

結果舉例代碼:

<div class="idocument-list"> 
    <ul> 
    <li> 
     <img style="align: left;" alt="map" src="..." border="0"> 
     <span class="ms-textLarge idocumentlist-title">Root</span> 
     <ul> 
     <li> 
      <img style="align: left;" alt="map" src="..." border="0"> 
      <span class="ms-textLarge idocumentlist-title">Formulier</span> 
      <ul> 
      <li> 
       <img style="align: left;" alt="map" src="..." border="0"> 
       <span class="ms-textLarge idocumentlist-title">Informed consent (IC)</span> 
       <ul> 
       <li> 
        <img style="align: left;" src="..." border="0"> 
        <span> 
        <a href="...">Form</a> 
        </span> 
       </li> 
       </ul> 
      </li> 
      <li> 
       <img style="align: left;" alt="map" src="..." border="0"> 
       <span> 
       <a href="...">Document</a> 
       </span> 
      </li> 
      </ul> 
     </li> 
     <li> 
      <img style="align: left;" alt="map" src="..." border="0"> 
      <span class="ms-textLarge idocumentlist-title">Handleidingen</span> 
      <ul> 
      <li> 
       <img style="align: left;" src="..." border="0"> 
       <span> 
       <a href="...">Handleiding1</a> 
       </span> 
      </li> 
      <li> 
       <img style="align: left;" src="..." border="0"> 
       <span> 
       <a href="...">Handleiding2</a> 
       </span> 
      </li> 
      </ul> 
     </li> 
     </ul> 
    </li> 
    </ul> 
</div> 

誰能給我的信息或代碼源一起玩用XSLT 1.0實現這樣的事情?

在此先感謝。

Nils

+0

請將預期結果**顯示爲代碼**。 –

+0

我的不好,我添加了這個例子! – AppSum

+0

這與這個問題幾乎相同:http:// stackoverflow。com/questions/872067/Creating-a-nested-tree-structure-from-a-path-in-xslt – Tomalak

回答

0

恐怕這可能比看起來複雜得多。

  • 如果要顯示每個文件夾中的一個節點(是否含有 文件或沒有),您必須通過符號化開始位置到 單個文件夾。
  • 接下來,您必須消除從結果的重複。*
  • 第三步是安排文件夾到一個層次結構 並重新連接的文件,其文件夾。

這裏,你可以爲你的樣式表的基礎上使用草圖:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<xsl:key name="location-by-path" match="location" use="@path" /> 
<xsl:key name="location-by-parent" match="location" use="@parent-path" /> 
<xsl:key name="document-by-location" match="row" use="location" /> 

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

<!-- 1st pass: tokenize paths to individual locations --> 
<xsl:variable name="locations"> 
    <xsl:for-each select="/list/row"> 
     <xsl:call-template name="tokenize"> 
      <xsl:with-param name="text" select="location"/> 
     </xsl:call-template> 
    </xsl:for-each> 
</xsl:variable> 

<!-- 2nd pass: distinct locations only --> 
<xsl:variable name="distinct-locations"> 
    <xsl:copy-of select="exsl:node-set($locations)/location[count(. | key('location-by-path', @path)[1]) = 1]"/> 
</xsl:variable> 
<xsl:variable name="distinct-locations-set" select="exsl:node-set($distinct-locations)" /> 

<!-- output --> 
<xsl:template match="/list"> 
    <root> 
     <!-- start with progenitor locations --> 
     <xsl:apply-templates select="$distinct-locations-set/location[@parent-path='']"/> 
    </root> 
</xsl:template> 

<xsl:template match="location"> 
    <xsl:variable name="path" select="@path" /> 
    <xsl:element name="{@name}"> 
     <!-- set context to XML input --> 
     <xsl:for-each select="$xml"> 
      <!-- get documents --> 
      <xsl:apply-templates select="key('document-by-location', $path)"/> 
     </xsl:for-each> 
     <!-- set context to distinct locations --> 
     <xsl:for-each select="$distinct-locations-set"> 
      <!-- get subdirectories --> 
      <xsl:apply-templates select="key('location-by-parent', concat($path, '\'))"/> 
     </xsl:for-each> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="row"> 
    <document name="{title}"/> 
</xsl:template> 

<xsl:template name="tokenize"> 
    <xsl:param name="text"/> 
    <xsl:param name="parent-path"/> 
    <xsl:param name="delimiter" select="'\'"/> 
    <xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" /> 
    <xsl:if test="$token"> 
     <location name="{$token}" path="{concat($parent-path, $token)}" parent-path="{$parent-path}"/> 
    </xsl:if> 
    <xsl:if test="contains($text, $delimiter)"> 
     <!-- recursive call --> 
     <xsl:call-template name="tokenize"> 
      <xsl:with-param name="text" select="substring-after($text, $delimiter)"/> 
      <xsl:with-param name="parent-path" select="concat($parent-path, $token, $delimiter)"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 


</xsl:stylesheet> 

結果,當應用到你的榜樣輸入,將是:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <rootfolder> 
     <document name="Doc2"/> 
     <folder1> 
     <document name="Doc3"/> 
     <folder1.1> 
      <folder1.1.1> 
       <document name="Doc1"/> 
      </folder1.1.1> 
     </folder1.1> 
     </folder1> 
     <folder2> 
     <folder2.1> 
      <folder2.1.1> 
       <document name="Doc4"/> 
      </folder2.1.1> 
     </folder2.1> 
     </folder2> 
    </rootfolder> 
</root> 

(*)您需要熟悉Muenchian grouping才能理解此解決方案。