I'm trying to retrieve a hierarchy of categories/keywords from the Core Service on Tridion 2013.
I want to either retrieve the whole tree in one request, i.e. pass in a Category ID and get its child keywords, and their child keywords and so forth;
Or be able to retrieve individual levels of the tree, i.e. pass in a Category ID and get its immediate child keywords. And then be able to pass in one of the child Keyword IDs and retrieve its immediate children.
I've tried using the following code:
var items = _client.GetList(categoryId, new KeywordsFilterData());
And:
var items = _client.GetList(keywordId, new ChildKeywordsFilterData());
But both methods simply return the whole tree as a flattened list. This wouldn't be a problem if the KeywordData.ParentKeywords
property wasn't always null on the returned items, as I could parse the results and build the tree myself.
It must be possible to do this, as the CME loads its tree one level at a time, and I was under the impression that in Tridion 2013 everything (except legacy backwards compatibility) uses the Core Service.
I'm currently stumped by this, so any help anyone can give would be much appreciated.
EDIT
Thanks for your help guys, I've ended up using the TaxonomiesOwlFilterData
option and parsing the XML, as I can get the whole tree in one hit, parse it and any keyword metadata and cache it for later use.
Here's my solution, with some bits snipped for brevity:
public CategoryItem GetHierarchy(string categoryId)
{
var tcmUri = new TcmUri(categoryId);
var filter = new TaxonomiesOwlFilterData
{
RootCategories = new[] {new LinkToCategoryData {IdRef = categoryId}}
};
var publicationId = "tcm:0-{0}-1".FormatWIth(tcmUri.PublicationId);
var xml = _client.GetListXml(publicationId, filter);
return Parse(publicationId, categoryId, xml);
}
public CategoryItem Parse(string publicationId, string categoryId, XElement xml)
{
XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
XNamespace rdfs = "http://www.w3.org/2000/01/rdf-schema#";
XNamespace tcmt = "http://www.tridion.com/ContentManager/5.2/Taxonomies#";
XNamespace tcmc = publicationId + "/Categories#";
var category = xml.Element(tcmt + "Taxonomy");
var result = new CategoryItem
{
Id = category.Attribute(rdf + "about").Value,
Title = category.Element(rdfs + "label").Value
};
foreach (var rootKeyword in category.Elements(tcmt + "rootKeyword"))
{
var id = rootKeyword.Attribute(rdf + "resource").Value;
var element = xml.Elements().First(e => e.Attribute(rdf + "about").Value == id);
var title = element.Element(rdfs + "label").Value;
var keyword = new KeywordItem {Id = id, Title = title};
ParseChildren(keyword, xml, element);
result.Keywords.Add(keyword);
}
return result;
}
public void ParseChildren(KeywordItem parent, XElement xml, XElement parentElement)
{
XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
XNamespace rdfs = "http://www.w3.org/2000/01/rdf-schema#";
XNamespace tcmt = "http://www.tridion.com/ContentManager/5.2/Taxonomies#";
foreach (var childKeyword in parentElement.Elements(tcmt + "childKeyword"))
{
var id = childKeyword.Attribute(rdf + "resource").Value;
var element = xml.Elements().First(e => e.Attribute(rdf + "about").Value == id);
var title = element.Element(rdfs + "label").Value;
var keyword = new KeywordItem {Id = id, Title = title};
ParseChildren(keyword, xml, element);
parent.Children.Add(keyword);
}
}