I see how read options let you choose how to choose how to read fields in a Component's XML: How to Get Keyword from Metadata or Item XML Using Core Service.

I'm having a hard time finding an example for saving a Component over the Core Service with Keywords. Do we use text or tcm-ids for Keywords (in text fields set to a Category)?


3 Answers 3


You use the TCM URI of the Keyword and you set it in an xlink:href attribute.

(The xlink:type and xlink:title attributes are optional and will be set automatically for you if you don't include them)

For example:

<SeeAlso xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="tcm:1-261"></SeeAlso>

Just like with other fields, this is inside of the XML stored in the Content property. How you create the XML is up to you, but I recommend using LINQ to XML (XDocument, XElement, etc.)

  • I just checked that the "xlink:href=tcm:x-y-z" is added automatically as well. I am doing it in 2013 sp1 Jun 30, 2015 at 16:04
  • Okay, so it's either text or TCM URI? Does the text inside the text node (e.g. Value in <SeeAlso>Value</SeeAlso>) count? Jun 30, 2015 at 16:52
  • And good tip on LINQ--we had a minor issue with using the right namespace for embedded fields with plain old XMLDocument (it should be the same as the Schema, oops). Jun 30, 2015 at 16:58
  • 1
    I actually didn't know that it also can look it up by the title. Very handy. So you can choose whether you want to refer to the Keyword by its ID or its title. Jul 2, 2015 at 5:55

So assuming you are having Component Xml prepared to be saved using Core Service. You would be doing something like below:

var component = client.GetDefaultData(ItemType.Component, containerId) as ComponentData;

                component.Title = title;
                component.Schema = new LinkToSchemaData { IdRef = schemaId };
                component.Content = contentXml;
client.Create(component, DefaultReadOptions)

In contentXml there will be the xml elements for the Text Fields using Keywords. And those are nothing but Text Fields in Tridion.

So if you set the inner text for those elements to the Keyword Title, the Components should be saved. I have run this code in Tridion 2011.

So as Peter mentioned in his answer, if you set somthing like this

<myKeywordField>keyword Title</myKeywordField>

Tridion will convert it as below according to the schema by setting the additional attributes.

<myKeywordField xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:13-366-1024" xlink:title="keyword Title">keyword Title</myKeywordField>
  • Excellent. We just need to make sure the text is a valid Keyword Title (for that Publication). Jun 30, 2015 at 14:40
  • Yeah correct, else it will result in a exception. Jun 30, 2015 at 14:41

I have written the below code for Localizing and Updating a list of Components in a specific publication; this may help in getting some idea of handling the Keywords - So if a Keyword does not exists, it will create it through core service before creating the component and so there is no exception: (This code is for update but can provide help in getting startup code for handling Keyword scenario)

public List<string> LocalizeAndUpdateComponent(List<ComponentXMLs> components, string targetPubID)
            List<string> successList = new List<string>();

            foreach (ComponentXMLs xml in components)
                    string tcmURI = xml.TCMURI;
                    TcmUri oldURI = new TcmUri(tcmURI);
                    ItemType type = oldURI.ItemType;
                    if (type == ItemType.Component)
                        string oldPubURI = oldURI.ContextRepositoryId.ToString();
                        if (!string.IsNullOrEmpty(tcmURI))
                            tcmURI = tcmURI.Substring(tcmURI.IndexOf('-'));

                        string localizedURI = string.Concat("tcm:", targetPubID, tcmURI);

                        ComponentData component = (ComponentData)client.Read(localizedURI, new ReadOptions());

                        XmlDocument doc = new XmlDocument();

                        if (doc.DocumentElement != null && doc.DocumentElement.Attributes != null)

                        XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
                        ns.AddNamespace("tcm", "http://www.tridion.com/ContentManager/5.0");
                        ns.AddNamespace("xlink", "http://www.w3.org/1999/xlink");
                        ns.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");
                        ns.AddNamespace("xmlns: tcmi", "http://www.tridion.com/ContentManager/5.0/Instance");
                        SchemaData schemaData = (SchemaData)client.Read(component.Schema.IdRef, new ReadOptions());
                        Dictionary<string, string> keywordFields = GetKeywordFields(component.Schema.IdRef, targetPubID);
                        foreach (KeyValuePair<string, string> keyValue in keywordFields)
                            var keywords = client.GetList(keyValue.Key, new KeywordsFilterData());

                            foreach (KeywordData keyword in keywords)
                                XmlNodeList nodes = doc.SelectNodes(string.Concat(schemaData.RootElementName, "/", keyValue.Value), ns);
                                keyword.Title = nodes != null && nodes.Count > 0 ? nodes[0].InnerText : keyword.Title;

                                if (keyword.BluePrintInfo.IsLocalized != null && keyword.BluePrintInfo.IsLocalized == false)
                                    client.Localize(keyword.Id, new ReadOptions());

                                if (!keyword.LockInfo.LockType.Value.HasFlag(LockType.CheckedOut))
                                    client.CheckOut(keyword.Id, true, new ReadOptions());
                                client.Save(keyword, new ReadOptions());
                                client.CheckIn(keyword.Id, new ReadOptions());

                        if (component.BluePrintInfo.IsLocalized != null && component.BluePrintInfo.IsLocalized == false)
                            client.Localize(localizedURI, new ReadOptions());

                        component.Content = xml.ComponentXML.Replace("tcm:" + oldPubURI, "tcm:" + targetPubID);

                        if (!component.LockInfo.LockType.Value.HasFlag(LockType.CheckedOut))
                            client.CheckOut(localizedURI, true, new ReadOptions());

                        client.Save(component, new ReadOptions());

                        client.CheckIn(localizedURI, new ReadOptions());
                        successList.Add(localizedURI + " - Localized Successfully");
                catch (Exception ex)
                    successList.Add(xml.TCMURI + " - Error in Localizing");

            return successList;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.