/// <summary>
        /// Find parent nearest pos tagging POS.
        /// </summary>
        /// <param name="parentPosStack">Parent pos stack, record all parent pos.</param>
        /// <param name="attributeValue">Current attribute value.</param>
        /// <param name="pos">Pos to be found pos tagging pos.</param>
        /// <returns>Nearst parent pos tagging POS.</returns>
        private static string FindPosTaggingPos(Stack<AttributeValue> parentPosStack,
            AttributeValue attributeValue, string pos)
        {
            string posTaggingPos = string.Empty;
            parentPosStack.Push(attributeValue);

            if (attributeValue.Name.Equals(pos, StringComparison.Ordinal))
            {
                foreach (AttributeValue value in parentPosStack)
                {
                    if (value.PosTagging)
                    {
                        posTaggingPos = value.Name;
                        break;
                    }
                }
            }
            else
            {
                if (attributeValue.Categories != null)
                {
                    foreach (AttributeCategory category in attributeValue.Categories)
                    {
                        if (category.Values != null)
                        {
                            foreach (AttributeValue value in category.Values)
                            {
                                posTaggingPos = FindPosTaggingPos(parentPosStack, value, pos);
                                if (!string.IsNullOrEmpty(posTaggingPos))
                                {
                                    break;
                                }
                            }
                        }

                        if (!string.IsNullOrEmpty(posTaggingPos))
                        {
                            break;
                        }
                    }
                }
            }

            parentPosStack.Pop();

            return posTaggingPos;
        }
        /// <summary>
        /// Load category from xml node of category.
        /// </summary>
        /// <param name="categoryNode">Xml category node.</param>
        /// <returns>Attribute category.</returns>
        private AttributeCategory LoadXmlCategoryNode(XmlNode categoryNode)
        {
            AttributeCategory category = null;
            if (categoryNode.Name.Equals("Category"))
            {
                category = new AttributeCategory();
                Debug.Assert(categoryNode.Attributes["name"] != null);
                category.Name = categoryNode.Attributes["name"].InnerText.Trim();
                Debug.Assert(categoryNode.Attributes["ID"] != null);
                category.Id = int.Parse(categoryNode.Attributes["ID"].InnerText.Trim(), 
                    NumberFormatInfo.InvariantInfo);
                
                // Permit category load mean and invStdDev
                if (categoryNode.Attributes["Mean"] != null)
                {
                    category.Mean = float.Parse(categoryNode.Attributes["Mean"].InnerText.Trim(),
                         NumberFormatInfo.InvariantInfo);
                }
                else
                {
                    category.Mean = 0.0f;
                }

                if (categoryNode.Attributes["InvStdDev"] != null)
                {
                    category.InvStdDev = float.Parse(categoryNode.Attributes["InvStdDev"].InnerText.Trim(),
                       NumberFormatInfo.InvariantInfo);
                }
                else
                {
                    category.InvStdDev = 1.0f;
                }

                // Permit category dosen't have child
                if (categoryNode.HasChildNodes)
                {
                    foreach (XmlNode valueNode in categoryNode.ChildNodes)
                    {
                        if (valueNode.NodeType == XmlNodeType.Comment)
                        {
                            continue;
                        }

                        Debug.Assert(valueNode.Name.Equals("Value"));
                        if (valueNode.Name.Equals("Value"))
                        {
                            AttributeValue value = new AttributeValue();
                            Debug.Assert(valueNode.Attributes["name"] != null);
                            value.Name = valueNode.Attributes["name"].InnerText.Trim();
                            Debug.Assert(valueNode.Attributes["ID"] != null);
                            value.Id = int.Parse(valueNode.Attributes["ID"].InnerText.Trim(),
                                NumberFormatInfo.InvariantInfo);
                            if (valueNode.Attributes["posTagging"] != null)
                            {
                                value.PosTagging = bool.Parse(valueNode.Attributes["posTagging"].InnerText.Trim());
                            }

                            if (valueNode.HasChildNodes)
                            {
                                value.UpdateCategories(new Collection<AttributeCategory>());
                                foreach (XmlNode subCategoryNode in valueNode.ChildNodes)
                                {
                                    AttributeCategory subCategory = LoadXmlCategoryNode(subCategoryNode);
                                    value.Categories.Add(subCategory);
                                }
                            }

                            category.Values.Add(value);
                        }
                    }
                }
            }

            return category;
        }