以编程方式编辑Sharepoint Wiki内容

8
我希望能够通过编程方式编辑我的Sharepoint Wiki内容。其中一个优点是可以自动向Wiki环境中添加索引。
有人能够做到这一点吗?语言不重要,但需要寻找脚本解决方案。
2个回答

7
是的。我已经自己开发了一个Metaweblog API,用于以编程方式管理Sharepoint 2010和2007中的wiki页面。
我的资源: SP 2010和2007的服务代码几乎相同,但有一些注意事项。
  • 在2010年,无需担心管理维基链接标记(例如[[方括号]])。
  • 在2007年,维基标记将根据您的请求进行转换,因此您必须在发布之前重新转换为维基标记。在发布时,您不能使用UpdateListItems,而必须使用Copy服务。这是因为UpdateListItems将转义任何维基标记,从而使您的努力无用。
  • 在我们的环境中,在检入之前需要填写RecordType。也许这是标准的?如果您没有设置此字段,则您的页面将保留为已检出状态。因此,我有一个条件为SP2007设置此字段。
  • 在2010年,SP在原始WikiField值中添加了大量标记,如果缺少它可能会破坏布局。我只是在WLW发布的值周围插入它,然后在获取时将其删除。请参见以下内容。

我像第一个链接中那样使用Copy服务来创建和更新维基页面。在2010年,您可以使用Lists服务进行更新,但不能添加。 我使用Imaging服务自动上传图像到图片库。

以下是将“ms-wikilinks”替换为维基标记的函数:

注意:我使用HTMLAgilityPack以防返回的标记格式不正确。您也可以使用Regex来完成此操作。我还使用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维基的人非常有帮助。使用WLW,我可以自动上传图片,获得更好的HTML编辑支持,并支持像PreCode Snippet这样的插件。太棒了!


4
一个SharePoint Wiki只是一个特殊类型的文档库。在尝试使用它时,我遇到了一些奇怪的问题。
一个SharePoint Wiki页面由一个模板文件和一个列表项组成。当您查看页面时,列表项中的字段将插入到模板文件中。因此,要更新Wiki页面,您只需更新列表项中的正确字段。(顺便说一句,这也意味着您无法像在普通文档库中那样访问原始模板。到目前为止,我发现唯一获取模板本身的方法是通过SharePoint Designer下载它。)
此外,当您以编程方式访问列表项时,SharePoint会自动呈现Wiki内容。因此,我从未能够获取包含"[[My Link Name]]"的内容 - 例如,SharePoint总是返回已呈现的HTML,如:
<A class=ms-wikilink href="/MyWikiLibrary/MyLinkName.aspx">My Link Name</A>

通过一些正则表达式的处理,您应该能够将其转换回原始的维基内容。


有人找到了如何在没有SharePoint Designer的情况下获取模板吗? - C. Ross
2
解析维基链接的正则表达式很容易,但反过来就不行了。如果你使用UpdateListItems并在WikiField中留下[[括号]],SharePoint会将其转换为\[[括号]\],这让我感到非常困惑。我无法弄清楚如何避免这种情况;如果我手动转换链接,SharePoint将把它们视为链接而不是原始维基标记。这是一个两败俱伤的局面。在SP2010中,这个问题已经得到解决,一切都运作良好。我正在尝试让它在SP2007中工作。 - kamranicus
2
找到了解决方案。您可以使用复制服务进行插入和更新,只需保持名称相同即可。然后它将以原始维基标记形式接收标记,并按预期工作。太棒了! - kamranicus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接