String Writer

my tech stuffs…

Posts Tagged ‘delete keywords

Delete keywords in Tridion

with 5 comments

As posted earlier, I completed the keyword deletion tool. I’ve tried both approaches (explained in my earlier post) to implement this keyword deletion. Finally I’ve decided to go with deleting keywords from bottom to top that’s 2nd approach.

How to call it

All you need is just to create class object with TCM Uri of a parent keyword whose child keywords are to be deleted and call its delete method.


//initialize the class with keyword TCM Uri value
TCMKeywords keywords = new TCMKeywords(ConfigurationManager.AppSettings["TCMURI"]);
//deletes keyword branch
keywords.Delete();

Here we don’t need to pass its publication TCM Uri since that can be retrieved from its keyword TCM Uri. I’ve given TCM Uri in my app.config file so that I can change it whenever I needed.

Call child keywords recursively

Tridion API does not provide direct method to get all child keywords in hierarchical order. But we can write a recursive call just like the way we do it for any other tree structure objects.


/// <summary>
/// Recursive method to navigate all keywords
/// </summary>
/// <param name="parentTCM">TCM Uri of parent keyword</param>
/// <param name="level">Hierarchy level of keyword</param>
private void NavigateKeywords(string parentTCM, int level)
{
   //gets all child keywords from given parent
   XmlNode keyNode = this.GetListChildKeywords(parentTCM);

   foreach (XmlNode key in keyNode.ChildNodes)
   {
      //loops through its next level
      NavigateKeywords(key.Attributes["ID"].Value, level + 1);

      //deletes keyword if it doesn't have any child
      this.DeleteKeyword((Keyword)this.GetObject(key.Attributes["ID"].Value), level);
   }
}

Obviously a keyword cannot be deleted if it is being used by other items. So all other associations should be removed before deleting it. That’s the reason DeleteKeyword(…) is being called after NavigateKeywords(…). That means if keyword (A) do not have any child, keyword (A) will be considered for deletion.

GetListChildKeywords(…) is a private method to retrieve all child keywords in Xml type of object.


/// <summary>
/// Gets all child keywords in xml object
/// </summary>
/// <param name="parentKeywordTCM">Parent <see cref="Keyword">Keyword</see></param>
/// <returns>Child keywords in <see cref="XmlNode">XmlNode</see> object</returns>
private XmlNode GetListChildKeywords(string parentKeywordTCM)
{
   //gets all child keywords
   string keyXML = ((Keyword)this.GetObject(parentKeywordTCM)).GetListChildKeywords(EnumKeywordSortType.SortTypeTitle,ListColumnFilter.XMLListID, (ListRowFilter)TObj.CreateListRowFilter());

   //returns output as xml object
   return this.PopulateXMLNode(keyXML);
}

ListColumnFilter –Other attributes also can be retrieved other than ListID. But we need only list id for this tool.

ListRowFilter – Here we are getting all rows so we are not setting any filter conditions. This can be set based upon our requirements. Let’s look at this code sample if filtering condition is needed.

Deleting a keyword

The keywords in Tridion can be used in following ways.

  1. Classified with other building blocks
  2. Used in component or metadata fields
  3. Localized in its child publications

A keyword should be released from the all above associations before deleting it.


//releases keyword from its all dependencies
if (this.ReleaseKeyword(keyword, keyLevel))
{
   //deletes keyword
   keyword.Delete();

   Console.WriteLine("{0}{1} deleted...", keyLevel, keyword.Title);
}

ReleaseKeyword(…) is a private method to unclassify and unlocalize the keywords.


/// <summary>
/// Releases the keyword from its dependencies
/// </summary>
/// <param name="keyword"><see cref="Keyword">Keyword</see> object to be released</param>
/// <param name="keyLevel">Hirarchical level of a keyword</param>
/// <returns>Returns <see cref="bool">bool</see> if released or not</returns>
private bool ReleaseKeyword(Keyword keyword, string keyLevel)
{
   //default status
   bool released = false;

   //unclassifies the keyword
   released = this.Unclassify(keyword, keyLevel);

   //unlocalizes the keyword from its all child publications
   if (released)
      released = UnLocalize(keyword, keyLevel);

   //returns released status
   return released;
}

Unclassifying keywords

In Tridion, the content or building blocks are generally classified with keywords.

Classified means that it can be in either way,

1) Keyword can be used in any of field values in metadata or components.

2) An Tridion object is classified against keyword.

These two associations should be removed as part of unclassification.

For example, if a keyword is classified with 10 Tridion objects, we need to retrieve those 10 objects and call them separately its own unclassify method.

The problem here is a keyword in one publication would be derived into its child publications. In child publications, these keywords might have classified with other objects. Hence the appropriate keyword from the same publication should be retrieved to unclassify it.


/// <summary>
/// Unclassifies the keyword
/// </summary>
/// <param name="keyword"><see cref="Keyword">Keyword</see> object to be released</param>
/// <param name="keyLevel">Hierarchical level of a keyword</param>
/// <returns>Returns <see cref="bool">bool</see> if unclassified or not</returns>
private bool Unclassify(Keyword keyword, string keyLevel)
{
   try
   {
      //gets all using items from all publications
      string classifiedItemsXML = keyword.Info.GetListUsingItems(ListColumnFilter.XMLListDefault,(ListRowFilter)TObj.CreateListRowFilter());

      //converts xml string to xml object
      XmlNode xmlDoc = this.PopulateXMLNode(classifiedItemsXML);

      string tcmChild = null;
      //default publication is set to current publication

      string pubURI = this.PublicationURI;

      foreach (XmlNode child in xmlDoc.ChildNodes)
      {
         //gets keyword tcm uri
         tcmChild = child.Attributes["ID"].Value;

         //checks if publication of child object is same as its parent keyword
         if (!this.IsSamePublication(tcmChild))
         {
            //gets publication tcm uri from given tcm uri
            pubURI = GeneratePublicationTCM(tcmChild);

            //gets the same keyword object from its child object publication
            keyword = (Keyword)this.GetObject(pubURI, ReplacePublicationID(keyword.ID, this.GetPublicationID(tcmChild)));
         }

         //checks its child object type and unclassify
         switch (child.Attributes["Type"].Value)
         {
            case "2":
               ((Folder)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "4":
               ((StructureGroup)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "16":
               ((Component)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "32":
               ((ComponentTemplate)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "64":
               ((Tridion.ContentManager.Interop.TDS.Page)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "128":
               ((PageTemplate)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
         }
      }

      //display the output if any of child is unclassified
      if (xmlDoc.ChildNodes.Count != 0)
         Console.WriteLine("{0}{1} unclassified...", keyLevel, keyword.Title);

      return true;
   }
   catch (Exception ex)
   {
      Console.WriteLine("Unclassification Failed!");
      Console.WriteLine(ex.Message);
      return false;
   }
}

GetListUsingItems(…) is the common method in all Tridion objects to retrieve its associated items. In this case, this method will return all the objects wherever the keyword is being used.

Here important note is that if a keyword is unclassified, the parent object will not get republished automatically. If you need to republish the parent object while keyword unclassification, you need to set some code and trigger workflow events.

Unlocalizing keywords

Unlocalizing is not a straight forward approach unlike unclassification. There is no method to write all localized keywords.

If there is a keyword in publication, the same keyword has to be checked in its all child publications whether it is localized in child publication level.


/// <summary>
/// Unlocalizes keyword
/// </summary>
/// <param name="keyword"><see cref="Keyword">Keyword</see> object to be released</param>
/// <param name="keyLevel">Hirarchical level of a keyword</param>
/// <returns>Returns <see cref="bool">bool</see> if unlozalized or not</returns>
private bool UnLocalize(Keyword keyword, string keyLevel)
{
   try
   {
      //gets all child publications
      List<string> childPublications = this.GetChildPublications(keyword.Publication.ID);

      foreach (string cPub in childPublications)
      {
         //gets the keyword in each child publication
         Keyword childKey = (Keyword)this.GetObject(cPub, ReplacePublicationID(keyword.ID, this.SplitURI(cPub, 1)));

         //checks if it is localized
         if (childKey.Info.IsLocalized)
         {
             childKey.UnLocalize();
             Console.WriteLine("{0}{1} unlocalized from {2}...", keyLevel, childKey.Title, childKey.Publication.Title);
         }
      }
      return true;
   }
   catch (Exception ex)
   {
      Console.WriteLine(ex.Message);
      return false;
   }
}

GetChildPublications(…) posted earlier (Get Child publications in Tridion)

Output

I created these keywords for my testing. All keywords are classified against a component and two of them are localized in child publications.

clip_image001[1]

I ran the tool and got the following output.

clip_image002[1]

The source code can be copied from this link.

Written by visvabalaji

April 12, 2011 at 10:53 pm

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: