以编程方式编辑 Sharepoint Wiki 内容
-
05-07-2019 - |
题
我想以编程方式编辑我的 Sharepoint Wiki 内容。优点之一是自动向 Wiki 环境添加索引。
有人能够做到这一点吗?语言并不重要,重要的是寻找脚本解决方案。
解决方案
SharePoint wiki只是一种特殊类型的文档库。尝试这样做时,我遇到了一些奇怪的事情。
SharePoint维基页面由模板文件和列表项组成。查看页面时,列表项中的字段将插入模板文件中。因此,要更新Wiki页面,您只需更新列表项中的正确字段即可。 (顺便说一句,这也意味着你不能像普通文档库中的文件那样获得原始模板。到目前为止,我发现获取模板本身的唯一方法是通过SharePoint Designer下载它。)
此外,当您以编程方式访问列表项时,SharePoint会自动呈现Wiki内容。所以,我从来没有能够获得包含“[[我的链接名称]],”的内容。例如 - SharePoint总是会返回呈现的HTML,例如:
<A class=ms-wikilink href="/MyWikiLibrary/MyLinkName.aspx">My Link Name</A>
通过一些正则表达式工作,您应该能够将其转换回原始的wiki内容。
其他提示
是的。我推出了自己的 Metaweblog API,以编程方式管理 Sharepoint 2010 和 2007 中的 wiki 页面。
我的资料来源:
- http://sites.google.com/site/sharepointwikiuploader/
- http://blogs.msdn.com/b/dwinter/archive/2008/06/28/migration-wiki-pages-remotely-part-01.aspx (第 1 - 6 部分)
SP 2010 和 2007 的服务代码几乎相同,但有一些注意事项:
- 在 2010 年,无需担心管理 wiki 链接标记(例如[[括号]])。
- 2007 年,Wiki 标记会根据您的请求进行转换,因此您必须在发回之前将其重新转换为 Wiki 标记。发回后,您 不能 使用UpdateListItems,必须使用Copy服务。这是因为 UpdateListItems 会转义任何 wiki 标记,从而有效地使您的努力毫无用处。
- 在我们的环境中,我们需要 记录类型 入住前需填写。也许这是标准的?如果您不设置此字段,您的页面将保持签出状态。因此,我有一个为 SP2007 设置此字段的条件。
- 2010 年,SP 在原始 WikiField 值中添加了一堆标记,如果缺少它可能会弄乱布局。我只是将它插入到 WLW 发布的值周围,然后在获取时将其删除。见下文。
我使用第一个链接中的复制服务来创建和更新 wiki 页面。2010年,你 能 使用列表服务进行更新,但不能添加。我使用图像服务将图像自动上传到图片库。
这是一个将“ms-wikilinks”替换为 wiki 标记的函数:
笔记: 我使用 HTMLAgilityPack 以防返回的标记格式错误。您也可以使用正则表达式来执行此操作。我还使用 Microsoft Anti-XSS 4.1 库来清理标记。
笔记2: 我的 UrlDecode 函数不依赖于 System.Web, 取自这里.
/// <summary>
/// Sharepoint 2007 is mean and converts [[wiki links]] once the page is saved in the Sharepoint editor.
/// Luckily, each link is decorated with class="ms-wikilink" and follows some conventions.
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
private static string ConvertAnchorsToWikiLinks(this string html)
{
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
var anchorTags = (from d in htmlDoc.DocumentNode.Descendants()
where d.Attributes.Contains("class") && d.Attributes["class"].Value == "ms-wikilink"
select d).ToList();
foreach (var anchor in anchorTags)
{
// Two kinds of links
// [[Direct Link]]
// [[Wiki Page Name|Display Name]]
var wikiPageFromLink = UrlDecode(anchor.Attributes["href"].Value.Split('/').LastOrDefault().Replace(".aspx", ""));
var wikiPageFromText = anchor.InnerText;
HtmlNode textNode = null;
if (wikiPageFromLink == wikiPageFromText)
{
// Simple link
textNode = HtmlTextNode.CreateNode("[[" + wikiPageFromText + "]]");
}
else
{
// Substituted link
textNode = HtmlTextNode.CreateNode(String.Format("[[{0}|{1}]]", wikiPageFromLink, wikiPageFromText));
}
if (textNode != null)
{
anchor.ParentNode.ReplaceChild(textNode, anchor);
}
}
return htmlDoc.DocumentNode.InnerHtml;
}
剥离SharePoint HTML 的函数是:
/// <summary>
/// Gets editable HTML for a wiki page from a SharePoint HTML fragment.
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
public static string GetHtmlEditableContent(string html)
{
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
HtmlNode divNode = (from d in htmlDoc.DocumentNode.Descendants()
where d.Attributes.Contains("class") && d.Attributes["class"].Value == "ms-rte-layoutszone-inner"
select d).FirstOrDefault();
HtmlNode divNode2 = (from d in htmlDoc.DocumentNode.Descendants()
where d.Attributes.Contains("class") && d.Attributes["class"].Value.StartsWith("ExternalClass")
select d).FirstOrDefault();
if (divNode != null)
{
// SP 2010
return divNode.InnerHtml;
}
else if (divNode2 != null)
{
// SP 2007 or something else
return divNode2.InnerHtml.ConvertAnchorsToWikiLinks();
}
else
{
return null;
}
}
最后,将标记全部添加回来的函数:
/// <summary>
/// Inserts SharePoint's wrapping HTML around wiki page content. Stupid!
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
public static string InsertSharepointHtmlWrapper(string html, SharePointVersion spVersion)
{
// No weird wrapper HTML for 2007
if (spVersion == SharePointVersion.SP2007)
return Microsoft.Security.Application.Sanitizer.GetSafeHtmlFragment(html);
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(@"<table id='layoutsTable' style='width:100%'>
<tbody>
<tr>
<td>
<div class='ms-rte-layoutszone-outer' style='width:99.9%'>
<div class='ms-rte-layoutszone-inner' style='min-height:60px;word-wrap:break-word'>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<span id='layoutsData' style='display:none'>false,false,1</span>");
HtmlNode divNode = (from d in htmlDoc.DocumentNode.Descendants()
where d.Attributes.Contains("class") && d.Attributes["class"].Value == "ms-rte-layoutszone-inner"
select d).FirstOrDefault();
divNode.InnerHtml = Microsoft.Security.Application.Sanitizer.GetSafeHtmlFragment(html);
return htmlDoc.DocumentNode.InnerHtml;
}
这很好用。
- 页面仍然保留最后修改和正确的用户
- 页面将保留其所有历史记录
- 页面更易于管理
我正在考虑发布我的 API,这并不是很多代码,我认为对于我们这些想要更好地管理 Sharepoint wiki 的人来说非常有帮助。通过 WLW,我可以获得自动图像上传、更好的 HTML 编辑支持以及对 PreCode Snippet 等插件的支持。这很棒!