最近在做一个项目,需要获取NX装配结构信息,这里把代码分享给大家,希望对各位有帮助,注意以下几点:
1)代码获取了PART的属性、表达式等,因此一些细节可能需要您根据实际情况修改。
2)读写XML用的pugixml,需要您包含到工程中,接口使用的是宽字符模式,所以在pugiconfig.hpp需要打开宽字符开关。
题外话,本人用过的解析XML的库有微软MSXML、markup、tinyxml、pugixml等,其中pugixml是最好用的,强烈推荐给大家,下载地址:pugixml。
3)代码功能是传入一个装配part,生成一个包含装配信息的xml。
4)代码采用ug open c实现,如果您需要在C#、Java等其他工程中调用,可将其包装成独立的exe,采用后台方式调用。
5)如果您不需要生成XML,可不生成,直接使用其内存对象即可。
6)该代码只是抛砖引玉,仅供参考。
VS后台传参如下:
由于装配结构嵌套可能非常多,生成的xml结构大致如下:
代码如下:
1 // GenarateAssemblyInfo.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include "pugiconfig.hpp" 6 #include "pugixml.hpp" 7 #include <windows.h> 8 #include <stdlib.h> 9 #include <uf_attr.h> 10 #include <uf_modl.h> 11 #include <uf.h> 12 #include <uf_part.h> 13 #include <uf_assem.h> 14 #include <uf_ui_ugopen.h> 15 #include <map> 16 #include <vector> 17 #include <NXSigningResource.cpp> 18 using namespace std; 19 20 #ifndef SAFE_DELETE 21 #define SAFE_DELETE(p) do{ if(p){delete(p);(p)=NULL;} }while(0) 22 #endif 23 typedef struct _tagAssemblyInfo 24 { 25 _tagAssemblyInfo() 26 { 27 28 } 29 30 virtual ~_tagAssemblyInfo() 31 { 32 for (vector<_tagAssemblyInfo*>::iterator iter = children.begin(); iter != children.end(); ++iter) 33 { 34 SAFE_DELETE (*iter); 35 } 36 } 37 38 string path;//原型路径 39 map<string,map<string, string>> attr; //组,键值对 40 vector<_tagAssemblyInfo*> children;//子件 41 }AssemblyInfo; 42 43 44 string TCHAR2char( const TCHAR* STR) 45 { 46 string strchar; 47 if (!*STR) 48 { 49 return strchar; 50 } 51 52 //返回字符串的长度 53 int size = WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, FALSE); 54 55 //申请一个多字节的字符串变量 56 char* str = new char[sizeof(char) * size]; 57 58 //将STR转成str 59 WideCharToMultiByte(CP_ACP, 0, STR, -1, str, size, NULL, FALSE); 60 strchar = str; 61 delete (str); 62 63 return strchar; 64 } 65 66 TCHAR* char2TCAHR(const char* str) 67 { 68 int size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 69 70 TCHAR* retStr = new TCHAR[size * sizeof(TCHAR)]; 71 72 MultiByteToWideChar(CP_ACP, 0, str, -1, retStr, size); 73 74 return retStr; 75 } 76 77 void ReadExpression(AssemblyInfo* info,tag_t obj) 78 { 79 if ((NULL == info) || (NULL_TAG == obj)) 80 { 81 return ; 82 } 83 84 int number_of_exps = 0; 85 tag_t *exps = NULL; 86 UF_MODL_ask_exps_of_part(obj,&number_of_exps,&exps); 87 char *name = "Exp"; 88 for (int i = 0; i < number_of_exps; ++i) 89 { 90 tag_t expTag = *(exps + i); 91 char* expStr = NULL; 92 UF_MODL_ask_exp_tag_string(expTag, &expStr); 93 char* leftStr = NULL; 94 char* rightStr = NULL; 95 UF_MODL_dissect_exp_string(expStr, &leftStr, &rightStr,&expTag ); 96 info->attr[name].insert(make_pair(leftStr,rightStr)); 97 UF_free(expStr); 98 UF_free(leftStr); 99 UF_free(rightStr); 100 } 101 102 UF_free(exps); 103 } 104 105 106 void ReadAttribute(AssemblyInfo* info,tag_t obj) 107 { 108 if ((NULL == info) || (NULL_TAG == obj)) 109 { 110 return ; 111 } 112 113 char* category[] = {"ParameterExpression","ParameterMapping", "FxPartThumbnail"}; //组名称 114 115 for (int i = 0; i < _countof(category); ++i) 116 { 117 int num_attributes = 0; 118 logical has_attribute = false; 119 120 UF_ATTR_info_t attr_info = {0}; 121 UF_ATTR_init_user_attribute_info(&attr_info); 122 123 UF_ATTR_iterator_t query; 124 UF_ATTR_init_user_attribute_iterator(&query); 125 query.category = category[i]; 126 query.check_category = true; 127 query.type = UF_ATTR_string; 128 129 UF_ATTR_get_user_attribute(obj,&query,&attr_info,&has_attribute); 130 while (has_attribute) 131 { 132 info->attr[query.category].insert(make_pair(attr_info.title,attr_info.string_value)); 133 UF_ATTR_free_user_attribute_info_strings(&attr_info); 134 UF_ATTR_get_next_user_attribute(obj,&query,&attr_info,&has_attribute); 135 } 136 } 137 } 138 139 void GetAssembly(AssemblyInfo* info,tag_t occ) 140 { 141 if ((NULL == info) || (NULL_TAG == occ)) 142 { 143 return ; 144 } 145 tag_t prototype = UF_ASSEM_ask_prototype_of_occ(occ); 146 UF_PART_set_display_part(prototype); 147 148 //根据obj获取路径及属性 149 char part_fspec [MAX_FSPEC_SIZE+1] = {0}; 150 UF_PART_ask_part_name(prototype,part_fspec); 151 info->path = part_fspec; 152 153 //根据obj获取属性 154 ReadAttribute(info, prototype); 155 156 //根据obj获取表达式 157 ReadExpression(info, prototype); 158 159 //遍历子节点 160 tag_t *child_part_occs = NULL; 161 162 int number = UF_ASSEM_ask_part_occ_children(occ, &child_part_occs); 163 for (int i = 0; i < number; ++i) 164 { 165 AssemblyInfo* childInfo = new AssemblyInfo(); 166 info->children.push_back(childInfo); 167 GetAssembly(childInfo, *(child_part_occs + i)); 168 } 169 170 UF_free(child_part_occs); 171 } 172 173 void WriteNode(AssemblyInfo* info, pugi::xml_node parent) 174 { 175 if ((NULL == info) || (NULL == parent)) 176 { 177 return ; 178 } 179 _TCHAR* tmpStr = NULL; 180 pugi::xml_node assembly = parent.append_child(_T("assembly")); 181 tmpStr = char2TCAHR(info->path.c_str()); 182 assembly.append_attribute(_T("name")).set_value(tmpStr); 183 SAFE_DELETE(tmpStr); 184 pugi::xml_node attrs = assembly.append_child(_T("attrs")); 185 186 //属性 187 for (map<string,map<string, string>>::iterator iter = info->attr.begin(); iter != info->attr.end(); ++iter) 188 { 189 pugi::xml_node category = attrs.append_child(_T("category")); 190 tmpStr = char2TCAHR(iter->first.c_str()); 191 category.append_attribute(_T("name")).set_value(tmpStr); 192 SAFE_DELETE(tmpStr); 193 map<string, string>& attrsMap = iter->second; 194 for (map<string, string>::iterator iterAttr = attrsMap.begin(); iterAttr != attrsMap.end(); ++iterAttr) 195 { 196 pugi::xml_node attr = category.append_child(_T("attr")); 197 tmpStr = char2TCAHR(iterAttr->first.c_str()); 198 attr.append_attribute(_T("name")).set_value(tmpStr); 199 SAFE_DELETE(tmpStr); 200 tmpStr = char2TCAHR(iterAttr->second.c_str()); 201 attr.append_attribute(_T("value")).set_value(tmpStr); 202 SAFE_DELETE(tmpStr); 203 } 204 } 205 206 //子节点 207 pugi::xml_node children = assembly.append_child(_T("children")); 208 for (int i = 0; i < info->children.size(); ++i) 209 { 210 WriteNode(info->children[i], children); 211 } 212 } 213 214 void WriteXml(AssemblyInfo* info,_TCHAR* xmlFile) 215 { 216 if ((NULL == info) || (NULL == xmlFile)) 217 { 218 return ; 219 } 220 221 pugi::xml_document doc; 222 pugi::xml_node decNode = doc.append_child(pugi::node_declaration); 223 pugi::xml_attribute vAttr = decNode.append_attribute(_T("version")); 224 vAttr.set_value(_T("1.0")); 225 pugi::xml_attribute encAttr = decNode.append_attribute(_T("encoding")); 226 encAttr.set_value(_T("utf-8")); 227 228 pugi::xml_node root = doc.append_child(_T("root")); 229 WriteNode(info,root); 230 231 doc.save_file(xmlFile, _T(" "), pugi::format_indent, pugi::encoding_utf8); 232 } 233 234 int _tmain(int argc, _TCHAR* argv[]) 235 { 236 if (argc < 3) 237 { 238 return 0; 239 } 240 241 if (UF_initialize() != 0) 242 { 243 return 0; 244 } 245 246 const _TCHAR* prtPath = argv[1]; 247 TCHAR* xmlFile = argv[2]; 248 tag_t tag = NULL_TAG; 249 UF_PART_load_status_t status; 250 UF_PART_open(TCHAR2char(prtPath).c_str(),&tag,&status); 251 if (status.failed) 252 { 253 return 0; 254 } 255 256 tag_t occ = UF_ASSEM_ask_root_part_occ(tag); 257 AssemblyInfo* info = new AssemblyInfo(); 258 if (NULL == info) 259 { 260 return 0; 261 } 262 263 GetAssembly(info, occ); 264 WriteXml(info,xmlFile); 265 266 UF_terminate(); 267 delete info; 268 return 0; 269 }