...

понедельник, 23 сентября 2013 г.

[Из песочницы] Загрузка данных в списки Sharepoint

При разработке SharePoint-решений часто стоит задача, помимо автоматического разворачивания структуры сайта (поля, типы контента, списки), также и наполнять его базовым контентом. Это могут быть, в основном, списки со справочной информацией. Но, помимо этого, может возникунть потребность наполнить их какими-то тестовыми данными, чтобы провести тестирование решения, в том числе и нагрузочного.

Есть способ наполнить списки данными, указывая их в XML файле к ListInstance. Но такой подход менее удобен, чем рассматриваемый в статье. ListDefinitions не всегда практично использовать для создания списков, кроме того может возникнуть потребность наполнить списки, которые уже существуют на сайте, а не разворачиваются из решения.


Итак, идея заключается в следующей логике:



создание таблиц с данными в Excel,

экспорт данных из Excel в XML,

добавление XML файлов в проект Visual Studio,

парсинг XML содержимого файлов и добавление данных в списки в ресивере фичи на активацию.

Использовать Excel довольно-таки удобно. Во-первых, данные там легко наполнять; можно создавать копии разных строк, просто протянув их мышкой; можно писать разные формулы, чтобы придать значениям рандомности в целях тестирования и т.д. И самое главное — именно в таком виде справочную информацию обычно присылает заказчик, то есть подготоить информацию по вашему запросу в Excel ему будет намного проще.


Последовательность действий:


1. Создайте в Excel-книге на отдельном листе таблицу с данными.


2. Создайте файл .xsd, который будет представлять схему данных, в таком формате:


<?xml version=«1.0» encoding=«UTF-8»?>

<xs:schema xmlns:xs=«www.w3.org/2001/XMLSchema»>

<xs:element name=«Currencies»>

<xs:complexType>

<xs:sequence>

<xs:element ref=«Currency» minOccurs=«0» maxOccurs=«unbounded»/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name=«Currency»>

<xs:complexType>

<xs:sequence>

<xs:element name=«Title» type=«xs:string»/>

<xs:element name=«Currency_IsNational» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>


Для удобства называйте корневой элемент так, как называется ваш список на сайте (или как основная часть его адреса). Я называл этот элемент Currencies. При парсинге XML можно будет сразу использовать это название для доступа к нужному списку.


Название полей указывайте в соответствии с InternalName у полей в нужном списке (в примере выше это Title и Currency_IsNational).


Также не смущайтесь, что тип значений стоит «xs:string». При парсинге XML вы все равно будете получать стринговые значения, которые при записи в объект SPListItem сами будут сконвертированы в нужный тип.


Если же вам надо использовать более сложные типы, вроде User, то указывайте в Excel-таблице, к примеру, login name, а в коде выполняйте дополнительную конвертацию в SPFieldUserValue. Далее это будет продемонстрировано.


3. Активируйте вкладку «Разработчик» в экселе.


4. На этой вкладке нажмите кнопку «Источник»:


5. В появившейся панеле нажмите кнопку «Карты XML»:


6. Нажмите кнопку «Добавить» и добавьте созданный ранее файлик .xsd:


7. После добавления схемы выделите заголовок таблицы в экселе и нажмите в панеле справа на дереве данных «Сопоставить элемент»:


Таким образом вы сопоставите вашей таблице схему данных. Теперь её можно экспортировать в XML.


8. Нажмите «Экспорт» и сохраните файл .xml:


Экспортированный файл будет выглядеть примерно так:


9.Проделайте описанные выше операции для всех таблиц, которые вы собираетесь загрузить на сайт.


10. Создайте Module в вашем проекте Visual Studio и добавьте в него все .xml фалы с данными, созданными таким образом. Назовите его к примеру InitialData.


Не забудьте включить модуль в фичу.


11. При активации фичи на сайте будет создаваться папка с именем InitialData, куда будут добавлены .xml файлы.


12. Далее в ресивере активации фичи добавьте логику по парсингу этих xml файлов и создании айтемов в нужных списках.


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


Метод ниже проходит по всем xml файлам в папке InitialData и вызывает метод ImportToSPList для каждого.


public void Import()

{

// _siteUrl — адрес сайтовой коллекции

using (SPSite site = new SPSite(_siteUrl))

{

SPWeb web = site.RootWeb;

// _initialDataFolderName — название Модуля (папки, которую он создает)

SPFolder initialDataFolder = web.RootFolder.SubFolders[_initialDataFolderName];


foreach (SPFile file in initialDataFolder.Files)

{

if (file.Name.EndsWith(".xml", StringComparison.CurrentCultureIgnoreCase))

{

using (MemoryStream inStream = new MemoryStream(file.OpenBinary()))

{

using (XmlTextReader reader = new XmlTextReader(inStream))

{

XmlDocument xd = new XmlDocument();

xd.Load(reader);


ImportToSPList(web, xd);

}

}

}

}

}

}


В методе ImportToSPList определяется список на основании названия корневого элемента из xml, как я писал выше. Далее для каждого вложенного элемента, который, по сути, преобразовывается в SPListItem, идёт обход по их полям и запись значений в поля SPListItem’а.


private void ImportToSPList(SPWeb web, XmlDocument xd)

{

XmlElement root = xd.DocumentElement;

// получаем вн. название списка из названия корневого элемента

string rootName = root.LocalName;

string listUrl = String.Format(«Lists/{0}/AllItems.aspx», rootName);

SPList list = web.GetListFromUrl(listUrl);


foreach (XmlNode item in root.ChildNodes)

{

SPListItem spListItem = list.AddItem();

// обходим все поля

foreach (XmlNode field in item.ChildNodes)

{

// ищем специальное правило для этого списка и поля

DataImportSpecialRule specialRule =

_diSpecialRules.FirstOrDefault(x => x.ListUrl == listUrl && x.FieldName == field.LocalName);

if (specialRule == null)

{

// специального правила нет, поэтому записываем стринговое значение

spListItem[field.LocalName] = field.InnerText;

}

else

{

// записываем значение нужного типа через метод-конвертер

spListItem[field.LocalName] = specialRule.Converter(web, field.InnerText);

}

}

// сохраняем айтем

spListItem.Update();

}

}


Также обратите внимание на вспомогательный класс DataImportSpecialRule, который нужен для конвертации стринговых значений из xml в более сложный тип, если это требуется.


Вот сам класс DataImportSpecialRule, который хранит в себе адрес списка, название поля и функцию для конвертации:


public delegate object GetTypedValue(SPWeb web, string value);


class DataImportSpecialRule

{

public string ListUrl { get; set; }

public string FieldName { get; set; }

public GetTypedValue Converter { get; set; }

}

Функция имеет сигнатуру, описанную в делегате GetTypedValue. На вход она принимает SPWeb и стринговое значение, а возвращает объект, который должен быть записан в поле SPListItem’а.


Изначально вы можете описать все правила, которые должны быть применены ко всем вашим справочникам, так, как показано в примере:


_diSpecialRules = new List()

{

new DataImportSpecialRule()

{

ListUrl = «Lists/BusinessBlocks/AllItems.aspx»,

FieldName = «BusinessBlock_Group»,

Converter = (SPWeb web, string value) =>

{

SPGroup group = web.SiteGroups[value];

return new SPFieldUserValue(web, group.ID, group.Name);

}

}

// тут добавляются другие правила

};


Как вы видите, в данном правиле происходит описание того, как значение из xml файла, содержащее только название группы, будет записано в поле SPListItem корректным образом.


Для наглядности вот еще один пример конвертера. Он выдаёт значения для поля с множественным выбором. При этом ожидается, что в эксель-таблице такие значения будут записаны через точку с запятой.


private SPFieldMultiChoiceValue MultiChoiceConverter(SPWeb web, string value)

{

SPFieldMultiChoiceValue fValue = new SPFieldMultiChoiceValue();

foreach (string choice in value.Split(';')) fValue.Add(choice.Trim());

return fValue;

}


Вы можете изменить разделитель, дописать другие правила. В статье приводится лишь концепция и примеры, как это можно легко сделать.


Вывод:


Таким образом, у вас будет эксель-книга, содержащая таблицы с данными. В любой момент, как только эти данные будут изменены или актуализированы, вы несколькими кликами мышки экспорируете таблицу в xml файл, закидываете в проект, и еще одним кликом мышки передеплоиваете решение.

Рутинная работа сведена к минимуму и наполнение справочников происходит автоматически по отлаженной схеме.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий