C#完成XML文档节点的自动计算功能
一个项目涉及XML文档中节点的自动计算,就是XML文档的每个节点都参与运算,要求:
⑴如果节点有计算公式则按照计算公式进行;
⑵如果节点没有计算公式则该节点的值就是所有子节点的值之和;
⑶节点有4种类型,计算节点、输入框、单选节点、多选节点;
计算节点:汇总;
输入框:点击该节点弹出输入框用于输入数据;
单选节点:众多选项中只能选择一个,根据选择项确定该节点的具体值;
多选节点:众多选项中可以选择多个,该节点的值是所有选择项的和;
类似下图(实际选项近100个):
问题是点击任何图标节点后都要完成的自动计算。
开始的时候,我将所有XML信息加载到Treeview中,包括属性,在Treeview中进行计算,完成后同步到XML文档,这样完成后效果不好,选项多了速度慢,如果计算机配置一般的话有略微的卡顿。
今天下午,我修改了方法,直接在XML文档中进行操作,使用递归完成节点的自动计算,这样速度很快,并且不需要同步到Treeview中(因为Treeview只是用于显示)。
1、点击节点
在Treeview中确定节点,根据节点类型完成图标变化,在XML中找到对应的节点。
⑴完成状态标识,如果是Radio则标识单选;如果是Checkbox标识多选;
⑵提取Value值,如果是Textbox则是输入值,如果是Radio则是父项value值是点击节点的Value值;如果是Checkbox则父项是所有选择项的value值之和。
⑶调用自动计算,如果是Radio或者Checkbox则是从父项的父项开始,如果是Textbox则是从父项开始。
private void treeView1_MouseDown(object sender, MouseEventArgs e){//获取鼠标点击的位置TreeNode FocusNode = treeView1.GetNodeAt(e.Location);string StrCurrentFullPath = FocusNode.FullPath;string StrNodeType = "";if (FocusNode != null){//获取鼠标点击的位置是否在节点的图标上//在Treeview中针对Radio、Checkbox、TextBook分别进行设置TreeViewHitTestInfo hitTestInfo = treeView1.HitTest(e.Location);if (hitTestInfo.Location == TreeViewHitTestLocations.Image){StrNodeType = FocusNode.Tag.ToString();//鼠标点击了节点的图标switch (StrNodeType){case "Radio":// 取消同级节点的选中状态foreach (TreeNode node1 in FocusNode.Parent.Nodes){if (node1 != FocusNode){node1.ImageKey = "Radio";node1.SelectedImageKey = "Radio";}}// 设置当前节点为选中状态FocusNode.ImageKey = "RadioChecked";FocusNode.SelectedImageKey = "RadioChecked";//在XML文档中处理HandleNodeInfoAtXmlContent(StrCurrentFullPath, StrNodeType,"");//在文档中找到该节点并处理//break;case "Checkbox":if (FocusNode.ImageKey == "Checkbox"){FocusNode.ImageKey = "CheckboxChecked";FocusNode.SelectedImageKey = "CheckboxChecked";}else{FocusNode.ImageKey = "Checkbox";FocusNode.SelectedImageKey = "Checkbox";}//在XML文档中处理HandleNodeInfoAtXmlContent(StrCurrentFullPath, StrNodeType,"");//在文档中找到该节点并处理break;case "Textbox":string StrMin = "";string StrMax = "";string StrMemo = "";float fTemp;ToTextboxInputWinPara.fMax = 0;ToTextboxInputWinPara.fMin = 0;ToTextboxInputWinPara.StrMemo = "";FrmTextBoxInput FTI= new FrmTextBoxInput();DialogResult result= FTI.ShowDialog();if(result == DialogResult.OK){StrCurrentTextboxValue = FTI.StrReturn;}//在XML文档中处理HandleNodeInfoAtXmlContent(StrCurrentFullPath, StrNodeType, StrCurrentTextboxValue);//在文档中找到该节点并处理break;}treeView1.Invalidate();}if (hitTestInfo.Location == TreeViewHitTestLocations.Label){//点击标签if (FocusNode.Tag != null){switch (FocusNode.Tag.ToString()){case "Radio":if (FocusNode.ImageKey == "RadioChecked"){FocusNode.SelectedImageKey = "RadioChecked";}if (FocusNode.ImageKey == "Radio"){FocusNode.SelectedImageKey = "Radio";}break;case "Checkbox":if (FocusNode.ImageKey == "Checkbox"){FocusNode.SelectedImageKey = "Checkbox";}if (FocusNode.ImageKey == "CheckboxChecked"){FocusNode.SelectedImageKey = "CheckboxChecked";}break;default: break;}treeView1.Invalidate();}}}}
对应在XML文档中的处理函数:
private void HandleNodeInfoAtXmlContent(string StrCurrentFullPath,string StrNodeType,string StrInputTextValue){//在XML文档内容中处理节点信息,传入参数:StrCurrentFullPath是当前点击选择的节点全路径名称int FirstIndex = StrCurrentFullPath.IndexOf("\\");int LastIndex = StrCurrentFullPath.LastIndexOf("\\");string StrCurrentNodeName = StrCurrentFullPath.Substring(LastIndex + 1);//提取父节点的名称string[] SubStr= StrCurrentFullPath.Split("\\");string ParentStr = SubStr[SubStr.Length - 2];// 使用XPath表达式定位到具体的节点,点击的节点名称是caption值string XpathExpression="";XmlNode CalculateNode=null;//计算节点switch (StrNodeType){case "Radio":XpathExpression = "//" + ParentStr + "/option[@caption='" + StrCurrentNodeName + "']";break;case "Checkbox":XpathExpression = "//" + ParentStr + "/input[@caption='" + StrCurrentNodeName + "']";break;case "Textbox":XpathExpression = "//" + ParentStr + "/"+ StrCurrentNodeName;break;}XmlNode BeSelectNode = XmlDoc.SelectSingleNode(XpathExpression);//得到父节点的全路径名string SParentPath = StrCurrentFullPath.Substring(0, LastIndex);//得到父节点XmlNode ParentNode = FindNodeAtXmlContentByFullPath(SParentPath);XmlNode TempNode = null;if (BeSelectNode != null && ParentNode!=null){//根据节点类型处理本节点switch (StrNodeType){case "Radio":string StrValue = "";//找到该节点标识选中状态foreach (XmlNode RadioChildNode in ParentNode.ChildNodes){//单选,先将父节点下的子节点的select属性全部删除if (RadioChildNode.Attributes["select"] != null){RadioChildNode.Attributes.Remove(RadioChildNode.Attributes["select"]);}//找到子节点if (RadioChildNode.Attributes["caption"].Value == StrCurrentNodeName){TempNode = RadioChildNode;StrValue = TempNode.Attributes["value"].Value;}}//添加select属性if (TempNode!=null){ if (HasAttribute(TempNode, "select")){TempNode.Attributes["select"].Value = "true";}else{XmlAttribute RadioNodeAttr = XmlDoc.CreateAttribute("select");RadioNodeAttr.Value = "true";TempNode.Attributes.Append(RadioNodeAttr);}}//为父节点的value属性赋值ParentNode.Attributes["value"].Value = StrValue;//寻找父节点的父节点CalculateNode = ParentNode.ParentNode;//计算Autocalculate(CalculateNode);break;case "Checkbox":Single TempSum = 0.0f;//找到该节点标识状态,如果是选择则去掉,没有选择则加上,同时计算和foreach (XmlNode CheckChildNode in ParentNode.ChildNodes){if (CheckChildNode.Attributes["caption"].Value == StrCurrentNodeName){TempNode = CheckChildNode;}}//添加select属性if (HasAttribute(TempNode, "select")){if (TempNode.Attributes["select"].Value == "true"){//如果已经选择了,需要去掉选择TempNode.Attributes.Remove(TempNode.Attributes["select"]);}else{TempNode.Attributes["select"].Value = "true";}}else{XmlAttribute CheckSelectedAttr = XmlDoc.CreateAttribute("select");CheckSelectedAttr.Value = "true";TempNode.Attributes.Append(CheckSelectedAttr);}foreach (XmlNode CheckChildNode in ParentNode.ChildNodes){if (HasAttribute(CheckChildNode, "select")){TempSum += Convert.ToSingle(CheckChildNode.Attributes["value"].Value);}}//为父节点的value属性赋值ParentNode.Attributes["value"].Value = TempSum.ToString();//寻找父节点的父节点CalculateNode = ParentNode.ParentNode;//计算Autocalculate(CalculateNode);break;case "Textbox"://找到该节点修改Value值BeSelectNode.Attributes["value"].Value = StrInputTextValue;//寻找本节点的父节点CalculateNode = BeSelectNode.ParentNode;//计算Autocalculate(CalculateNode);break;}}else{textBox1.Text += "提取属性值发生错误,没有找到对应节点或者属性值错误!" + Environment.NewLine;}}
2、递归计算
private void Autocalculate(XmlNode CalculateNode){//在XML文档中,节点自动计算结果//CalculateResult MyCalcuteResult= new CalculateResult();float fSum = 0f;string StrID = "";string StrValue = "";string StrFormula = "";Boolean Continue = true;string StrFalse = "";//判断是否有子节点if (CalculateNode.HasChildNodes){//有子节点需要看是否有计算公式,根据指定的节点进行自动计算if (HasAttribute(CalculateNode, "formula")){//如果节点有formula属性,则提取出计算公式。StrFormula = GetAttrValue(CalculateNode, "formula");//将所有子节点的值进行替换完成后再进行计算。foreach (XmlNode MyNode in CalculateNode.ChildNodes){if (HasAttribute(MyNode,"id")){StrID = MyNode.Attributes["id"].Value;StrValue = MyNode.Attributes["value"].Value;if (StrValue.IsNullOrEmpty()){Continue = false;StrFalse = $"{StrID}为空";break;}else{//替换公式中的字符串,ID和值StrFormula = StrFormula.Replace(StrID, StrValue);}}else{Continue = false;}}if (Continue){//进行计算获得结果fSum = GetFormulaResult(StrFormula);}}else{//没有formula属性,计算结果等于所有子节点的和。foreach (XmlNode MyNode in CalculateNode.ChildNodes){StrValue = MyNode.Attributes["value"].Value;if (StrValue.IsNullOrEmpty()){Continue = false;StrFalse = MyNode.Name +"的值为空";break;}else{fSum += Convert.ToSingle(StrValue);}}}if (Continue){//修改本节点的Value属性CalculateNode.Attributes["value"].Value = fSum.ToString();}CalculateNode = CalculateNode.ParentNode;//if (CalculateNode.NodeType == XmlNodeType.Document)if(CalculateNode==null){StrFalse = "没有了父节点";Continue = false;}//是否继续计算if (Continue){Autocalculate(CalculateNode);}else{textBox1.Text += StrFalse+Environment.NewLine;}}}
这个问题看似简单,实际上也的确不难,就是有一点麻烦,需要耐心去解决细节问题。
相关文章:

C#完成XML文档节点的自动计算功能
一个项目涉及XML文档中节点的自动计算,就是XML文档的每个节点都参与运算,要求: ⑴如果节点有计算公式则按照计算公式进行; ⑵如果节点没有计算公式则该节点的值就是所有子节点的值之和; ⑶节点有4种类型,计…...

体验SOLIDWORKS旋转反侧切除增强 硕迪科技
大家在设计中经常使用的旋转切除命令在solidworks2024版本中迎来了新的增强,添加了旋转反侧切除选项。在设计过程中不必修改复杂的草图即可切除掉我们不需要的部分。使设计工作更加方便快捷。 打开零部件后,点击键盘上的S键并输入旋转切除以搜索该命令&a…...
分布式ID系统设计(3)
分布式ID系统设计第三集 id-service-SnowFlake方案 第二集说了id-service-Segment-DB可以生成趋势递增的ID,但是ID号是可以计算的。不太适用于一些订单ID生成的场景。因为存在数据暴露的风险 比如我可以对比两天的订单ID号来大致计算出公司一天的订单量。这个有点危险。 所以…...
工作备忘录【微信】
这工作备忘录【微信】里写自定义目录标题 unionid获取用户基本信息无 unionid EasyWeChat"overtrue/wechat": "^4.6" 与 "overtrue/wechat": "~3.1" 使用方式有异 unionid 微信 unionid 有关备忘录 获取用户基本信息无 unionid htt…...

Window下SRS服务器的搭建
---2023.7.23 准备材料 srs下载:GitHub - ossrs/srs at 3.0release 目前srs release到5.0版本。 srs官方文档:Introduction | SRS (ossrs.net) Docker下载:Download Docker Desktop | Docker 进入docker官网选择window版本直接下载。由…...

Canvas绘制简易雨滴碰撞效果
实现会动的图形,向下播放多张静态的图片。一秒内要大于屏幕刷新的帧数(60) 也就是每隔1/60s执行一次函数在每次绘制的正方形上添加一个背景色为白色蒙板。 效果图 源代码 <!DOCTYPE html> <html lang"en"><head><meta charset"…...
【五、http】go的http的信息提交
一、post提交的几种 form表单json文件 1、提交表单 //http的postfunc requstPost(){params : make(url.Values)params.Set("name", "kaiyue")params.Set("age", "18")formDataStr : []byte(params.Encode())formDataByte : bytes.N…...

第六讲:VBA与ACCESS的ADO连接中,所涉及的对象
《VBA数据库解决方案》教程(10090845)是我推出的第二套教程,目前已经是第二版修订了。这套教程定位于中级,是学完字典后的另一个专题讲解。数据库是数据处理的利器,教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法和实…...

【计算机网络】同源策略及跨域问题
1. 同源策略 同源策略是一套浏览器安全机制,当一个源的文档和脚本,与另一个源的资源进行通信时,同源策略就会对这个通信做出不同程度的限制。 同源策略对 同源资源 放行,对 异源资源 限制。因此限制造成的开发问题,称…...

uniapp在APP端使用swiper进行页面不卡顿滑动
uniapp在APP端使用swiper进行页面会卡顿,主要是渲染的数据有点多,这里只渲染三个数据就不好那么卡顿了,每次滑动后更新数据 <view><swiper change"changePoint" circular :disable-touch"disableTouch"><…...
遗憾
《遗憾》 文/罗光记 岁月匆匆如梦过, 回首往事泪沾裳。 遗憾犹存心深处, 青春岁月已成伤。...
hustoj 平台
1.大部分功能和选项的开关和参数调整都在配置文件中,安装后几个重要配置文件的位置如下: /home/judge/etc/judge.conf #判题judged/judge_client /home/judge/src/web/include/db_info.inc.php #Web debian-sys-maint gdfNPYOdITxtDEK1 修改MySQl管…...

如何使用Scrapy提取和处理数据
目录 一、安装和设置Scrapy 二、创建爬虫 三、提取数据 四、处理数据 五、存储数据 六、进阶操作 七、注意事项 总结 Scrapy是一个强大且灵活的Python库,用于创建网页爬虫,提取和处理数据。本文将为您深入讲解如何使用Scrapy进行数据处理&#x…...
拟合与过拟合
拟合跟过拟合 过拟合:将泛化误差分解为偏差跟方差 偏差:学习者不断学习相同错误事物的倾向 方差:学习随机信号而不考虑真实情况的趋势 过拟合:所建的机器学习模型或者深度学习模型在训练样本中表现得过于优越,导致测试数据集表现…...
科学化决策数据分析,先从量化开始
在当今信息爆炸的时代,数据已经成为我们生活和工作中不可或缺的一部分。在各行各业,人们越来越依赖数据来指导决策和优化业务。在这个背景下,量化成为了一种重要的方法论,通过收集、分析和解读数据,为我们提供了更准确…...

使用Docker搭建一个“一主两从”的 Redis 集群(超详细步骤)
目录 1、Redis 单机版安装1.1 拉取 Redis1.2 创建数据卷目录1.3 修改 redis.conf1.4 启动 Redis 容器1.5 进入容器连接 Redis 2、Redis 一主两从集群搭建2.1 复制三份 redis.conf2.2 启动 master2.3 启动 两个redis slave2.4 三者关系查看2.5 数据测试 1、Redis 单机版安装 1.…...

阿里云盘第三方linux客户端“小白羊”云盘“Aria2本地连接已断开”错误的解决方法
简介 随着数据的不断增长,我们需要更大的存储空间来保存我们的信息。阿里云盘是阿里巴巴推出的一款云存储服务,它提供了大量可扩展的存储空间。然而,阿里云盘官方没有提供Linux操作系统的客户端。 在这种情况下,“小白羊”云盘…...

Linux flock和fcntl函数详解
文章目录 flock函数描述返回值和错误码笔记 fcntl函数描述复制文件描述符文件描述标志文件状态标志 咨询锁强制锁管理信号租赁文件和目录变更通知改变管道容量 返回值错误备注遗留问题 flock函数 主要功能是在已打开的文件应用或者删除共享锁或者独占锁。sys/file.h声明了这个…...
React 组件点击事件
点击事件 点击事件方式1、传统类方法(不推荐)2、传统类方法 16.3.0 - 自动绑定(不推荐)3、箭头函数3.1、类组件3.2、函数组件3.3、内联箭头函数 4、useState Hook 点击事件方式 1、传统类方法(不推荐) 当…...

Windows 下编译 TensorFlow 2.9.1 CC库
参考 Intel 的 tensorflow 编译指导,不过项目还是可以用 TF原本的,不是一定要选择Intel 的TF版本。 安装 MSVC 2019 安装 Intel OneDNN OneMKL 似乎也可以不安装 ( & ) https://www.intel.cn/content/www/cn/zh/developer/articles/tool/one…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...