Xml 基于节点值的递归XSLT1.0
我试图在XSLT 1.0中实现一个递归(树)列表,该列表从如下所示的XML开始:Xml 基于节点值的递归XSLT1.0,xml,xslt,recursion,sharepoint-2013,xslt-1.0,Xml,Xslt,Recursion,Sharepoint 2013,Xslt 1.0,我试图在XSLT 1.0中实现一个递归(树)列表,该列表从如下所示的XML开始: <list> <row> <icon>http://server/app/icon.gif</icon> <title>Document</title> <location>Root\Formulier</location> </row> <row>
<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>
http://server/app/icon.gif
文件
Root\Formulier
http://server/app/icon.gif
手工打样1
根\Handleidingen
http://server/app/icon.gif
类型
Root\Formulier\知情同意书(IC)
http://server/app/icon.gif
手工打样2
根\Handleidingen
这必须使用XSLT1.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>
-
-
其结果如下所示:
例如,“Formulier \知情同意书(IC)”显示每个文件夹之后的所有文件夹,而它应在\上拆分,并显示“Formulier”作为“知情同意书(IC)”的父文件夹。(我将“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>
-
根
-
公式制定者
-
知情同意(IC)
-
-
-
汉德雷丁根
-
-
有谁能给我一个信息源或代码,让我用XSLT1.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>
(*)您需要熟悉才能理解此解决方案。请将预期结果显示为代码。我的错,我添加了示例!这与这个问题几乎相同:@Tomalak这是不同的,因为在这里您需要为每个不同的位置步骤创建一个节点,而不仅仅是为每个文档创建一个节点,就像另一个答案那样。@Devil请将预期结果显示为代码(2)。