Sharepoint Wikiコンテンツをプログラムで編集する
-
05-07-2019 - |
質問
Sharepoint Wikiのコンテンツをプログラムで編集したい。利点の1つは、Wiki環境にインデックスを自動的に追加することです。
誰でもこれを行うことができましたか?言語は関係ありませんが、スクリプトソリューションを探しています。
解決
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>
ちょっとした正規表現の作業で、これを元のwikiコンテンツに変換できるはずです。
他のヒント
はい。 Sharepoint 2010および2007でWikiページをプログラムで管理する独自のMetaweblog APIを公開しました。
私のソース:
- http://sites.google.com/site/sharepointwikiuploader/ >
- http://blogs.msdn.com/b/dwinter/archive/2008/06/28/migrating-wiki-pages-remotely-part-01.aspx (パート1〜6)
SP 2010と2007の両方のサービスコードはほぼ同じですが、いくつか注意点があります:
- 2010年には、Wikiリンクマークアップの管理について心配する必要はありません(例:[[brackets]])。
- 2007年、Wikiマークアップはリクエストに応じて変換されるため、投稿する前にWikiマークアップに再変換する必要があります。ポストバック時に、UpdateListItemsを使用することはできません。コピーサービスを使用する必要があります。これは、UpdateListItemsがすべてのwikiマークアップをエスケープし、事実上あなたの努力を役に立たなくするからです。
- この環境では、チェックインする前に RecordType を入力する必要があります。これが標準的なのでしょうかこのフィールドを設定しない場合、ページはチェックアウトされたままになります。そのため、SP2007にこのフィールドを設定する条件があります。
- 2010年、SPは未加工のWikiField値に大量のマークアップを追加します。欠落している場合、レイアウトを台無しにする可能性があります。 WLWが投稿している値の周りに挿入し、取得時に削除します。以下を参照してください。
最初のリンクのようにコピーサービスを使用して、Wikiページを作成および更新します。 2010年には、リストサービスを使用して更新できますが、追加はできません。 イメージングサービスを使用して、画像を画像ライブラリに自動的にアップロードします。
これは、「ms-wikilinks」を置き換える関数です。 wikiマークアップへ:
注:返されるマークアップの形式が正しくない場合、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の公開を考えています。Sharepointwikiの管理を改善したい人にとって非常に役立つと思うコードはそれほど多くありません。 WLWを使用すると、自動画像アップロード、より優れたHTML編集サポート、PreCode Snippetなどのプラグインのサポートが得られます。すごい!