// ********************************************************************************************************** // XmlParser.cs // 6/6/2022 // NGI - Next Generation Interceptor // // Contract No. HQ0856-21-C-0003/1022000209 // // THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S. // INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS. // // RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON // COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. // DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON // COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED // TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF // RAYTHEON COMPANY. // // UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. // // DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M, // NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006, // INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3, // DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3, // SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4, // INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION. // // CONTROLLED BY: MISSILE DEFENSE AGENCY // CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE // CUI CATEGORY: CTI // DISTRIBUTION/DISSEMINATION CONTROL: F // POC: Alex Kravchenko (1118268) // ********************************************************************************************************** using System; using System.Collections.Generic; using System.Xml; using System.Xml.XPath; namespace Raytheon.Common.Coe { public class XmlParser { public class CommonXmlElements { public List fileIncludes = new List(); public string projectName = string.Empty; public string classification = string.Empty; public string fileHeader = string.Empty; } public class XmlConstant { public string nameSpace = string.Empty; public List comments = new List(); public string name = string.Empty; public string value = string.Empty; public string description = string.Empty; } public class XmlEnumeration { public string nameSpace = string.Empty; public string description = string.Empty; public List comments = new List(); //public Dictionary enumKeyAndValuePairs = new Dictionary(); public List enumItems = new List(); } public class XmlEnumItem { public List comments = new List(); public string name = string.Empty; public string value = string.Empty; } public class XmlStructure { public string nameSpace = string.Empty; public string name = string.Empty; public List comments = new List(); public List structDataItems = new List(); } public class XmlStructureItem { public string nameSpace = string.Empty; public List comments = new List(); public string name = string.Empty; public string description = string.Empty; public string type = string.Empty; public string defaultVal = string.Empty; public string arrayLength = string.Empty; public string bits = string.Empty; } public class XmlMbitMessage { public string nameSpace = string.Empty; public string name = string.Empty; public string label = string.Empty; public string instruLabel = string.Empty; public string description = string.Empty; public List comments = new List(); public List dataItems = new List(); } ///=================================================================================== /// XmlParser.getCommonElementsFromXml ///=================================================================================== /// /// Each XML file contains common elements such as header, includes, etc /// We want to parse it and save the common elements /// /// navigator object that points to the current XML node we are at /// data structure that stores all the common elements of each XML file ///=================================================================================== public static bool GetCommonElementsFromXml(XPathNavigator nav, CommonXmlElements commonElements) { bool isSuccessful = true; if (string.Equals(nav.Name, "include", StringComparison.OrdinalIgnoreCase)) { if (nav.MoveToFirstChild()) { GetFileIncludes(nav, commonElements); nav.MoveToParent(); } } else if (string.Equals(nav.Name, "project", StringComparison.OrdinalIgnoreCase)) { commonElements.projectName = nav.Value.Trim(); } else if (string.Equals(nav.Name, "classification", StringComparison.OrdinalIgnoreCase)) { commonElements.classification = nav.Value.Trim(); } else if (string.Equals(nav.Name, "fileheader", StringComparison.OrdinalIgnoreCase)) { commonElements.fileHeader = nav.Value; } else if (string.Equals(nav.Name, "packing", StringComparison.OrdinalIgnoreCase)) { } else isSuccessful = false; return isSuccessful; } ///=================================================================================== /// XmlParser.getFileIncludes ///=================================================================================== /// /// Get the file includes specify by the XML file /// /// navigator object that points to the current XML node we are at /// data structure that stores all the common elements of each XML file ///=================================================================================== public static void GetFileIncludes(XPathNavigator nav, CommonXmlElements commonElements) { do { commonElements.fileIncludes.Add(nav.Value.Trim()); } while (nav.MoveToNext()); } ///=================================================================================== /// XmlParser.getConstant ///=================================================================================== /// /// Parse the symbolic constant defined by the XML /// /// navigator object that points to the current XML node we are at /// the XML file name that defines this constant /// the Dictionary that stores this constant information /// the Dictioanry that stores duplicate constant definitions ///=================================================================================== public static void GetConstant(XPathNavigator nav, string nameSpace, List xmlConstants, Dictionary> duplicateConstants) { XmlConstant tempXmlConstant = new XmlConstant(); if (nav.MoveToFirstChild()) { do { if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase)) { tempXmlConstant.name = nav.Value.Trim(); } else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase)) { tempXmlConstant.description = nav.Value.Trim(); } else if (string.Equals(nav.Name, "value", StringComparison.OrdinalIgnoreCase)) { tempXmlConstant.value = nav.Value.Trim(); } else if (nav.Name.Length > 0) { throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } while (nav.MoveToNext()); nav.MoveToParent(); } if (tempXmlConstant.name.Length > 0) { tempXmlConstant.nameSpace = nameSpace; xmlConstants.Add(tempXmlConstant); } else { throw new XmlParsingException("Child element \"name\" not found for node \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } ///=================================================================================== /// XmlParser.getEnumeration ///=================================================================================== /// /// Parse the enumeration type defined by the XML /// /// navigator object that points to the current XML node we are at /// the XML file name that defines this enumeration type /// data structure that stores enumeration data /// the Dictioanry that stores duplicate enumeration type ///=================================================================================== public static void GetEnumeration(XPathNavigator nav, string nameSpace, Dictionary xmlEnums, Dictionary> duplicateEnums) { string enumTypeName = string.Empty; string tempEnumTypeName = "temp"; Dictionary tempXmlEnums = new Dictionary { [tempEnumTypeName] = new XmlEnumeration() }; tempXmlEnums[tempEnumTypeName].nameSpace = nameSpace; if (nav.MoveToFirstChild()) { do { if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase)) { enumTypeName = nav.Value.Trim(); } else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase)) { tempXmlEnums[tempEnumTypeName].description = nav.Value.Trim(); } else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase)) { tempXmlEnums[tempEnumTypeName].comments.Add(nav.Value.Trim()); } else if (string.Equals(nav.Name, "item", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "enum_item", StringComparison.OrdinalIgnoreCase)) { if (nav.MoveToFirstChild()) { GetEnumItem(nav, tempXmlEnums[tempEnumTypeName]); nav.MoveToParent(); } } else if (nav.Name.Length > 0) { throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } while (nav.MoveToNext()); nav.MoveToParent(); } if (enumTypeName.Length > 0) { if (xmlEnums.ContainsKey(enumTypeName)) { // save file name the defines this message that is a duplicate if (!duplicateEnums.ContainsKey(enumTypeName)) { duplicateEnums[enumTypeName] = new List(); } int index2 = duplicateEnums[enumTypeName].FindIndex(f => string.Equals(f, nameSpace + ".xml", StringComparison.OrdinalIgnoreCase)); if (index2 < 0) duplicateEnums[enumTypeName].Add(nameSpace + ".xml"); // see if the official structure is already in the duplicate list int index3 = duplicateEnums[enumTypeName].FindIndex(f => string.Equals(f, xmlEnums[enumTypeName].nameSpace + ".xml", StringComparison.OrdinalIgnoreCase)); // if the official structure is not in the duplicate list, we want to save it in the duplicate list if (index3 < 0) { duplicateEnums[enumTypeName].Add(xmlEnums[enumTypeName].nameSpace + ".xml"); } } else { xmlEnums[enumTypeName] = tempXmlEnums[tempEnumTypeName]; } } else { throw new XmlParsingException("Child element \"name\" not found for node \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } ///=================================================================================== /// XmlParser.getEnumItem ///=================================================================================== /// /// Parse each enumerated key/value pair /// /// navigator object that points to the current XML node we are at /// data structure that stores enumeration data ///=================================================================================== public static void GetEnumItem(XPathNavigator nav, XmlEnumeration xmlEnum) { XmlEnumItem enumItem = new XmlEnumItem(); do { if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "item_name", StringComparison.OrdinalIgnoreCase)) { enumItem.name = nav.Value.Trim(); } else if (string.Equals(nav.Name, "value", StringComparison.OrdinalIgnoreCase)) { enumItem.value = nav.Value.Trim(); } else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase)) { enumItem.comments.Add(nav.Value.Trim()); } else if (nav.Name.Length > 0) { throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } while (nav.MoveToNext()); xmlEnum.enumItems.Add(enumItem); } public static void GetStructure(XPathNavigator nav, string nameSpace, Dictionary xmlStructures, List comments, Dictionary> duplicateStructures) { string structureTypeName = string.Empty; string tempStructureTypeName = "temp"; Dictionary tempXmlStructures = new Dictionary(); tempXmlStructures[tempStructureTypeName] = new XmlStructure(); tempXmlStructures[tempStructureTypeName].nameSpace = nameSpace; if (nav.MoveToFirstChild()) { do { if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase)) { structureTypeName = nav.Value.Trim(); if (comments != null && comments.Count > 0) { tempXmlStructures[tempStructureTypeName].comments = new List(comments); } } else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase)) { tempXmlStructures[tempStructureTypeName].comments.Add(nav.Value.Trim()); } else if (string.Equals(nav.Name, "item", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "struct_item", StringComparison.OrdinalIgnoreCase)) { if (nav.MoveToFirstChild()) { XmlStructureItem structureItem = new XmlStructureItem(); structureItem.nameSpace = nameSpace; GetStructureItem(nav, structureItem); tempXmlStructures[tempStructureTypeName].structDataItems.Add(structureItem); nav.MoveToParent(); } } else if (nav.Name.Length > 0) { throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } while (nav.MoveToNext()); nav.MoveToParent(); } if (structureTypeName.Length > 0) { if (xmlStructures.ContainsKey(structureTypeName)) { // save file name the defines this message that is a duplicate if (!duplicateStructures.ContainsKey(structureTypeName)) { duplicateStructures[structureTypeName] = new List(); } int index2 = duplicateStructures[structureTypeName].FindIndex(f => string.Equals(f, nameSpace + ".xml", StringComparison.OrdinalIgnoreCase)); if (index2 < 0) duplicateStructures[structureTypeName].Add(nameSpace + ".xml"); // see if the official structure is already in the duplicate list int index3 = duplicateStructures[structureTypeName].FindIndex(f => string.Equals(f, xmlStructures[structureTypeName].nameSpace + ".xml", StringComparison.OrdinalIgnoreCase)); // if the official structure is not in the duplicate list, we want to save it in the duplicate list if (index3 < 0) { duplicateStructures[structureTypeName].Add(xmlStructures[structureTypeName].nameSpace + ".xml"); } } else { xmlStructures[structureTypeName] = tempXmlStructures[tempStructureTypeName]; xmlStructures[structureTypeName].name = structureTypeName; } } else { throw new XmlParsingException("Child element \"name\" not found for node \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } ///=================================================================================== /// XmlParser.getStructureItem ///=================================================================================== /// /// Parse the data structure defined by the XML /// /// navigator object that points to the current XML node we are at /// data structure that stores all data members of the data structure ///=================================================================================== public static void GetStructureItem(XPathNavigator nav, XmlStructureItem xmlStructureItem) { do { if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "item_name", StringComparison.OrdinalIgnoreCase)) { xmlStructureItem.name = nav.Value.Trim(); } else if (string.Equals(nav.Name, "type", StringComparison.OrdinalIgnoreCase)) { xmlStructureItem.type = nav.Value.Trim(); } else if (string.Equals(nav.Name, "default", StringComparison.OrdinalIgnoreCase)) { xmlStructureItem.defaultVal = nav.Value.Trim(); } else if (string.Equals(nav.Name, "arrayLength", StringComparison.OrdinalIgnoreCase)) { xmlStructureItem.arrayLength = nav.Value.Trim(); } else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase)) { xmlStructureItem.comments.Add(nav.Value.Trim()); } else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase)) { xmlStructureItem.description = nav.Value.Trim(); } else if (string.Equals(nav.Name, "bits", StringComparison.OrdinalIgnoreCase)) { xmlStructureItem.bits = nav.Value.Trim(); } else if (nav.Name.Length > 0) { throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } while (nav.MoveToNext()); } ///=================================================================================== /// XmlParser.getMbitMessage ///=================================================================================== /// /// Parse the message defined by the XML /// /// navigator object that points to the current XML node we are at /// the XML file name that defines this message /// list of messages defined by XML /// the Dictioanry that stores duplicate messages ///=================================================================================== public static void GetMbitMessage(XPathNavigator nav, string nameSpace, List mbitMessages, Dictionary> duplicateMbitMessages) { var mbitMsg = new XmlMbitMessage() { nameSpace = nameSpace }; if (nav.MoveToFirstChild()) { do { if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase)) { mbitMsg.name = nav.Value.Trim(); } else if (string.Equals(nav.Name, "label", StringComparison.OrdinalIgnoreCase)) { mbitMsg.label = nav.Value.Trim(); } else if (string.Equals(nav.Name, "instrulabel", StringComparison.OrdinalIgnoreCase)) { mbitMsg.instruLabel = nav.Value.Trim(); } else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase)) { mbitMsg.description = nav.Value.Trim(); } else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase)) { mbitMsg.comments.Add(nav.Value.Trim()); } else if (string.Equals(nav.Name, "item", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "struct_item", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "msg_item", StringComparison.OrdinalIgnoreCase)) { if (nav.MoveToFirstChild()) { XmlStructureItem structureItem = new XmlStructureItem() { nameSpace = nameSpace }; GetStructureItem(nav, structureItem); mbitMsg.dataItems.Add(structureItem); nav.MoveToParent(); } } else if (nav.Name.Length > 0) { throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString()); } } while (nav.MoveToNext()); nav.MoveToParent(); int index = mbitMessages.FindIndex(f => string.Equals(f.name, mbitMsg.name, StringComparison.OrdinalIgnoreCase)); if (index >= 0) { // save file name the defines this message that is a duplicate if (!duplicateMbitMessages.ContainsKey(mbitMsg.name)) { duplicateMbitMessages[mbitMsg.name] = new List(); } int index3 = duplicateMbitMessages[mbitMsg.name].FindIndex(f => string.Equals(f, nameSpace + ".xml", StringComparison.OrdinalIgnoreCase)); if (index3 < 0) duplicateMbitMessages[mbitMsg.name].Add(nameSpace + ".xml"); // see if the official message is already in the duplicate list int index2 = duplicateMbitMessages[mbitMsg.name].FindIndex(f => string.Equals(f, mbitMessages[index].nameSpace + ".xml", StringComparison.OrdinalIgnoreCase)); // if the official message is not in the duplicate list, we want to save it in the duplicate list if (index2 < 0) { duplicateMbitMessages[mbitMsg.name].Add(mbitMessages[index].nameSpace + ".xml"); } // the existing message is defined in an xml file other than MsgsMc.xml. At this time, we want the messages in MsgsMc.xml to take precedence over other xml files. // Why is the same message being defined in multiple xml files? if (!string.Equals(mbitMessages[index].nameSpace, "msgsmc", StringComparison.OrdinalIgnoreCase) && string.Equals(nameSpace, "msgsmc", StringComparison.OrdinalIgnoreCase)) { mbitMessages.RemoveAt(index); mbitMessages.Add(mbitMsg); } } else mbitMessages.Add(mbitMsg); } } } }