/// <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); }