Перенос элементов списка с вложениями из SharePoint 2003 в существующий список в SharePoint 2007

StackOverflow https://stackoverflow.com/questions/826999

Вопрос

У меня есть элементы в списке на сайте SharePoint 2003, которые нужно добавить в существующий список на сайте 2007 года. Предметы имеют вложения.

Как это можно сделать с помощью PowerShell или C #?

Это было полезно?

Решение

В итоге я использовал программу C # в сочетании с веб-службами SharePoint для достижения этой цели. Я также использовал методы расширения (GetXElement, GetXmlNode) в блоге Эрика Уайта здесь для преобразования между XMLNodes и XElements, что упростило работу с XML из SharePoint.

Ниже приведен шаблон для большей части кода, необходимого для переноса данных списка, включая вложения, из одного списка SharePoint (2003 или 2007) в другой:

1) Этот код перемещает вложения после добавления нового элемента в целевой список.

// Adds attachments from a list item in one SharePoint server to a list item in another SharePoint server.
//   addResults is the return value from a lists.UpdateListItems call.
private void AddAttachments(XElement addResults, XElement listItem)
{
    XElement itemElements = _listsService2003.GetAttachmentCollection(_listNameGuid, GetListItemIDString(listItem)).GetXElement();

    XNamespace s = "http://schemas.microsoft.com/sharepoint/soap/";

    var items = from i in itemElements.Elements(s + "Attachment")
                select new { File = i.Value };

    WebClient Client = new WebClient();
    Client.Credentials = new NetworkCredential("user", "password", "domain");

    // Pull each attachment file from old site list and upload it to the new site list.
    foreach (var item in items)
    {

        byte[] data = Client.DownloadData(item.File);
        string fileName = Path.GetFileName(item.File);
        string id = GetID(addResults);
        _listsService2007.AddAttachment(_newListNameGuid, id, fileName, data);
    }
}

2) Код, который перебирает старый список SharePoint и заполняет новый.

    private void TransferListItems()
    {

        XElement listItems = _listsService2003.GetListItems(_listNameGuid, _viewNameGuid, null, null, "", null).GetXElement();

        XNamespace z = "#RowsetSchema";
        foreach (XElement listItem in listItems.Descendants(z + "row"))
        {
            AddNewListItem(listItem);
        }
    }

    private void AddNewListItem(XElement listItem)
    {
        // SharePoint XML for adding new list item.
        XElement newItem = new XElement("Batch",
            new XAttribute("OnError", "Return"),
            new XAttribute("ListVersion", "1"),
            new XElement("Method",
                new XAttribute("ID", "1"),
                new XAttribute("Cmd", "New")));

        // Populate fields from old list to new list mapping different field names as necessary.
        PopulateFields(newItem, listItem);

        XElement addResults = _listsService2007.UpdateListItems(_newListNameGuid, newItem.GetXmlNode()).GetXElement();

        // Address attachements.
        if (HasAttachments(listItem))
        {
            AddAttachments(addResults, listItem);
        }
    }

    private static bool HasAttachments(XElement listItem)
    {
        XAttribute attachments = listItem.Attribute("ows_Attachments");

        if (System.Convert.ToInt32(attachments.Value) != 0)
            return true;

        return false;
    }

3) Разный код поддержки для этого образца.

    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    using System.Xml.Linq;
    using System.Net;
    using System.IO;

    // This method uses an map List<FieldMap> created from an XML file to map fields in the
    // 2003 SharePoint list to the new 2007 SharePoint list.
    private object PopulateFields(XElement batchItem, XElement listItem)
    {
        foreach (FieldMap mapItem in FieldMaps)
        {
            if (listItem.Attribute(mapItem.OldField) != null)
            {
                batchItem.Element("Method").Add(new XElement("Field",
                    new XAttribute("Name", mapItem.NewField),
                        listItem.Attribute(mapItem.OldField).Value));
            }
        }

        return listItem;
    }

    private static string GetID(XElement elem)
    {
        XNamespace z = "#RowsetSchema";

        XElement temp = elem.Descendants(z + "row").First();

        return temp.Attribute("ows_ID").Value;
    }

    private static string GetListItemIDString(XElement listItem)
    {
        XAttribute field = listItem.Attribute("ows_ID");

        return field.Value;
    }

    private void SetupServices()
    {
        _listsService2003 = new SPLists2003.Lists();

        _listsService2003.Url = "http://oldsite/_vti_bin/Lists.asmx";
        _listsService2003.Credentials = new System.Net.NetworkCredential("username", "password", "domain");

        _listsService2007 = new SPLists2007.Lists();

        _listsService2007.Url = "http://newsite/_vti_bin/Lists.asmx";
        _listsService2007.Credentials = new System.Net.NetworkCredential("username", "password", "domain");

    }

    private string _listNameGuid = "SomeGuid";      // Unique ID for the old SharePoint List.
    private string _viewNameGuid = "SomeGuid";      // Unique ID for the old SharePoint View that has all the fields needed.
    private string _newListNameGuid = "SomeGuid";   // Unique ID for the new SharePoint List (target).

    private SPLists2003.Lists _listsService2003;    // WebService reference for the old SharePoint site (2003 or 2007 is fine).
    private SPLists2007.Lists _listsService2007;    // WebService reference for the new SharePoint site.

    private List<FieldMap> FieldMaps;   // Used to map the old list to the new list. Populated with a support function on startup.

    class FieldMap
    {
        public string OldField { get; set; }
        public string OldType { get; set; }
        public string NewField { get; set; }
        public string NewType { get; set; }
    }

Другие советы

Я бы, вероятно, попытался реализовать что-то с помощью веб-сервисов - я знаю, что в 2007 году URL-адреса вложений отображаются в атрибуте ows_Attachements, и как только вы это сделаете, вы можете выполнить довольно стандартную загрузку / выгрузку. Я давно ничего не делал с 2003 года, но я не думаю, что это новое поле.

Если у вас возникли проблемы с получением правильных данных с 2003 года, вы всегда можете перенести весь сайт на 2007 год, а затем извлечь нужные данные с помощью новейшего API.

Вы пытались сохранить список (" с содержимым ") в качестве шаблона, сохранить этот файл в шаблонах портала 2007, а затем создать новый список, используя этот " custom < !> Quot; шаблон? Это не сработает, если размер вложений и элементов превышает 10 МБ, и я не уверен на 100%, что это сработает в 2003 году & Gt; 2007. Это должно занять & Lt; 10 минут, так что стоит попробовать, если вы еще этого не сделали.

Мне нужно было создать этот проект: http://sourceforge.net/projects/splistcp для аналогичная задача, но чтобы сохранить измененное и созданное время и пользователя, мне пришлось использовать локальный API на месте назначения. Преимущество вашего подхода заключается в облегчении поддержки как 2003, так и 2007 года в качестве источника.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top