/// <summary>
        /// Функция запускает чтение файла и записывает в this.Storage
		/// </summary>
		public void Read()
		{
			bool cont = false;
			this.CurNode = this.Storage;
            //Читаем word-документ
			//Читаем заголовок и префикс 
			ReadMainTag(CurNode);
			//если XMLNS = null  то ошибка...

			//read 
			while(tr.Read())
			{
				//Если это теги word-a (те которые мы сами расставили)
				if ( tr.Name.Length > XMLNS.Length)
				{

					if (this.XMLNS == tr.Name.Substring(0,XMLNS.Length))
					{
						//Если начало, то добавляем child
						if (tr.NodeType == XmlNodeType.Element)
						{
							CurNode = this.CurNode.AddChild(tr.Name.Substring(XMLNS.Length +1));
							bool isEnd = tr.IsEmptyElement;

							//Далее должны пробежать по атрибутам потомка...
							//ДОДЕЛАТЬ!!!!
							if (tr.AttributeCount > 0)
							{
                            
								tr.MoveToFirstAttribute();
								while (true)
								{
									//пробегаем по всем атрибутам
									CurNode.AddAttribute(tr.Name, tr.Value);
									if (!tr.MoveToNextAttribute())
										break;
								}
							}
							if (isEnd)
							{
								CurNode = CurNode.GetParent();
							}
						}
						//Если конец текущего эл-та, то возвращяем потомка
						else if (tr.NodeType == XmlNodeType.EndElement)
						{
							this.CurNode =  CurNode.GetParent();
						}
					}
					else
					{
						if (tr.Name.IndexOf("schemaLibrary") != -1)
						{
							cont = !cont;
							continue;
						}
                        if (cont)
							continue;
                        //XmlTextReader n = tr;
						bool isEmpty = tr.IsEmptyElement;
						string name = tr.Name;
						XmlNodeType type = tr.NodeType;
						this.CurNode.AddXmlNode(tr.Name, tr.NodeType, tr.Value);

						if (tr.AttributeCount > 0)
						{
							tr.MoveToFirstAttribute();
							while (true)
							{
								//пробегаем по всем атрибутам
								CurNode.listXml.Add(new XmlNodeValue(tr.Name, XmlNodeType.Attribute, tr.Value));
								if (!tr.MoveToNextAttribute())
									break;
							}
						}

						if (isEmpty && type == XmlNodeType.Element)
						{
                            this.CurNode.AddXmlNode(name, XmlNodeType.EndElement,"");
						}
					}

				}
				else
				{
					if (tr.Name.IndexOf("schemaLibrary") != -1)
					{
						cont = !cont;
						continue;
					}
					if (cont)
						continue;
					//XmlTextReader n = tr;
					bool isEmpty = tr.IsEmptyElement;
					string name = tr.Name;
					XmlNodeType type = tr.NodeType;
					this.CurNode.AddXmlNode(tr.Name, tr.NodeType, tr.Value);
					if (tr.AttributeCount > 0)
					{
                            
						tr.MoveToFirstAttribute();
						while (true)
						{
							//пробегаем по всем атрибутам
							//CurNode.AddAttribute(tr.Name, tr.Value);
							CurNode.listXml.Add(new XmlNodeValue(tr.Name, XmlNodeType.Attribute, tr.Value));
							if (!tr.MoveToNextAttribute())
								break;
						}
					}
					if (isEmpty && type == XmlNodeType.Element)
					{
						this.CurNode.AddXmlNode(name, XmlNodeType.EndElement,"");
					}
				}
			}
		}
        /// <summary>
        /// Пишет поддерево <see cref="Write(Node,bool,Parametrs)"/>
        /// </summary>
        /// <param name="node">Поддерево</param>
        /// <param name="isSingle">Single или Array</param>
		private void Write(Node node, bool isSingle)
		{
			Write(node, isSingle, null);
		}
        /// <summary>
        /// Пишет поддерево
        /// </summary>
        /// <param name="node"></param>
		private void WriteWord(Node node)
		{
			//tw.WriteStartElement(node.)
			for (int i=0; i<node.list.Count; i++)
			{
                Child ch = (Child) node.list[i];
				tw.WriteStartElement(ch.value);
                //Пишем атрибуты
				for (int j=0; j<ch.child.att.Count; j++)
				{
                    XmlNodeValue val = (XmlNodeValue) ch.child.att[j];
					tw.WriteAttributeString(val.name, val.value);
				}
				//Далее пишем для child
                WriteWord(ch.child);
				tw.WriteEndElement();
			}
		}
        /// <summary>
        /// Пишет текущий узел
        /// </summary>
        /// <param name="node">Узел</param>
        /// <param name="isSingle">Single или Array</param>
        /// <param name="parent">Параметры</param>
		private void Write(Node node, bool isSingle, Parametrs parent)
		{
			int id = 0;
			for (int i=0;i<node.listXml.Count;i++)
			{
				XmlNodeValue val = (XmlNodeValue) node.listXml[i];
				if (val.value == null)
				{
					//тада пишем Child
					int count = 0;
					Child ch = (Child) node.list[id];
					//Здесь должна быть обработка и вставка конструкций XSLT
					if (xsd.isSingle(ch.value) && ch.child.listXml.Count != 0)
					{
						//count = WriteXSLT(node, id, i);
						Parametrs p = new Parametrs();
						p.parent = ch.value;
						p.attr = ch.child.att;
						p.isEmpty = false;
						p.parentname = null;

                        Write(ch.child ,true, p);
					}
					else if (ch.child.listXml.Count == 0 && xsd.isSingle(ch.value))
					{
						//count = WriteXSLT(node, id, i);
						Parametrs p = new Parametrs();
						p.parent = ch.value;
						p.attr = ch.child.att;
						//надо выбрать настоящего предка...
						/*Parametrs p1 =*/ GetParent(node.listXml, i, p);
						/*p.parentname = p1.parentname;
						p.parenttype = p1.parenttype;*/
						//p.parentname = ((XmlNodeValue) node.listXml[i-1]).name;
						//p.parenttype = ((XmlNodeValue) node.listXml[i-1]).type;
						p.isEmpty = true;
						WriteXSLT(p);
					}
					else
					{
						//else - (isSingle=false)
						count = WriteXSLT(node, id, i);
						Write(ch.child, false);
						isSingle = false;
					}

					//Здесь должна быть обработка и вставка конструкций XSLT
					for (int k=0;k<count;k++)
						tw.WriteEndElement();
					id++;
				}
				else
				{
					switch (val.type)
					{
						case XmlNodeType.Element:
						{
							tw.WriteStartElement(val.name);
						}break;

						case XmlNodeType.EndElement:
						{
							
							if (isSingle)
							{
								parent.parentname = val.name;
								bool res = WriteXSLT(parent);
								if (res)
									isSingle = false;
								
							}
                            
							/*if (val.name == "w:t" && isSingle)
							{
								//tw.WriteStartElement("xsl:value-of");
								//tw.WriteAttributeString("select","value");
								//tw.WriteEndElement();
								string value = parent.parent;
								tw.WriteString(value);
								if (parent.attr!= null)
								{
                                    tw.WriteString(parent.attr.Count.ToString());
								}

								isSingle = false;
							}*/
							tw.WriteEndElement();
						}break;

						case XmlNodeType.Attribute:
						{
							tw.WriteAttributeString(val.name,val.value);
						}break;
						case XmlNodeType.Text:
						{
							tw.WriteString(val.value);
						}break;
					}
				}
			}
		}
        /// <summary>
        /// Пишет поддерево <see cref="Write(Node,bool,Parametrs)"/>
        /// </summary>
        /// <param name="node">Поддерево</param>
		private void Write(Node node)
		{
			Write(node, false, null);
		}
        /// <summary>
        /// Смотрит, существует ли одинаковые тэги на +1 элементе
        /// </summary>
        /// <param name="node">Узел дерева</param>
        /// <param name="id">Номер элемента в списке xml-тэгов ворда</param>
        /// <param name="i">Номер элемента в списке xml-тэгов ворда</param>
        /// <returns></returns>
		private bool isExistNext(Node node, int id, int i)
		{
			if (id+1 >= node.list.Count || i+1 >= node.listXml.Count)
				return false;
			string name1 = ((Child)node.list[id+1]).value;
			string name2 = ((XmlNodeValue)node.listXml[i+1]).name;
			string val = ((XmlNodeValue)node.listXml[i+1]).value;
			if (val == null && name1 == name2)
				return true;
			else
				return false;
		}
        /// <summary>
        /// Пишет XSLT-Word-файл
        /// </summary>
        /// <param name="node">Узле дереве</param>
        /// <param name="id">Номер 1</param>
        /// <param name="i">Номер 2</param>
        /// <returns></returns>
		private int WriteXSLT(Node node, int id, int i)
		{
			//Node xx = node.parent;
			//Node xx2 = node.
			string prefix = "xsl:";
			Child ch = (Child) node.list[id];
			int count = 0;
			//Вначале мы должны посмареть на атрибуты
			bool attr = false;
			Child v = null;
			if (node.list.Count >0)
			{
				v = (Child)node.list[id];
				if (v.child.att.Count >0)
					attr = true;
			}
			
			if (attr)
			{
				string str = "";
                for (int ii=0;ii<v.child.att.Count;ii++)
                {
					XmlNodeValue val = (XmlNodeValue) v.child.att[ii];
					//Если это keyed
					if (val.name.IndexOf("key-") == 0)
					{
                        if (str != "")
							str += " and ";
						else
							str+="";
						str += "@" + val.name.Substring(4) + "=\'" + val.value + "\'";
					}
                }
				if (str.Length > 0)
				{
					tw.WriteStartElement(prefix + "for-each");
					tw.WriteAttributeString("select", "./" + ch.value +"[" + str +"]");
					count =1;
				}
			}
			else
			{
				if (!isExistNext(node,id,i) && !isExistBefore(node,id,i))
				{
					//т.е. не существует тега до и после текущего, значит он 1 и значит ставим for-each и закрываем его
					tw.WriteStartElement(prefix + "for-each");
					if (node.parent == null)
						tw.WriteAttributeString("select", "//" + ch.value);
					else
						tw.WriteAttributeString("select", "./" + ch.value);

					count =1;
				}
				else if (!isExistBefore(node,id,i))
				{
					tw.WriteStartElement(prefix + "for-each");
					tw.WriteAttributeString("select", "./*");
					tw.WriteStartElement(prefix + "if");
					tw.WriteAttributeString("test","local-name() = '" + ch.value + "'");
					count = 1;
				}
				else if (!isExistNext(node,id,i))
				{
					//tw.WriteStartElement(prifix + "for-each");
					//tw.WriteAttributeString("select", "./" + ch.value);
					tw.WriteStartElement(prefix + "if");
					tw.WriteAttributeString("test","local-name() = '" + ch.value + "'");
					count = 2;
				}
				else
				{
					tw.WriteStartElement(prefix + "if");
					tw.WriteAttributeString("test","local-name() = '" + ch.value + "'");
					count = 1;
				}			
				//tw.WriteStartElement("ns2:" + ch.value);
			}

			return count;
		}
        /// <summary>
        /// Смотрит, существует ли одинаковые тэги на -1 элементе
        /// </summary>
        /// <param name="node">Узел дерева</param>
        /// <param name="id">Номер элемента в списке xml-тэгов ворда</param>
        /// <param name="i">Номер элемента в списке xml-тэгов ворда</param>
        /// <returns></returns>
		private bool isExistBefore(Node node, int id, int i)
		{
            if (id == 0 || i == 0)
				return false;
			string name1 = ((Child)node.list[id-1]).value;
			string name2 = ((XmlNodeValue)node.listXml[i-1]).name;
			string val = ((XmlNodeValue)node.listXml[i-1]).value;
			if (val == null && name1 == name2)
				return true;
			else
				return false;
		}
        /// <summary>
        /// Конструктор, пишутся все необхордиммые заголовки для XSLT-Word-файла
        /// </summary>
        /// <param name="Head">Верхушка дерева</param>
        /// <param name="fileName">имя файла</param>
        /// <param name="XsdFileName">Имя XSD-файла</param>
		public WriteWordXml(Node Head, string fileName, string XsdFileName)
		{
            this.Head = Head;
			TextWriter file = new StreamWriter(fileName);
			tw = new XmlTextWriter(file);
			//tw.Formatting = Formatting.None;
			tw.WriteStartDocument(true);

			tw.WriteStartElement("xsl:stylesheet");
			tw.WriteAttributeString("version","2.0");
			tw.WriteAttributeString("xmlns:xsl","http://www.w3.org/1999/XSL/Transform");
			tw.WriteStartElement("xsl:output");
			tw.WriteAttributeString("method", "xml");
			tw.WriteAttributeString("encoding", "utf-8");
			tw.WriteEndElement();
			tw.WriteStartElement("xsl:template");
					
			tw.WriteAttributeString("match", "/");
			tw.WriteStartElement("xsl:processing-instruction");
			tw.WriteAttributeString("name", "mso-application");
			tw.WriteStartElement("xsl:text");
			tw.WriteString("progid=\"Word.Document\"");
			tw.WriteEndElement();
			tw.WriteEndElement();


			xsd = new XSD(XsdFileName);
			xsd.Load();
		}
        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="parent">Родитель</param>
		public Node(Node parent)
		{
			this.parent = parent;
		}
		public Child(string value, Node parent)
		{
			this.value = value;
			type = 0;
			child = new Node(parent);
		}
        /// <summary>
        /// Читает имя тэга(точнее его префикс) которые записано в Word перед XSD-тэгами
        /// Например ns0:
        /// </summary>
        /// <param name="node"></param>
		private void ReadMainTag(Node node)
		{
			XmlTextReader tr = this.tr;
			XMLNS = "";
			while(tr.Read())
			{
				if (tr.NodeType == XmlNodeType.Element)
				{
					//tw.WriteStartElement(tr.Name);
					node.listXml.Add(new XmlNodeValue(tr.Name,XmlNodeType.Element, tr.Value));
					if (tr.AttributeCount == 0)
						return;
					if (!tr.MoveToFirstAttribute())
					{
						return;
					}
					do
					{
						//tw.WriteAttributeString(tr.Name, tr.Value);
						node.listXml.Add(new XmlNodeValue(tr.Name,XmlNodeType.Attribute, tr.Value));

						if (tr.Value.ToLower() == this.URI.ToLower())
						{
							int ind = tr.Name.LastIndexOf(":");
							XMLNS = tr.Name.Substring(ind + 1); 
						}

					}while (tr.MoveToNextAttribute());
					break;
				}
			}
			if (this.XMLNS == "")
				throw new Exception("Ошибка, в Word документе не найдено схемы с URI: " + this.URI);
		}