2015-10-28 9 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)' показывает все папки после друг друга, в то время как он должен быть разделен на \ и показывать «Формуляр» в качестве родителя «Информированное согласие (IC)». (I substringed местоположение «Root \», но он должен показать на вершине как корневой узел)

Пример кода результата:

<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/create-a-nested-tree-structure-from-a-path-in-xslt – Tomalak

ответ

0

Я боюсь, что это может быть гораздо более сложным, чем это кажется.

  • Если вы хотите, чтобы отобразить узел для каждой папки (содержит ли он документа или нет), вы должны начать с tokenizing места Into отдельных папок.
  • Далее, вы должны устранить дубликаты из результата. *
  • Третьего шага расположить папки в иерархическую структуру , а также повторно прикрепить документы в их папки.

Вот эскиз можно использовать в качестве основы для таблицы стилей:

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.

Смежные вопросы