/// <summary>
        /// Get parent MoGlossItem and fill in any missing items between the parent and the top level.
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="node"></param>
        /// <returns>The MoGlossItem object which is or is to be the parent of this item.</returns>
        private IMoGlossItem GetMyParentGlossItem(FdoCache cache, XmlNode node)
        {
            ILangProject   lp = cache.LangProject;
            IMoMorphData   md = lp.MorphologicalDataOA;
            IMoGlossSystem gs = md.GlossSystemOA;

            System.Xml.XmlNode parent = node.ParentNode;
#if NUnitDebug
            Console.WriteLine("gmpgi: working on " + XmlUtils.GetAttributeValue(node, "id"));
#endif
            if (parent.Name != "item")
            {             // is a top level item; find it or add it
#if NUnitDebug
                Console.WriteLine("gmpgi: found top");
#endif
                MIoGlossItem giFound = gs.FindEmbeddedItem(XmlUtils.GetAttributeValue(node, "term"),
                                                           XmlUtils.GetAttributeValue(node, "abbrev"), false);
                if (giFound == null)
                {                 // not found; so add it
                    IMoGlossItem gi = new MoGlossItem();
                    gs.GlossesOC.Add(gi);
                    FillInGlossItemBasedOnXmlNode(gi, node, this);
#if NUnitDebug
                    Console.WriteLine("gmpgi, found top, made new, returning ", gi.Name.AnalysisDefaultWritingSystem);
#endif
                    return(gi);
                }
                else
                {                 //found, so return it
#if NUnitDebug
                    Console.WriteLine("gmpgi, found top, exists, returning ", giFound.Name.AnalysisDefaultWritingSystem);
#endif
                    return(giFound);
                }
            }
            else
            {              // not a top level item; get its parent and add it, if need be
#if NUnitDebug
                Console.WriteLine("gmpgi: calling parent of " + XmlUtils.GetAttributeValue(node, "id"));
#endif
                IMoGlossItem giParent = GetMyParentGlossItem(cache, parent);
                IMoGlossItem giFound  = giParent.FindEmbeddedItem(XmlUtils.GetAttributeValue(node, "term"),
                                                                  XmlUtils.GetAttributeValue(node, "abbrev"), false);
                if (giFound == null)
                {                 // not there, add it
#if NUnitDebug
                    Console.WriteLine("gmpgi: adding a node");
#endif
                    giFound = new MoGlossItem();
                    giParent.GlossItemsOS.Append(giFound);
                    FillInGlossItemBasedOnXmlNode(giFound, node, this);
                }
#if NUnitDebug
                Console.WriteLine("gmpgi, in middle, returning " + giFound.Name.AnalysisDefaultWritingSystem + " for node " + XmlUtils.GetAttributeValue(node, "id"));
#endif
                return(giFound);
            }
        }
        /// <summary>
        /// Fill in the attributes of a MoGlossItem object based on its corresponding XML node in the etic gloss list tree
        /// </summary>
        /// <param name="gi"></param>
        /// <param name="xn"></param>
        /// <param name="glbi"></param>
        private void FillInGlossItemBasedOnXmlNode(MoGlossItem gi, XmlNode xn, GlossListBoxItem glbi)
        {
            XmlNode attr = xn.Attributes.GetNamedItem("term");

            if (attr == null)
            {
                gi.Name.AnalysisDefaultWritingSystem = MGAStrings.ksUnknownTerm;
            }
            else
            {
                gi.Name.AnalysisDefaultWritingSystem = attr.Value;
            }
            attr = xn.Attributes.GetNamedItem("abbrev");
            if (attr == null)
            {
                gi.Abbreviation.AnalysisDefaultWritingSystem = MGAStrings.ksUnknownAbbreviation;
            }
            else
            {
                gi.Abbreviation.AnalysisDefaultWritingSystem = attr.Value;
            }
            attr = xn.Attributes.GetNamedItem("afterSeparator");
            if (attr == null)
            {
                gi.AfterSeparator = this.AfterSeparator;
            }
            else
            {
                gi.AfterSeparator = attr.Value;
            }
            attr = xn.Attributes.GetNamedItem("complexNameSeparator");
            if (attr == null)
            {
                gi.ComplexNameSeparator = this.ComplexNameSeparator;
            }
            else
            {
                gi.ComplexNameSeparator = attr.Value;
            }
            attr = xn.Attributes.GetNamedItem("complexNameFirst");
            if (attr == null)
            {
                gi.ComplexNameFirst = this.ComplexNameFirst;
            }
            else
            {
                gi.ComplexNameFirst = XmlUtils.GetBooleanAttributeValue(attr.Value);
            }
            attr = xn.Attributes.GetNamedItem("type");
            attr = xn.Attributes.GetNamedItem("status");
            if (attr == null)
            {
                gi.Status = true;
            }
            else
            {
                if (attr.Value == "visible")
                {
                    gi.Status = true;
                }
                else
                {
                    gi.Status = false;
                }
            }
            attr = xn.Attributes.GetNamedItem("type");
            if (attr == null)
            {
                gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.unknown;
            }
            else
            {
                switch (attr.Value)
                {
                case "complex":
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.complex;
                    break;

                case "deriv":
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.deriv;
                    break;

                case "feature":
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.feature;
                    break;

                case "fsType":
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.fsType;
                    break;

                case "group":
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.group;
                    break;

                case "value":
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.inflValue;
                    break;

                case "xref":
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.xref;
                    break;

                default:
                    gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.unknown;
                    break;
                }
            }
        }
		/// <summary>
		/// Fill in the attributes of a MoGlossItem object based on its corresponding XML node in the etic gloss list tree
		/// </summary>
		/// <param name="gi"></param>
		/// <param name="xn"></param>
		/// <param name="glbi"></param>
		private void FillInGlossItemBasedOnXmlNode(MoGlossItem gi, XmlNode xn, GlossListBoxItem glbi)
		{
			XmlNode attr = xn.Attributes.GetNamedItem("term");
			if (attr == null)
				gi.Name.AnalysisDefaultWritingSystem = MGAStrings.ksUnknownTerm;
			else
				gi.Name.AnalysisDefaultWritingSystem = attr.Value;
			attr = xn.Attributes.GetNamedItem("abbrev");
			if (attr == null)
				gi.Abbreviation.AnalysisDefaultWritingSystem = MGAStrings.ksUnknownAbbreviation;
			else
				gi.Abbreviation.AnalysisDefaultWritingSystem = attr.Value;
			attr = xn.Attributes.GetNamedItem("afterSeparator");
			if (attr == null)
				gi.AfterSeparator = this.AfterSeparator;
			else
				gi.AfterSeparator = attr.Value;
			attr = xn.Attributes.GetNamedItem("complexNameSeparator");
			if (attr == null)
				gi.ComplexNameSeparator = this.ComplexNameSeparator;
			else
				gi.ComplexNameSeparator= attr.Value;
			attr = xn.Attributes.GetNamedItem("complexNameFirst");
			if (attr == null)
				gi.ComplexNameFirst = this.ComplexNameFirst;
			else
				gi.ComplexNameFirst = XmlUtils.GetBooleanAttributeValue(attr.Value);
			attr = xn.Attributes.GetNamedItem("type");
			attr = xn.Attributes.GetNamedItem("status");
			if (attr == null)
				gi.Status = true;
			else
			{
				if (attr.Value == "visible")
					gi.Status = true;
				else
					gi.Status = false;
			}
			attr = xn.Attributes.GetNamedItem("type");
			if (attr == null)
				gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.unknown;
			else
			{
				switch(attr.Value)
				{
					case "complex":
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.complex;
						break;
					case "deriv":
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.deriv;
						break;
					case "feature":
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.feature;
						break;
					case "fsType":
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.fsType;
						break;
					case "group":
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.group;
						break;
					case "value":
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.inflValue;
						break;
					case "xref":
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.xref;
						break;
					default:
						gi.Type = (int)SIL.FieldWorks.FDO.Ling.MoGlossItem.ItemType.unknown;
						break;
				}
			}
		}
 public GlossListBoxItem(XmlNode node, string sAfterSeparator, string sComplexNameSeparator, bool fComplexNameFirst)
 {
     m_xmlNode = node;
     SetValues(node, sAfterSeparator, sComplexNameSeparator, fComplexNameFirst);
     m_glossItem = new MoGlossItem();
 }
		/// <summary>
		/// Get parent MoGlossItem and fill in any missing items between the parent and the top level.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="node"></param>
		/// <returns>The MoGlossItem object which is or is to be the parent of this item.</returns>
		private IMoGlossItem GetMyParentGlossItem(FdoCache cache, XmlNode node)
		{
			ILangProject lp=cache.LangProject;
			IMoMorphData md = lp.MorphologicalDataOA;
			IMoGlossSystem gs = md.GlossSystemOA;

			System.Xml.XmlNode parent = node.ParentNode;
#if NUnitDebug
			Console.WriteLine("gmpgi: working on " + XmlUtils.GetAttributeValue(node, "id"));
#endif
			if (parent.Name != "item")
			{ // is a top level item; find it or add it
#if NUnitDebug
				Console.WriteLine("gmpgi: found top");
#endif
				MIoGlossItem giFound = gs.FindEmbeddedItem(XmlUtils.GetAttributeValue(node, "term"),
					XmlUtils.GetAttributeValue(node, "abbrev"), false);
				if (giFound == null)
				{ // not found; so add it
					IMoGlossItem gi = new MoGlossItem();
					gs.GlossesOC.Add(gi);
					FillInGlossItemBasedOnXmlNode(gi, node, this);
#if NUnitDebug
					Console.WriteLine("gmpgi, found top, made new, returning ", gi.Name.AnalysisDefaultWritingSystem);
#endif
					return gi;
				}
				else
				{ //found, so return it
#if NUnitDebug
					Console.WriteLine("gmpgi, found top, exists, returning ", giFound.Name.AnalysisDefaultWritingSystem);
#endif
					return giFound;
				}
			}
			else
			{  // not a top level item; get its parent and add it, if need be
#if NUnitDebug
				Console.WriteLine("gmpgi: calling parent of " + XmlUtils.GetAttributeValue(node, "id"));
#endif
				IMoGlossItem giParent = GetMyParentGlossItem(cache, parent);
				IMoGlossItem giFound = giParent.FindEmbeddedItem(XmlUtils.GetAttributeValue(node, "term"),
					XmlUtils.GetAttributeValue(node, "abbrev"), false);
				if (giFound == null)
				{ // not there, add it
#if NUnitDebug
					Console.WriteLine("gmpgi: adding a node");
#endif
					giFound = new MoGlossItem();
					giParent.GlossItemsOS.Append(giFound);
					FillInGlossItemBasedOnXmlNode(giFound, node, this);
				}
#if NUnitDebug
				Console.WriteLine("gmpgi, in middle, returning " + giFound.Name.AnalysisDefaultWritingSystem + " for node " + XmlUtils.GetAttributeValue(node, "id"));
#endif
				return giFound;
			}
		}