XmlParser.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Windows.Forms;
  6. using System.Xml;
  7. using System.Xml.Linq;
  8. public static class SymbolParser
  9. {
  10. public static List<TypeBase> ParseTypeList(string filePath)
  11. {
  12. XmlDocument doc = new XmlDocument();
  13. doc.Load(filePath);
  14. // 1. 动态获取命名空间
  15. string namespaceUri = doc.DocumentElement?.NamespaceURI ?? "";
  16. // 2. 创建命名空间管理器
  17. XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
  18. nsmgr.AddNamespace("ns", namespaceUri);
  19. var typeList = doc.SelectNodes("//ns:TypeList/*", nsmgr);
  20. if (typeList == null)
  21. {
  22. throw new Exception("无法找到 TypeList 节点,请检查XML结构或命名空间。");
  23. }
  24. List<TypeBase> types = new List<TypeBase>();
  25. // 解析类型定义
  26. foreach (XmlNode typeNode in typeList)
  27. {
  28. var type= ParseTypeDefinition(typeNode, nsmgr);
  29. if(type!=null)
  30. { types.Add(type); }
  31. }
  32. return types;
  33. }
  34. private static TypeBase ParseTypeDefinition(XmlNode node, XmlNamespaceManager nsmgr)
  35. {
  36. string typeName = GetAttribute(node, "name");
  37. if (typeName == null)
  38. return null;
  39. switch (node.Name)
  40. {
  41. case "TypeSimple":
  42. var typeSimple = new TypeSimple()
  43. {
  44. Name = GetAttribute(node, "name"),
  45. Size = int.Parse(GetAttribute(node, "size")),
  46. SwapSize = int.Parse(GetAttribute(node, "swapsize")),
  47. TypeClass = GetAttribute(node, "typeclass"),
  48. IecName = GetAttribute(node, "iecname"),
  49. BitOffset = int.Parse(string.IsNullOrEmpty(GetAttribute(node, "bitoffset")) ? "0" : GetAttribute(node, "bitoffset"))
  50. };
  51. return typeSimple;
  52. case "TypeArray":
  53. var typeArray = new TypeArray()
  54. {
  55. Name = GetAttribute(node, "name"),
  56. Size = int.Parse(GetAttribute(node, "size")),
  57. NativeSize = int.Parse(GetAttribute(node, "nativesize")),
  58. TypeClass = GetAttribute(node, "typeclass"),
  59. IecName = GetAttribute(node, "iecname"),
  60. BaseType = GetAttribute(node, "basetype")
  61. };
  62. var dimensions = GetArrayDimensions(node, nsmgr);
  63. typeArray.Rank = dimensions.Count;
  64. if (typeArray.Rank > 0)
  65. {
  66. typeArray.MinRange = new int[typeArray.Rank];
  67. typeArray.MaxRange = new int[typeArray.Rank];
  68. for (int i = 0; i < typeArray.Rank; i++)
  69. {
  70. typeArray.MinRange[i] = dimensions[i].Min;
  71. typeArray.MaxRange[i] = dimensions[i].Max;
  72. }
  73. }
  74. return typeArray;
  75. case "TypeUserDef":
  76. var typeUserDef = new TypeUserDef()
  77. {
  78. Name = GetAttribute(node, "name"),
  79. Size = int.Parse(GetAttribute(node, "size")),
  80. NativeSize = int.Parse(GetAttribute(node, "nativesize")),
  81. TypeClass = GetAttribute(node, "typeclass"),
  82. PouClass = GetAttribute(node, "pouclass"),
  83. IecName = GetAttribute(node, "iecname"),
  84. };
  85. typeUserDef.UserDefElements = GetUserDefElement(node, nsmgr);
  86. return typeUserDef;
  87. default:
  88. return null;
  89. }
  90. }
  91. public static List<(int Min, int Max)> GetArrayDimensions(XmlNode arrayNode, XmlNamespaceManager nsmgr)
  92. {
  93. var result = new List<(int Min, int Max)>();
  94. XmlNodeList dimNodes = arrayNode.SelectNodes("ns:ArrayDim", nsmgr);
  95. if (dimNodes == null) return result;
  96. foreach (XmlNode dim in dimNodes)
  97. {
  98. if (int.TryParse(dim.Attributes["minrange"]?.Value, out int min) &&
  99. int.TryParse(dim.Attributes["maxrange"]?.Value, out int max))
  100. {
  101. result.Add((min, max));
  102. }
  103. }
  104. return result;
  105. }
  106. public static List<UserDefElement> GetUserDefElement(XmlNode arrayNode, XmlNamespaceManager nsmgr)
  107. {
  108. var result = new List<UserDefElement>();
  109. XmlNodeList dimNodes = arrayNode.SelectNodes("ns:UserDefElement", nsmgr);
  110. if (dimNodes == null) return result;
  111. foreach (XmlNode dim in dimNodes)
  112. {
  113. var element = new UserDefElement
  114. {
  115. IecName = dim.Attributes["iecname"]?.Value,
  116. Type = dim.Attributes["type"].Value,
  117. //ByteOffset = uint.Parse(dim.Attributes["byteoffset"]?.Value),
  118. VarType = dim.Attributes["vartype"]?.Value,
  119. Access = dim.Attributes["access"]?.Value
  120. };
  121. //if(element.Type!=GetAttribute(arrayNode, "name"))//如果一个类型的name和子类型的type相同,则不能添加进去,否则在添加Node时会出现一直递归,堆栈溢出
  122. result.Add(element);
  123. }
  124. return result;
  125. }
  126. public static XmlVariable ParseNode(string filePath, List<TypeBase> types)
  127. {
  128. XmlDocument doc = new XmlDocument();
  129. doc.Load(filePath);
  130. // 1. 动态获取命名空间
  131. string namespaceUri = doc.DocumentElement?.NamespaceURI ?? "";
  132. // 2. 创建命名空间管理器
  133. XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
  134. //nsmgr.AddNamespace("ns", "http://www.3s-software.com/schemas/Symbolconfiguration.xsd");
  135. nsmgr.AddNamespace("ns", namespaceUri);
  136. // 使用命名空间前缀进行查询
  137. XmlNode rootNode = doc.SelectSingleNode("//ns:NodeList/ns:Node", nsmgr);
  138. if (rootNode == null)
  139. {
  140. throw new Exception("无法找到 NodeList/Node 节点,请检查XML结构或命名空间。");
  141. }
  142. //var varNode= ParseNode(rootNode);
  143. var varNode= ParseAllElementNode(rootNode, nsmgr, types);
  144. return varNode;
  145. }
  146. private static XmlVariable ParseAllElementNode(XmlNode xmlNode, XmlNamespaceManager nsmgr, List<TypeBase> types)
  147. {
  148. var varNode = GetNodeValue(xmlNode, nsmgr);
  149. if (!varNode.IsLeaf)
  150. {
  151. foreach (XmlNode xmlChild in xmlNode.ChildNodes)
  152. {
  153. if (xmlChild.Name == "Node")
  154. {
  155. string strXmlChildNodeType = GetAttribute(xmlChild, "type");
  156. if (string.IsNullOrEmpty(strXmlChildNodeType))//不是具体的数据,有子Node
  157. varNode.Children.Add(ParseAllElementNode(xmlChild, nsmgr, types));
  158. else
  159. {
  160. var xmlChildNodeType = types.First(t => t.Name == strXmlChildNodeType);//找到具体是之前搜索到的具体哪个类型
  161. if (xmlChildNodeType is TypeSimple)//简单数据类型,直接添加
  162. {
  163. var subNode = GetNodeValue(xmlChild, nsmgr);
  164. varNode.Children.Add(subNode);
  165. }
  166. else if (xmlChildNodeType is TypeArray typeArray)//数组类型
  167. {
  168. var subNode = GetNodeValue(xmlChild, nsmgr);
  169. subNode.IsLeaf = false;
  170. varNode.Children.Add(subNode);//添加数组名本身,然后再添加其下面的元素
  171. int count = 1;
  172. for (int i = 0; i < typeArray.Rank; i++)
  173. {
  174. count *= (typeArray.MaxRange[i] + 1 - typeArray.MinRange[i]);
  175. }
  176. int[] cIndex = new int[typeArray.Rank];
  177. for (int i = 0; i < count; i++)
  178. {
  179. string name = IndicesToString(GetNDElement(typeArray.Rank, typeArray.MinRange, typeArray.MaxRange, i));
  180. subNode.Children.Add(ParseArrayAndUserDefElement(name, typeArray.BaseType, types));
  181. }
  182. }
  183. else if (xmlChildNodeType is TypeUserDef typeUserDef)//结构体类型
  184. {
  185. var subNode = GetNodeValue(xmlChild, nsmgr);
  186. subNode.IsLeaf = false;
  187. varNode.Children.Add(subNode);//添加结构体名本身,然后再添加其下面的元素
  188. foreach (var userDefElement in typeUserDef.UserDefElements)
  189. {
  190. subNode.Children.Add(ParseArrayAndUserDefElement(userDefElement.IecName, userDefElement.Type, types));
  191. }
  192. }
  193. }
  194. }
  195. }
  196. }
  197. return varNode;
  198. }
  199. private static int[] GetNDElement(int N, int[] MinRange, int[] MaxRange, int linearIndex)
  200. {
  201. // 1. 计算每个维度的长度
  202. int[] lengths = new int[N];
  203. for (int i = 0; i < N; i++)
  204. {
  205. lengths[i] = MaxRange[i] - MinRange[i] + 1;
  206. }
  207. int totalElements = 1;
  208. for (int i = 0; i < N; i++)
  209. {
  210. totalElements *= lengths[i];
  211. }
  212. if (linearIndex < 0 || linearIndex >= totalElements)
  213. {
  214. throw new IndexOutOfRangeException("线性索引超出数组范围");
  215. }
  216. // 2. 计算每个维度的步长(Stride)
  217. int[] strides = new int[N];
  218. strides[N - 1] = 1;
  219. for (int i = N - 2; i >= 0; i--)
  220. {
  221. strides[i] = strides[i + 1] * lengths[i + 1];
  222. }
  223. // 3. 还原每个维度的索引(加上偏移 MinRange[i])
  224. int[] result = new int[N];
  225. for (int i = 0; i < N; i++)
  226. {
  227. int index = (linearIndex / strides[i]) % lengths[i];
  228. result[i] = MinRange[i] + index;
  229. }
  230. return result;
  231. }
  232. private static string IndicesToString(int[] indices)
  233. {
  234. if (indices == null || indices.Length == 0)
  235. return "[]";
  236. return "[" + string.Join(",", indices) + "]";
  237. }
  238. private static XmlVariable ParseArrayAndUserDefElement(string name, string baseType, List<TypeBase> types)
  239. {
  240. var type = types.First(t => t.Name == baseType);//找到数组的基本类型是哪种类型(也即素组的元素是什么类型)
  241. if (type is TypeSimple typeSimple)//简单数据类型,直接添加
  242. {
  243. var subNode = new XmlVariable()
  244. {
  245. Name = name,
  246. Type = typeSimple.Name,
  247. IsLeaf = true,
  248. };
  249. return subNode;
  250. }
  251. else if (type is TypeArray typeArray)
  252. {
  253. var subNode = new XmlVariable();
  254. subNode.Name = name;
  255. int count = 1;
  256. for (int i = 0; i < typeArray.Rank; i++)
  257. {
  258. count *= (typeArray.MaxRange[i] + 1 - typeArray.MinRange[i]);
  259. }
  260. int[] cIndex = new int[typeArray.Rank];
  261. for (int i = 0; i < count; i++)
  262. {
  263. string n = IndicesToString(GetNDElement(typeArray.Rank, typeArray.MinRange, typeArray.MaxRange, i));
  264. subNode.Children.Add(ParseArrayAndUserDefElement(n, typeArray.BaseType, types));
  265. }
  266. return subNode;//添加数组名本身
  267. }
  268. else if (type is TypeUserDef typeUserDef)//结构体类型
  269. {
  270. var subNode = new XmlVariable();
  271. subNode.Name = name;
  272. foreach (var userDefElement in typeUserDef.UserDefElements)
  273. {
  274. subNode.Children.Add(ParseArrayAndUserDefElement(userDefElement.IecName, userDefElement.Type, types));
  275. }
  276. return subNode;
  277. }
  278. return null;
  279. }
  280. static XmlVariable GetNodeValue(XmlNode xmlNode, XmlNamespaceManager nsmgr)
  281. {
  282. var node = new XmlVariable
  283. {
  284. Name = GetAttribute(xmlNode, "name"),
  285. Type = GetAttribute(xmlNode, "type"),
  286. Access = GetAttribute(xmlNode, "access"),
  287. Comment= xmlNode.SelectSingleNode("ns:Comment", nsmgr)?.InnerText.Trim() ?? null,
  288. IsLeaf = xmlNode.SelectNodes("ns:Node", nsmgr).Count == 0
  289. };
  290. return node;
  291. }
  292. private static string GetAttribute(XmlNode node, string attrName)
  293. {
  294. XmlAttribute attr = node.Attributes?[attrName];
  295. return attr?.Value ?? string.Empty;
  296. }
  297. }