using System; using System.Xml; using CYQ.Data.Table; using System.Text.RegularExpressions; using System.Collections.Generic; using CYQ.Data.Tool; using System.Text; using System.Web; using System.Threading; using CYQ.Data.Json; namespace CYQ.Data.Xml { /// /// Xml/Html操作类 /// public partial class XHtmlAction : XHtmlBase { #region 构造函数 /// /// 默认构造函数[操作无名称空间的Xml] /// public XHtmlAction() : base() { } /// /// 构造函数 /// /// true时,将自动载入html的名称空间(http://www.w3.org/1999/xhtml) public XHtmlAction(bool isForHtml) : base() { if (isForHtml) { base.LoadNameSpace(htmlNameSpace); } } /// /// 构造函数 /// /// true时,将自动载入html的名称空间(http://www.w3.org/1999/xhtml) /// true时文档应为只读,所获取是同一份文档引用;false时文档可写,每次获取会克隆一份文档返回。 public XHtmlAction(bool isForHtml, bool isReadOnly) : base() { if (isForHtml) { base.LoadNameSpace(htmlNameSpace); } IsReadOnly = isReadOnly; } /// /// 构造函数 /// /// 当Xml的名称空间[若有] public XHtmlAction(string nameSpaceUrl) : base() { base.LoadNameSpace(nameSpaceUrl); } #endregion #region 查询 /// /// GetByID or GetByName /// /// id or name /// public XmlNode Get(string idOrName) { return Get(idOrName, null); } public XmlNode Get(string idOrName, XmlNode parentNode) { XmlNode node = GetByID(idOrName, parentNode); if (node == null) { node = GetByName(idOrName, parentNode); if (node == null) { switch (idOrName.ToLower()) { case "head": case "body": case "title": case "form": case "style": case "meta": case "link": case "script": XmlNodeList xList = GetList(idOrName.ToLower(), parentNode); if (xList != null) { node = xList[0]; } break; } } } return node; } public XmlNode GetByID(string id) { return Fill(GetXPath("*", "id", id), null); } public XmlNode GetByID(string id, XmlNode parentNode) { return Fill(GetXPath("*", "id", id), parentNode); } public XmlNode GetByName(string name) { return Fill(GetXPath("*", "name", name), null); } public XmlNode GetByName(string name, XmlNode parentNode) { return Fill(GetXPath("*", "name", name), parentNode); } public XmlNode Get(string tag, string attr, string value, XmlNode parentNode) { return Fill(GetXPath(tag, attr, value), parentNode); } public XmlNodeList GetList(string tag, string attr, string value) { return Select(GetXPath(tag, attr, value), null); } public XmlNodeList GetList(string tag, string attr, string value, XmlNode parentNode) { return Select(GetXPath(tag, attr, value), parentNode); } public XmlNodeList GetList(string tag, string attr) { return Select(GetXPath(tag, attr, null), null); } public XmlNodeList GetList(string tag, string attr, XmlNode parentNode) { return Select(GetXPath(tag, attr, null), parentNode); } public XmlNodeList GetList(string tag) { return Select(GetXPath(tag, null, null), null); } public XmlNodeList GetList(string tag, XmlNode parentNode) { return Select(GetXPath(tag, null, null), parentNode); } #endregion #region 创建 protected XmlElement Create(string tag) { if (xnm == null) { return _XmlDocument.CreateElement(tag); } return _XmlDocument.CreateElement(tag, xnm.LookupNamespace(PreXml)); } public void CreateNodeTo(XmlNode parentNode, string tag, string text, params string[] attrAndValue) { if (parentNode != null) { parentNode.AppendChild(CreateNode(tag, text, attrAndValue)); } } public XmlNode CreateNode(string tag, string text, params string[] attrAndValue) { XmlElement xElement = Create(tag); try { if (!string.IsNullOrEmpty(text)) { if (text.Contains("<") && text.Contains(">")) { xElement.InnerXml = text; } else { xElement.InnerText = text; } } } catch { xElement.InnerText = SetCDATA(text); } if (attrAndValue != null && attrAndValue.Length % 2 == 0) { for (int i = 0; i < attrAndValue.Length; i++) { string attr = attrAndValue[i]; i++; string value = attrAndValue[i]; xElement.SetAttribute(attr, value); } } return xElement as XmlNode; } #endregion #region 附加 public void AppendNode(XmlNode parentNode, XmlNode childNode) { if (parentNode != null && childNode != null) { parentNode.AppendChild(childNode); } } /// /// 添加节点 /// /// parentNode的第N个子节点之后 public void AppendNode(XmlNode parentNode, XmlNode childNode, int position) { if (parentNode != null && childNode != null)// A B { if (parentNode.ChildNodes.Count == 0 || position >= parentNode.ChildNodes.Count) { parentNode.AppendChild(childNode); } else if (position == 0) { InsertBefore(childNode, parentNode.ChildNodes[0]); } else { InsertAfter(childNode, parentNode.ChildNodes[position - 1]); } } } #endregion #region 删除 /// /// 保留节点,但清除节点所内容/属性 /// public void Clear(XmlNode node) { node.RemoveAll(); } public void Remove(XmlNode node) { if (node != null) { node.ParentNode.RemoveChild(node); } } public void Remove(string idOrName) { XmlNode node = Get(idOrName); if (node != null) { node.ParentNode.RemoveChild(node); } } public void RemoveAllChild(XmlNode node) { RemoveChild(node, 0); } public void RemoveAllChild(string idOrName) { RemoveChild(idOrName, 0); } /// /// 移除子节点 /// /// 节点的id /// 从第几个子节点开始删除[索引从0开始] public void RemoveChild(string idOrName, int start) { XmlNode node = Get(idOrName); if (node != null) { RemoveChild(node, start); } } /// /// 移除子节点 /// /// 节点 /// 从第几个子节点开始删除[索引从0开始] public void RemoveChild(XmlNode node, int start) { if (start == 0) { node.InnerXml = ""; return; } if (node.ChildNodes.Count > start) //1个子节点, 0 { for (int i = node.ChildNodes.Count - 1; i >= start; i--) { node.RemoveChild(node.ChildNodes[i]); } } } /// /// 移除多个属性 /// /// 要移除的名称列表 public void RemoveAttrList(params string[] attrNames) { XmlNodeList nodeList = null; foreach (string name in attrNames) { nodeList = GetList("*", name); if (nodeList != null && nodeList.Count > 0) { for (int i = 0; i < nodeList.Count; i++) { nodeList[i].Attributes.Remove(nodeList[i].Attributes[name]); } } } } /// /// 属性移除 /// /// 属性名称 /// 排除的节点类型 public void RemoveAttrList(string attrName, SetType excludeSetType) { XmlNodeList nodeList = GetList("*", attrName); if (nodeList != null && nodeList.Count > 0) { XmlNode node = null; string setType = excludeSetType.ToString().ToLower(); for (int i = 0; i < nodeList.Count; i++) { node = nodeList[i]; if (node.Name != setType) { node.Attributes.Remove(node.Attributes[attrName]); } } } } /// /// 移除注释节点 /// /// 移除此节点的注释文本 public void RemoveCommentNode(XmlNode node) { if (node != null) { XmlNodeList xmlNodeList = Select("//comment()", node); foreach (XmlNode xNode in xmlNodeList) { xNode.ParentNode.RemoveChild(xNode); } } } /// /// 移除注释节点 /// public override void RemoveCommentNode() { RemoveCommentNode(XmlDoc.DocumentElement); } #endregion #region 其它交换节点/插入节点 /// /// 两个节点交换位置 /// /// 第一个节点 /// 第二个节点 public void InterChange(XmlNode xNodeFirst, XmlNode xNodeLast) { if (xNodeFirst != null && xNodeLast != null) { if (xNodeFirst.ParentNode != null && xNodeLast.ParentNode != null) { xNodeFirst.ParentNode.ReplaceChild(xNodeLast.Clone(), xNodeFirst); xNodeLast.ParentNode.ReplaceChild(xNodeFirst.Clone(), xNodeLast); } else { _XmlDocument.DocumentElement.ReplaceChild(xNodeLast.Clone(), xNodeFirst); _XmlDocument.DocumentElement.ReplaceChild(xNodeFirst.Clone(), xNodeLast); } } } public void ReplaceNode(XmlNode newNode, string oldNodeIDorName) { ReplaceNode(newNode, Get(oldNodeIDorName)); } /// /// 节点替换[支持两个的文档间替换] /// /// 新的数据节点 /// 旧的节点 public void ReplaceNode(XmlNode newNode, XmlNode oldNode) { if (newNode != null && oldNode != null) { //oldNode = newNode.Clone(); if (newNode.Name == oldNode.Name) // 节点名相同。 { oldNode.RemoveAll();//清空旧节点 oldNode.InnerXml = newNode.InnerXml; XmlAttributeCollection attrs = newNode.Attributes;//设置属性 if (attrs != null && attrs.Count > 0) { for (int i = 0; i < attrs.Count; i++) { if (attrs[i].Name == "xml:space") { continue; } ((XmlElement)oldNode).SetAttribute(attrs[i].Name, attrs[i].Value); } } } else { XmlNode xNode = CreateNode(newNode.Name, newNode.InnerXml);//先创建一个节点。 XmlAttributeCollection attrs = newNode.Attributes; if (attrs != null && attrs.Count > 0) { for (int i = 0; i < attrs.Count; i++) { ((XmlElement)xNode).SetAttribute(attrs[i].Name, attrs[i].Value); } } oldNode.ParentNode.InsertAfter(xNode, oldNode);//挂在旧节点后面。 Remove(oldNode); } } } /// /// 节点之后插入[支持两文档之间的插入] /// /// 要被插入的新节点 /// 在此节点后插入NewNode节点 public void InsertAfter(XmlNode newNode, XmlNode refNode) { XmlNode xDocNode = CreateNode(newNode.Name, ""); ReplaceNode(newNode, xDocNode); refNode.ParentNode.InsertAfter(xDocNode, refNode); } /// /// 节点之前插入[支持两文档之间的插入] /// /// 要被插入的新节点 /// 在此节点前插入NewNode节点 public void InsertBefore(XmlNode newNode, XmlNode refNode) { XmlNode xDocNode = CreateNode(newNode.Name, ""); ReplaceNode(newNode, xDocNode); refNode.ParentNode.InsertBefore(xDocNode, refNode); } #endregion #region 节点判断 public bool Contains(string idOrName) { return Get(idOrName) != null; } public bool Contains(string idOrName, XmlNode parentNode) { return Get(idOrName, parentNode) != null; } #endregion #region 属性判断/取值 public bool HasAttr(string idOrName, string attrName) { return GetAttrValue(idOrName, attrName) != string.Empty; } public bool HasAttr(XmlNode node, string attrName) { return GetAttrValue(node, attrName) != string.Empty; } public string GetAttrValue(string idOrName, string attrName, params string[] defaultValue) { XmlNode node = Get(idOrName); return GetAttrValue(node, attrName, defaultValue); } public string GetAttrValue(XmlNode node, string attrName, params string[] defaultValue) { if (node != null) { switch (attrName) { case "InnerText": if (!string.IsNullOrEmpty(node.InnerText)) { return node.InnerText; } break; case "InnerXml": if (!string.IsNullOrEmpty(node.InnerXml)) { return node.InnerXml; } break; default: if (node.Attributes != null && node.Attributes[attrName] != null) { return node.Attributes[attrName].Value; } break; } } if (defaultValue.Length > 0) { return defaultValue[0]; } return string.Empty; } public void RemoveAttr(string idOrName, params string[] attrNames) { XmlNode node = Get(idOrName); RemoveAttr(node, attrNames); } public void RemoveAttr(XmlNode node, params string[] attrNames) { if (node != null && node.Attributes != null) { foreach (string name in attrNames) { if (node.Attributes[name] != null) { node.Attributes.Remove(node.Attributes[name]); } } } } #endregion #region 操作数据 private bool _IsCurrentLang = true; /// /// 当前请求是否用户当前设置的语言 /// public bool IsCurrentLang { get { return _IsCurrentLang; } set { _IsCurrentLang = value; } } /// /// 是否开始自定义语言分隔(分隔符号为:[#langsplit]) /// public bool IsUseLangSplit = true; private string SetValue(string sourceValue, string newValue, bool addCData) { if (string.IsNullOrEmpty(newValue)) { return sourceValue; } newValue = newValue.Replace(ValueReplace.Source, sourceValue); if (IsUseLangSplit) { int split = newValue.IndexOf(ValueReplace.LangSplit); if (split > -1) { newValue = _IsCurrentLang ? newValue.Substring(0, split) : newValue.Substring(split + ValueReplace.LangSplit.Length); } } if (addCData) { newValue = SetCDATA(newValue); } return newValue; } private void SetAttrValue(XmlNode node, string key, string value) { if (node == null || node.Attributes == null) { return; } if (node.Attributes[key] == null) { XmlAttribute attr = _XmlDocument.CreateAttribute(key); node.Attributes.Append(attr); } value = SetValue(node.Attributes[key].InnerXml, value, false); try { node.Attributes[key].Value = value; } catch { node.Attributes[key].Value = SetCDATA(value); } } /// /// 为节点赋值[通常值是在values中赋值] /// public void Set(XmlNode node, SetType setType, params string[] values) { if (node != null && values != null) { switch (setType) { case SetType.InnerText: string value = SetValue(node.InnerText, values[0], false); try { node.InnerText = value; } catch { node.InnerText = SetCDATA(value); } break; case SetType.InnerXml: node.InnerXml = SetValue(node.InnerXml, values[0], true); break; case SetType.Value: case SetType.Href: case SetType.Src: case SetType.Class: case SetType.Disabled: case SetType.ID: case SetType.Name: case SetType.Visible: case SetType.Title: case SetType.Style: case SetType.ClearFlag: string key = setType.ToString().ToLower(); SetAttrValue(node, key, values[0]); break; case SetType.Custom: for (int i = 0; i < values.Length; i++) { if (i > 0 && i % 2 == 1) { key = values[i - 1].ToLower(); switch (key) { case "innertext": Set(node, SetType.InnerText, values[i]); break; case "innerhtml": case "innerxml": Set(node, SetType.InnerXml, values[i]); break; default: SetAttrValue(node, key, values[i]); break; } } } break; case SetType.A: node.InnerXml = SetValue(node.InnerXml, values[0], true); if (values.Length > 1) { SetAttrValue(node, "href", values[1]); if (values.Length > 2) { SetAttrValue(node, "title", values[2]); if (values.Length > 3) { SetAttrValue(node, "target", values[3]); } } } break; case SetType.Select: if (!node.InnerXml.StartsWith("<"))//带特殊字符 { string innerHtml = node.InnerXml.Replace(string.Format("value=\"{0}\"", values[0]), string.Format("selected=\"selected\" value=\"{0}\"", values[0])); try { node.InnerText = innerHtml; //node.InnerXml = innerHtml; } catch { node.InnerXml = SetCDATA(innerHtml); } } else { string lowerValue = values[0].ToLower(); foreach (XmlNode option in node.ChildNodes) { string opValue = option.InnerText.ToLower(); if (option.Attributes["value"] != null) { opValue = option.Attributes["value"].Value.Split(',')[0].ToLower(); } if (opValue == lowerValue || opValue == (lowerValue == "true" ? "1" : (lowerValue == "false" ? "0" : lowerValue))) { SetAttrValue(option, "selected", "selected"); break; } } } break; case SetType.Checked: string type = GetAttrValue(node, "type"); if (node.Name == "input" && type == "radio") { values[0] = "1"; } switch (values[0].ToLower()) { case "1": case "true": case "check": case "checked": key = setType.ToString().ToLower(); SetAttrValue(node, key, key); break; case "0": case "false": if (type == "checkbox") { RemoveAttr(node, setType.ToString().ToLower()); } break; } break; } } } public void Set(string idOrName, SetType setType, params string[] values) { Set(null, idOrName, setType, values); } public void Set(XmlNode parentNode, string idOrName, SetType setType, params string[] values) { XmlNode node = Get(idOrName, parentNode); Set(node, setType, values); } public void Set(string idOrName, string value) { Set(null, idOrName, value); } /// /// 对节点赋值(此方法会忽略hidden隐藏域,隐藏节点赋值请用其它重载方法) /// /// /// public void Set(XmlNode parentNode, string idOrName, string value) { XmlNode node = Get(idOrName, parentNode); if (node != null) { SetType setType = SetType.InnerXml; switch (node.Name) { case "input": switch (GetAttrValue(node, "type")) { case "hidden": return;//此方法不对隐藏域处理。 case "checkbox": setType = SetType.Checked; break; case "image": setType = SetType.Src; break; case "radio"://情况复杂一点 XmlNodeList nodeList = GetList("input", "type", "radio"); for (int i = 0; i < nodeList.Count; i++) { if (GetAttrValue(nodeList[i], "name") == idOrName) { RemoveAttr(nodeList[i], "checked"); if (GetAttrValue(nodeList[i], "value") == value) { node = nodeList[i]; } } } setType = SetType.Checked; break; default: setType = SetType.Value; break; } break; case "select": setType = SetType.Select; break; case "a": setType = SetType.Href; break; case "img": setType = SetType.Src; break; } //try //{ Set(node, setType, value); //} //catch (Exception err) //{ // throw; //} } } #endregion #region 重写最终输出OutXml /// /// 输出的Xml内容。 /// public override string OutXml { get { if (_XmlDocument != null) { #region 处理clearflag标签 string key = "clearflag"; XmlNodeList xnl = GetList("*", key); if (xnl != null) { XmlNode xNode = null; for (int i = xnl.Count - 1; i >= 0; i--) { xNode = xnl[i]; switch (GetAttrValue(xnl[i], key)) { case "0": RemoveAttr(xNode, key); xNode.InnerXml = ""; break; case "1": Remove(xNode); break; } } } #endregion #region 处理XHtml 头前缀、清空CData string html = _XmlDocument.InnerXml; if (html.Contains(".dtd\"[]>")) { html = html.Replace(".dtd\"[]>", ".dtd\">"); } if (html.Contains(" xmlns=")) { html = html.Replace(" xmlns=\"\"", string.Empty).Replace(" xmlns=\"" + xnm.LookupNamespace(PreXml) + "\"", string.Empty); } if (html.Contains("&")) { //先把&符号替换回来,再替换后面的。 html = html.Replace("&", "&").Replace(">", ">").Replace("<", "<");//html标签符号。 } //if (!string.IsNullOrEmpty(docTypeHtml)) //{ // html = html.Replace(docTypeHtml, ""); //} #endregion #region 处理剩余的占位符替换 if (html.IndexOf("${") > -1 || html.IndexOf("<%#") > -1) { html = FormatHtml(html, null); } #endregion #region 清除CData标签 html = ClearCDATA(html); #endregion if (html.StartsWith(" /// 对Html的内容,进行标签替换【1次替换】 /// /// 需要被替换的内容 /// 用于值替换搜索的字典数据 /// private string FormatHtml(string html, MDictionary values) { if (html.IndexOf("${") > -1) { #region 替换占位符号 MatchCollection matchs = Regex.Matches(html, @"\$\{([\S\s]*?)\}", RegexOptions.Compiled | RegexOptions.IgnoreCase); if (matchs != null && matchs.Count > 0) { //过滤重复的占位符。 List keys = new List(matchs.Count); foreach (Match match in matchs) { //原始的占位符 ${txt#name:xx#xx} string value = match.Groups[0].Value;//${txt#name:xx#xx},${'aaa'+txt#name:xx#xx+'bbb'} if (string.IsNullOrEmpty(value) || keys.Contains(value)) { continue; } keys.Add(value); #region 分解占位符 //先处理+号 ${'aaa'+txt#name:xx#xx+'bbb'} formatter= 'aaa'{0} string formatter = "", key = ""; string[] items = match.Groups[1].Value.Trim().Split('+');//['aa',txt#name] foreach (string item in items) { if (item[0] == '"') { formatter += item.Trim('"'); } else if (item[0] == '\'') { formatter += item.Trim('\''); } else { if (!string.IsNullOrEmpty(key)) { break;//只允许存在一个key : txt#name:这是描述说明。 } formatter += "{0}"; key = item.Trim(); } } string columnName = key.Split(':')[0];//name #endregion string replaceValue = ""; #region 获取占位符的值 if (values != null) { replaceValue = GetValue1(columnName, values); } if (string.IsNullOrEmpty(replaceValue)) { replaceValue = GetValueByKeyValue2(columnName); } if (string.IsNullOrEmpty(replaceValue)) { replaceValue = GetValueByRequest3(columnName, key); } #endregion html = html.Replace(value, string.IsNullOrEmpty(replaceValue) ? "" : string.Format(formatter, replaceValue)); } keys.Clear(); keys = null; matchs = null; } #endregion } if (html.IndexOf("<%#") > -1)//js eval 执行 { #region 替换JavaScript语法 MatchCollection matchs = Regex.Matches(html, @"<%#([\S\s]*?)%>", RegexOptions.Compiled | RegexOptions.IgnoreCase); if (matchs != null && matchs.Count > 0) { foreach (Match match in matchs) { //原始的占位符 string value = match.Groups[0].Value;//${txt#name:xx#xx},${'aaa'+txt#name:xx#xx+'bbb'} string value1 = match.Groups[1].Value; string evalValue = null; try { evalValue = Convert.ToString(Microsoft.JScript.Eval.JScriptEvaluate(value1, Microsoft.JScript.Vsa.VsaEngine.CreateEngine())); } catch (Exception err) { Log.WriteLogToTxt(err, LogType.Error); } html = html.Replace(value, evalValue); } } #endregion } return html; } private string GetValue1(string columnName, MDictionary values)//, MDataRow row { if (values.ContainsKey(columnName))//值可能被格式化过,所以优先取值。 { return values[columnName]; } else if (columnName.Length < 3) { int i = 0; if (int.TryParse(columnName, out i) && i < values.Count) { return values[i]; //数字 } } //else //{ // MDataCell matchCell = row[columnName]; // if (matchCell != null) // { // return matchCell.ToString(); // } //} return string.Empty; } private string GetValueByKeyValue2(string columnName) { //处理keyValue替换 if (KeyValue.Count > 0 && KeyValue.ContainsKey(columnName)) { return KeyValue[columnName]; } return string.Empty; } private string GetValueByRequest3(string columnName, string key) { string replaceValue = string.Empty; if (HttpContext.Current != null && HttpContext.Current.Handler != null) { replaceValue = HttpContext.Current.Request[columnName] ?? HttpContext.Current.Request.Headers[columnName]; } if (string.IsNullOrEmpty(replaceValue) && key.Contains(":"))//如果为空,设置默认的说明。 { replaceValue = key.Substring(key.LastIndexOf(':') + 1); } return replaceValue ?? ""; } #endregion } //扩展交互 public partial class XHtmlAction { #region 操作数据 MDataRow _Row; #region 加载表格循环方式 public delegate string SetForeachEventHandler(string text, MDictionary values, int rowIndex); /// /// 对于SetForeach函数调用的格式化事件 /// public event SetForeachEventHandler OnForeach; public void SetForeach(MDataTable dataSource) { if (dataSource != null) { XmlNode node = Get(dataSource.TableName + "View"); if (node == null) { node = Get("defaultView"); } if (node != null) { SetForeach(dataSource, node, node.InnerXml, OnForeach); } } } public void SetForeach(MDataTable dataSource, string idOrName) { XmlNode node = Get(idOrName); SetForeach(dataSource, node, node.InnerXml, OnForeach); } public void SetForeach(MDataTable dataSource, string idOrName, string text) { XmlNode node = Get(idOrName); SetForeach(dataSource, node, text, OnForeach); } public void SetForeach(MDataTable dataSource, string idOrName, SetType setType) { string text = string.Empty; XmlNode node = Get(idOrName); if (node == null) { return; } switch (setType) { case SetType.InnerText: text = node.InnerText; break; case SetType.InnerXml: text = node.InnerXml; break; case SetType.Value: case SetType.Href: case SetType.Src: case SetType.Class: case SetType.Disabled: case SetType.ID: case SetType.Name: case SetType.Visible: case SetType.Title: case SetType.Style: string key = setType.ToString().ToLower(); if (node.Attributes[key] != null) { text = node.Attributes[key].Value; } break; } SetForeach(dataSource, node, text, OnForeach); } public void SetForeach(MDataTable dataSource, XmlNode node) { if (node == null) { return; } SetForeach(dataSource, node, node.InnerXml, OnForeach); } public void SetForeach(MDataTable dataSource, XmlNode node, string text) { if (node == null) { return; } SetForeach(dataSource, node, text, OnForeach); } /// /// 对列表进行循环绑定处理 /// /// 数据源 /// 处理的节点 /// 用于循环的内容【通常传递node.InnerXml】 /// 自定义事件 public void SetForeach(MDataTable dataSource, XmlNode node, string text, SetForeachEventHandler eventOnForeach) { try { #region 前置条件处理 if (node == null || string.IsNullOrEmpty(text)) { return; } if (dataSource == null || dataSource.Rows.Count == 0 || dataSource.Columns.Count == 0) { if (node.Attributes["clearflag"] == null) { node.InnerText = string.Empty; } return; } RemoveAttr(node, "clearflag"); #endregion StringBuilder innerXml = new StringBuilder(); for (int k = 0; k < dataSource.Rows.Count; k++) { string newText = text; MDictionary values = GetFromRow(dataSource.Rows[k]); if (eventOnForeach != null) { newText = eventOnForeach(text, values, k);//遍历每一行,产生新text。 } try { if (newText.IndexOf("${") > -1 || newText.IndexOf("<%#") > -1) { newText = FormatHtml(newText, values); } innerXml.Append(newText); } catch (Exception err) { Log.Write(err, LogType.Error); } finally { values.Clear(); } } ////用InnerText性能好,但循环后的内容无法通过节点操作。 //node.InnerText = innerXml.ToString(); try { node.InnerXml = innerXml.ToString(); } catch { try { node.InnerXml = SetCDATA(innerXml.ToString()); } catch (Exception err) { Log.Write(err, LogType.Error); } } } finally { if (eventOnForeach != null) { eventOnForeach = null; } } } /// /// 能减少反射就减少反射 /// private MDictionary GetFromRow(MDataRow row) { MDictionary keyValuePairs = new MDictionary(StringComparer.OrdinalIgnoreCase); foreach (var item in row) { keyValuePairs.Add(item.ColumnName, item.StringValue); } return keyValuePairs; } #endregion #region 加载行数据后操作方式 /// /// 用于替换占位符的数据。 /// public MDictionary KeyValue = new MDictionary(StringComparer.OrdinalIgnoreCase); /// /// 加载MDatarow行数据(CMS替换) /// /// 为所有字段名指定前缀(如:"a.",或空前缀:"" public void LoadData(object anyObjToRow, string pre) { LoadData(MDataRow.CreateFrom(anyObjToRow), pre); } /// /// 装载数据行 (一般后续配合SetFor方法使用或CMS替换) /// /// 为所有字段名指定前缀(如:"a.",或空前缀:"") public void LoadData(MDataRow row, string pre) { if (pre != null && row != null) { foreach (MDataCell cell in row) { if (cell.IsNullOrEmpty) { continue; } string cName = pre + cell.ColumnName; if (KeyValue.ContainsKey(cName)) { KeyValue[cName] = cell.ToString(); } else { KeyValue.Add(cName, cell.ToString()); } } } _Row = row; } /// /// 装载行数据 (一般后续配合SetFor方法使用) /// /// 数据行 public void LoadData(MDataRow row) { _Row = row; } /// /// 为节点设置值,通常在LoadData后使用。 /// /// 节点的id或name public void SetFor(string idOrName) { SetFor(idOrName, SetType.InnerXml); } /// /// 为节点设置值,通常在LoadData后使用。 /// /// 节点的类型 public void SetFor(string idOrName, SetType setType) { SetFor(idOrName, setType, GetRowValue(idOrName)); } /// /// 为节点设置值,通常在LoadData后使用。 /// /// setType为Custom时,可自定义值,如“"href","http://www.cyqdata.com","target","_blank"” public void SetFor(string idOrName, SetType setType, params string[] values) { int i = setType == SetType.Custom ? 1 : 0; for (; i < values.Length; i++) { if (values[i].Contains(ValueReplace.New)) { values[i] = values[i].Replace(ValueReplace.New, GetRowValue(idOrName)); } } Set(Get(idOrName), setType, values); } private string GetRowValue(string idOrName) { string rowValue = ""; if (_Row != null) { MDataCell cell = _Row[idOrName]; if (cell == null && idOrName.Length > 3) { cell = _Row[idOrName.Substring(3)]; } if (cell != null) { rowValue = cell.IsNull ? "" : cell.StringValue; } } return rowValue; } #endregion #endregion public override void Dispose() { base.Dispose(); KeyValue.Clear(); _Row = null; } } /// /// Json 交互 /// public partial class XHtmlAction { #region 转Json /// /// 转Json /// /// public string ToJson() { return ToJson(XmlDoc.DocumentElement, true); } /// /// 转Json /// 可设置一个节点(默认根节点) /// 是否将属性值也输出 /// public string ToJson(XmlNode parent, bool isWithAttr) { parent = parent ?? XmlDoc.DocumentElement; if (parent == null) { return string.Empty; } JsonHelper js = new JsonHelper(false, false); //分解递归,不然真他妈不好调试 js.Add(parent.Name, GetRootJson(parent, isWithAttr), true); js.AddBr(); return js.ToString(); } private string GetRootJson(XmlNode root, bool isWithAttr) { JsonHelper js = new JsonHelper(false, false); //js.Escape = EscapeOp.No; if (isWithAttr && root.Attributes != null && root.Attributes.Count > 0) { foreach (XmlAttribute item in root.Attributes) { js.Add(item.Name, item.Value); } } if (root.HasChildNodes) { foreach (XmlNode item in root.ChildNodes) { string childJson = GetChildJson(item, isWithAttr); js.Add(item.Name, childJson, !string.IsNullOrEmpty(childJson) && (childJson[0] == '{' || childJson[0] == '[')); } } string result = js.ToString(); return result; } private string GetChildJson(XmlNode parent, bool isWithAttr) { JsonHelper js = new JsonHelper(false, false); //js.Escape = EscapeOp.No; if (isWithAttr && parent.Attributes != null && parent.Attributes.Count > 0) { foreach (XmlAttribute item in parent.Attributes) { js.Add(item.Name, item.Value); } } if (parent.HasChildNodes) { XmlNode x0 = parent.ChildNodes[0];//XXList xx int childCount = parent.ChildNodes.Count; if (x0.NodeType != XmlNodeType.Element && childCount == 1) { if (js.RowCount == 0) { return parent.InnerText; } else { js.Add(parent.Name, parent.InnerText); } } else { #region MyRegion MDictionary jsonDic = new MDictionary(StringComparer.OrdinalIgnoreCase); List arrayName = new List(); foreach (XmlNode item in parent.ChildNodes) { string childJson = GetChildJson(item, isWithAttr); if (!jsonDic.ContainsKey(item.Name)) { StringBuilder sb = new StringBuilder(); sb.Append(childJson); jsonDic.Add(item.Name, sb); } else // 重复的TagName { if (!arrayName.Contains(item.Name)) { arrayName.Add(item.Name); } jsonDic[item.Name].Append("," + childJson);// = "[" + jsonDic[item.Name].TrimStart('[').TrimEnd(']') + "," + childJson + "]"; } } bool isList = parent.Name.EndsWith("List") && jsonDic.Count == 1; string cName = parent.Name.Substring(0, parent.Name.Length - 4); foreach (KeyValuePair kv in jsonDic) { string v = kv.Value.ToString(); if (v.Length > 0 && v[0] != '[' && (isList || arrayName.Contains(kv.Key))) { v = "[" + v + "]"; } if (isList && kv.Key == cName) { return v; // js.Add(parent.Name, v, true); } else { js.Add(kv.Key, v, !string.IsNullOrEmpty(v) && (v[0] == '{' || v[0] == '[')); } } jsonDic.Clear(); jsonDic = null; arrayName.Clear(); arrayName = null; #endregion } } js.AddBr(); string result = js.ToString(); if (result == "{}") { return ""; } else { if (js.RowCount == 0) { return ""; // return "fuck"; //卧槽,怎么有这样的代码? } } return result; } #endregion } }