Сервис Tridion Core — работа с иерархической таксономией

Я использую Tridion Core Service (Tridion 2011 SP1) для получения списка ключевых слов для данного идентификатора категории.

CoreService2010Client client = new CoreService2010Client();   
XElement xmlCategoryKeywords = client.GetListXml(category.Id, 
                                                 new KeywordsFilterData());

Это возвращает то, что кажется плоской структурой XML, представляющей нашу таксономию, которая имеет 4 уровня в глубину.

В документации подробно описан подход к работе с этим:

var categoryKeywords = xmlCategoryKeywords.Elements().Select(element => 
    element.Attribute("ID").Value).Select(id => (KeywordData)client.Read(id, null)
);
foreach (KeywordData keyword in categoryKeywords)
{
    Console.WriteLine("\t Keyword ID={0}, Title={1}", keyword.Id, keyword.Title);
}

Однако это будет перечислять только каждое ключевое слово. Объект KeywordData содержит свойство ParentKeywords, чтобы можно было построить иерархию в памяти.

Можно ли получить XML из Core Service с иерархической структурой? Или более простой способ работы с этими данными?


person Dave Houlker    schedule 02.03.2012    source источник


Ответы (3)


Один из способов — использовать TaxonomiesOwlFilterData:

string publicationId = "tcm:0-3-1";
var filter = new TaxonomiesOwlFilterData();
filter.RootCategories = new[] {new LinkToCategoryData{ IdRef = "tcm:3-158-512"},};
var list = ClientAdmin.GetListXml(publicationId, filter);

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

XNamespace tcmc = publicationId + "/Categories#";
XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
XNamespace tcmt = "http://www.tridion.com/ContentManager/5.2/Taxonomies#";

var taxonomyTree = new Dictionary<string, List<string>>();
var keywordNodes = list.Descendants(tcmc + "cat");
foreach (var keywordNode in keywordNodes)
{
   var parents = new List<string>();
   var parentNodes = keywordNode.Descendants(tcmt + "parentKeyword");
   if (parentNodes.Count() > 0)
   {
      foreach (var parentNode in parentNodes)
      {
         parents.Add(parentNode.Attribute(rdf + "resource").Value);
      }
    }
taxonomyTree.Add(keywordNode.Attribute(rdf + "about").Value, parents);
}

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

person Andrey Marchuk    schedule 02.03.2012

Вы можете обрабатывать каждую ветвь, уровень за уровнем. Вот какой код, с которым я играл, делает это:

CoreService2010Client client = new CoreService2010Client("basicHttp_2010");

KeywordsFilterData keywordsDataFilter = new KeywordsFilterData()
{
    BaseColumns = ListBaseColumns.IdAndTitle,
    IsRoot = true
};

UsingItemsFilterData usingItemsFilter = new UsingItemsFilterData()
{
    BaseColumns = ListBaseColumns.IdAndTitle,
    ItemTypes = new[] { ItemType.Keyword },
    InRepository = new LinkToRepositoryData() { IdRef = "tcm:0-1-1" }
};

XElement parents = client.GetListXml("tcm:1-272-512", keywordsDataFilter);

foreach (XElement parent in parents.Descendants())
{
    // Do something with the parent (top level) KW

    XElement children = client.GetListXml(parent.Attribute("ID").Value, usingItemsFilter);

    foreach (XElement child in children.Descendants())
    {
        // Do something with the child KW
    }
}

В прошлом я обнаружил, что обработка плоского списка в иерархию (в моем случае список всех SG в публикации) создавала огромные накладные расходы по сравнению с обработкой ветки за раз. Конечно, я должен предостеречь, сказав, что я пробовал это со старой (ранней 5.x) версией Tridion, так что с тех пор ситуация могла улучшиться.

person Jeremy Grand-Scrutton    schedule 02.03.2012
comment
Ваш алгоритм также пометит связанные ключевые слова как дочерние ключевые слова. Вы должны использовать ChildKeywordsFilterData вместо UsingItemsFilterData. Как вы справляетесь с ключевыми словами, у которых есть несколько родителей? - person Andrey Marchuk; 02.03.2012

Tridion 2011 SP1 поставляется с новой конечной точкой CoreService. CoreService 2011. Рекомендуется использовать последнюю конечную точку. В последней конечной точке есть новые функционалисты, а также исправлены ошибки. В SP1 также есть клиентский прокси-сервер coreservice по умолчанию, который вы можете использовать непосредственно в своем коде.

person Bappi    schedule 03.04.2012