3

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)?

| improve this question | | | | |
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.)

| improve this answer | | | | |
  • I just checked that the "xlink:href=tcm:x-y-z" is added automatically as well. I am doing it in 2013 sp1 – Saurabh Gangwar Jun 30 '15 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? – Alvin Reyes Jun 30 '15 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). – Alvin Reyes Jun 30 '15 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. – Peter Kjaer Jul 2 '15 at 5:55
3

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>
| improve this answer | | | | |
  • Excellent. We just need to make sure the text is a valid Keyword Title (for that Publication). – Alvin Reyes Jun 30 '15 at 14:40
  • Yeah correct, else it will result in a exception. – Saurabh Gangwar Jun 30 '15 at 14:41
2

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)
            {
                try
                {
                    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();
                        doc.LoadXml(xml.ComponentXML);

                        if (doc.DocumentElement != null && doc.DocumentElement.Attributes != null)
                        {
                            doc.DocumentElement.RemoveAttribute("xmlns");
                        }


                        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;
        }
| improve this answer | | | | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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