]>
Commit | Line | Data |
---|---|---|
4234283c LG |
1 | ## @file\r |
2 | # This file is for converting package information data file to xml file.\r | |
3 | #\r | |
421ccda3 | 4 | # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r |
4234283c LG |
5 | #\r |
6 | # This program and the accompanying materials are licensed and made available \r | |
7 | # under the terms and conditions of the BSD License which accompanies this \r | |
8 | # distribution. The full text of the license may be found at \r | |
9 | # http://opensource.org/licenses/bsd-license.php\r | |
10 | #\r | |
11 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
12 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
13 | #\r | |
14 | \r | |
15 | '''\r | |
16 | IniToXml\r | |
17 | '''\r | |
18 | \r | |
19 | import os.path\r | |
20 | import re\r | |
21 | from time import strftime\r | |
22 | from time import localtime\r | |
23 | \r | |
24 | import Logger.Log as Logger\r | |
25 | from Logger.ToolError import UPT_INI_PARSE_ERROR\r | |
26 | from Logger.ToolError import FILE_NOT_FOUND\r | |
27 | from Library.Xml.XmlRoutines import CreateXmlElement\r | |
28 | from Library.DataType import TAB_VALUE_SPLIT\r | |
29 | from Library.DataType import TAB_EQUAL_SPLIT\r | |
30 | from Library.DataType import TAB_SECTION_START\r | |
31 | from Library.DataType import TAB_SECTION_END\r | |
32 | from Logger import StringTable as ST\r | |
33 | from Library.String import ConvertSpecialChar\r | |
34 | from Library.ParserValidate import IsValidPath\r | |
421ccda3 | 35 | from Library import GlobalData\r |
4234283c LG |
36 | \r |
37 | ## log error:\r | |
38 | #\r | |
39 | # @param error: error\r | |
40 | # @param File: File\r | |
41 | # @param Line: Line\r | |
42 | #\r | |
43 | def IniParseError(Error, File, Line):\r | |
44 | Logger.Error("UPT", UPT_INI_PARSE_ERROR, File=File,\r | |
45 | Line=Line, ExtraData=Error)\r | |
46 | \r | |
47 | ## __ValidatePath\r | |
48 | #\r | |
49 | # @param Path: Path to be checked\r | |
50 | #\r | |
51 | def __ValidatePath(Path, Root):\r | |
52 | Path = Path.strip()\r | |
53 | if os.path.isabs(Path) or not IsValidPath(Path, Root):\r | |
54 | return False, ST.ERR_FILELIST_LOCATION % (Root, Path)\r | |
55 | return True, ''\r | |
56 | \r | |
57 | ## ValidateMiscFile\r | |
58 | #\r | |
59 | # @param Filename: File to be checked\r | |
60 | #\r | |
61 | def ValidateMiscFile(Filename):\r | |
421ccda3 | 62 | Root = GlobalData.gWORKSPACE\r |
4234283c LG |
63 | return __ValidatePath(Filename, Root)\r |
64 | \r | |
65 | ## ValidateToolsFile\r | |
66 | #\r | |
67 | # @param Filename: File to be checked\r | |
68 | #\r | |
69 | def ValidateToolsFile(Filename):\r | |
70 | Valid, Cause = False, ''\r | |
71 | if not Valid and 'EDK_TOOLS_PATH' in os.environ:\r | |
72 | Valid, Cause = __ValidatePath(Filename, os.environ['EDK_TOOLS_PATH'])\r | |
421ccda3 HC |
73 | if not Valid:\r |
74 | Valid, Cause = __ValidatePath(Filename, GlobalData.gWORKSPACE)\r | |
4234283c LG |
75 | return Valid, Cause\r |
76 | \r | |
77 | ## ParseFileList\r | |
78 | #\r | |
79 | # @param Line: Line\r | |
80 | # @param Map: Map\r | |
81 | # @param CurrentKey: CurrentKey\r | |
82 | # @param PathFunc: Path validate function\r | |
83 | #\r | |
84 | def ParseFileList(Line, Map, CurrentKey, PathFunc):\r | |
85 | FileList = ["", {}]\r | |
86 | TokenList = Line.split(TAB_VALUE_SPLIT)\r | |
87 | if len(TokenList) > 0:\r | |
88 | Path = TokenList[0].strip().replace('\\', '/')\r | |
89 | if not Path:\r | |
90 | return False, ST.ERR_WRONG_FILELIST_FORMAT\r | |
91 | Valid, Cause = PathFunc(Path)\r | |
92 | if not Valid:\r | |
93 | return Valid, Cause\r | |
94 | FileList[0] = TokenList[0].strip()\r | |
95 | for Token in TokenList[1:]:\r | |
96 | Attr = Token.split(TAB_EQUAL_SPLIT)\r | |
97 | if len(Attr) != 2 or not Attr[0].strip() or not Attr[1].strip():\r | |
98 | return False, ST.ERR_WRONG_FILELIST_FORMAT\r | |
99 | \r | |
100 | Key = Attr[0].strip()\r | |
101 | Val = Attr[1].strip()\r | |
102 | if Key not in ['OS', 'Executable']:\r | |
103 | return False, ST.ERR_UNKNOWN_FILELIST_ATTR % Key\r | |
104 | \r | |
105 | if Key == 'OS' and Val not in ["Win32", "Win64", "Linux32", \r | |
106 | "Linux64", "OS/X32", "OS/X64", \r | |
107 | "GenericWin", "GenericNix"]:\r | |
108 | return False, ST.ERR_FILELIST_ATTR % 'OS'\r | |
109 | elif Key == 'Executable' and Val not in ['true', 'false']:\r | |
110 | return False, ST.ERR_FILELIST_ATTR % 'Executable'\r | |
111 | FileList[1][Key] = Val\r | |
112 | \r | |
113 | Map[CurrentKey].append(FileList)\r | |
114 | return True, ''\r | |
115 | \r | |
116 | ## Create header XML file\r | |
117 | #\r | |
118 | # @param DistMap: DistMap\r | |
119 | # @param Root: Root\r | |
120 | #\r | |
121 | def CreateHeaderXml(DistMap, Root):\r | |
122 | Element1 = CreateXmlElement('Name', DistMap['Name'],\r | |
123 | [], [['BaseName', DistMap['BaseName']]])\r | |
124 | Element2 = CreateXmlElement('GUID', DistMap['GUID'],\r | |
125 | [], [['Version', DistMap['Version']]])\r | |
126 | AttributeList = [['ReadOnly', DistMap['ReadOnly']],\r | |
127 | ['RePackage', DistMap['RePackage']]]\r | |
128 | NodeList = [Element1,\r | |
129 | Element2,\r | |
130 | ['Vendor', DistMap['Vendor']],\r | |
131 | ['Date', DistMap['Date']],\r | |
132 | ['Copyright', DistMap['Copyright']],\r | |
133 | ['License', DistMap['License']],\r | |
134 | ['Abstract', DistMap['Abstract']],\r | |
135 | ['Description', DistMap['Description']],\r | |
136 | ['Signature', DistMap['Signature']],\r | |
137 | ['XmlSpecification', DistMap['XmlSpecification']],\r | |
138 | ]\r | |
139 | Root.appendChild(CreateXmlElement('DistributionHeader', '',\r | |
140 | NodeList, AttributeList))\r | |
141 | \r | |
142 | ## Create tools XML file\r | |
143 | #\r | |
144 | # @param Map: Map\r | |
145 | # @param Root: Root\r | |
146 | # @param Tag: Tag \r | |
147 | #\r | |
148 | def CreateToolsXml(Map, Root, Tag):\r | |
149 | #\r | |
150 | # Check if all elements in this section are empty\r | |
151 | #\r | |
152 | for Key in Map:\r | |
153 | if len(Map[Key]) > 0:\r | |
154 | break\r | |
155 | else:\r | |
156 | return\r | |
157 | \r | |
158 | NodeList = [['Name', Map['Name']],\r | |
159 | ['Copyright', Map['Copyright']],\r | |
160 | ['License', Map['License']],\r | |
161 | ['Abstract', Map['Abstract']],\r | |
162 | ['Description', Map['Description']],\r | |
163 | ]\r | |
164 | HeaderNode = CreateXmlElement('Header', '', NodeList, [])\r | |
165 | NodeList = [HeaderNode]\r | |
166 | \r | |
167 | for File in Map['FileList']:\r | |
168 | AttrList = []\r | |
169 | for Key in File[1]:\r | |
170 | AttrList.append([Key, File[1][Key]])\r | |
171 | NodeList.append(CreateXmlElement('Filename', File[0], [], AttrList))\r | |
172 | Root.appendChild(CreateXmlElement(Tag, '', NodeList, []))\r | |
173 | \r | |
174 | ## ValidateValues\r | |
175 | #\r | |
176 | # @param Key: Key\r | |
177 | # @param Value: Value\r | |
178 | # @param SectionName: SectionName\r | |
179 | #\r | |
180 | def ValidateValues(Key, Value, SectionName):\r | |
181 | if SectionName == 'DistributionHeader':\r | |
182 | Valid, Cause = ValidateRegValues(Key, Value)\r | |
183 | if not Valid:\r | |
184 | return Valid, Cause\r | |
185 | Valid = __ValidateDistHeader(Key, Value)\r | |
186 | if not Valid:\r | |
187 | return Valid, ST.ERR_VALUE_INVALID % (Key, SectionName)\r | |
188 | else:\r | |
189 | Valid = __ValidateOtherHeader(Key, Value)\r | |
190 | if not Valid:\r | |
191 | return Valid, ST.ERR_VALUE_INVALID % (Key, SectionName)\r | |
192 | return True, ''\r | |
193 | \r | |
194 | ## ValidateRegValues\r | |
195 | #\r | |
196 | # @param Key: Key\r | |
197 | # @param Value: Value\r | |
198 | #\r | |
199 | def ValidateRegValues(Key, Value):\r | |
200 | ValidateMap = {\r | |
201 | 'ReadOnly' :\r | |
202 | ('true|false', ST.ERR_BOOLEAN_VALUE % (Key, Value)),\r | |
203 | 'RePackage' :\r | |
204 | ('true|false', ST.ERR_BOOLEAN_VALUE % (Key, Value)),\r | |
205 | 'GUID' :\r | |
206 | ('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}'\r | |
207 | '-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}',\r | |
208 | ST.ERR_GUID_VALUE % Value),\r | |
209 | 'Version' : ('[0-9]+(\.[0-9]+)?', ST.ERR_VERSION_VALUE % \\r | |
210 | (Key, Value)),\r | |
211 | 'XmlSpecification' : ('1\.1', ST.ERR_VERSION_XMLSPEC % Value)\r | |
212 | }\r | |
213 | if Key not in ValidateMap:\r | |
214 | return True, ''\r | |
215 | Elem = ValidateMap[Key]\r | |
216 | Match = re.compile(Elem[0]).match(Value)\r | |
217 | if Match and Match.start() == 0 and Match.end() == len(Value):\r | |
218 | return True, ''\r | |
219 | return False, Elem[1]\r | |
220 | \r | |
221 | ## __ValidateDistHeaderName\r | |
222 | #\r | |
223 | # @param Name: Name\r | |
224 | #\r | |
225 | def __ValidateDistHeaderName(Name):\r | |
226 | if len(Name) < 1:\r | |
227 | return False\r | |
228 | \r | |
229 | for Char in Name:\r | |
230 | if ord(Char) < 0x20 or ord(Char) >= 0x7f:\r | |
231 | return False\r | |
232 | return True\r | |
233 | \r | |
234 | ## __ValidateDistHeaderBaseName\r | |
235 | #\r | |
236 | # @param BaseName: BaseName\r | |
237 | #\r | |
238 | def __ValidateDistHeaderBaseName(BaseName):\r | |
239 | if not BaseName:\r | |
240 | return False\r | |
241 | # if CheckLen and len(BaseName) < 2:\r | |
242 | # return False\r | |
243 | if not BaseName[0].isalnum() and BaseName[0] != '_':\r | |
244 | return False\r | |
245 | for Char in BaseName[1:]:\r | |
246 | if not Char.isalnum() and Char not in '-_':\r | |
247 | return False\r | |
248 | return True\r | |
249 | \r | |
250 | ## __ValidateDistHeaderAbstract\r | |
251 | #\r | |
252 | # @param Abstract: Abstract\r | |
253 | #\r | |
254 | def __ValidateDistHeaderAbstract(Abstract):\r | |
255 | return '\t' not in Abstract and len(Abstract.splitlines()) == 1\r | |
256 | \r | |
257 | ## __ValidateOtherHeaderAbstract\r | |
258 | #\r | |
259 | # @param Abstract: Abstract\r | |
260 | #\r | |
261 | def __ValidateOtherHeaderAbstract(Abstract):\r | |
262 | return __ValidateDistHeaderAbstract(Abstract)\r | |
263 | \r | |
264 | ## __ValidateDistHeader\r | |
265 | #\r | |
266 | # @param Key: Key\r | |
267 | # @param Value: Value\r | |
268 | #\r | |
269 | def __ValidateDistHeader(Key, Value):\r | |
270 | ValidateMap = {\r | |
271 | 'Name' : __ValidateDistHeaderName,\r | |
272 | 'BaseName' : __ValidateDistHeaderBaseName,\r | |
273 | 'Abstract' : __ValidateDistHeaderAbstract,\r | |
274 | 'Vendor' : __ValidateDistHeaderAbstract\r | |
275 | }\r | |
276 | return not (Value and Key in ValidateMap and not ValidateMap[Key](Value))\r | |
277 | \r | |
278 | ## __ValidateOtherHeader\r | |
279 | #\r | |
280 | # @param Key: Key\r | |
281 | # @param Value: Value\r | |
282 | #\r | |
283 | def __ValidateOtherHeader(Key, Value):\r | |
284 | ValidateMap = {\r | |
285 | 'Name' : __ValidateDistHeaderName,\r | |
286 | 'Abstract' : __ValidateOtherHeaderAbstract\r | |
287 | }\r | |
288 | return not (Value and Key in ValidateMap and not ValidateMap[Key](Value))\r | |
289 | \r | |
290 | ## Convert ini file to xml file\r | |
291 | #\r | |
292 | # @param IniFile\r | |
293 | #\r | |
294 | def IniToXml(IniFile):\r | |
295 | if not os.path.exists(IniFile):\r | |
296 | Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_TEMPLATE_NOTFOUND % IniFile)\r | |
297 | \r | |
298 | DistMap = {'ReadOnly' : '', 'RePackage' : '', 'Name' : '',\r | |
299 | 'BaseName' : '', 'GUID' : '', 'Version' : '', 'Vendor' : '',\r | |
300 | 'Date' : '', 'Copyright' : '', 'License' : '', 'Abstract' : '',\r | |
301 | 'Description' : '', 'Signature' : '', 'XmlSpecification' : ''\r | |
302 | }\r | |
303 | \r | |
304 | ToolsMap = {'Name' : '', 'Copyright' : '', 'License' : '',\r | |
305 | 'Abstract' : '', 'Description' : '', 'FileList' : []}\r | |
306 | #\r | |
307 | # Only FileList is a list: [['file1', {}], ['file2', {}], ...]\r | |
308 | #\r | |
309 | MiscMap = {'Name' : '', 'Copyright' : '', 'License' : '',\r | |
310 | 'Abstract' : '', 'Description' : '', 'FileList' : []}\r | |
311 | \r | |
312 | SectionMap = {\r | |
313 | 'DistributionHeader' : DistMap,\r | |
314 | 'ToolsHeader' : ToolsMap,\r | |
315 | 'MiscellaneousFilesHeader' : MiscMap\r | |
316 | }\r | |
317 | \r | |
318 | PathValidator = {\r | |
319 | 'ToolsHeader' : ValidateToolsFile,\r | |
320 | 'MiscellaneousFilesHeader' : ValidateMiscFile\r | |
321 | }\r | |
322 | \r | |
323 | ParsedSection = []\r | |
324 | \r | |
325 | SectionName = ''\r | |
326 | CurrentKey = ''\r | |
327 | PreMap = None\r | |
328 | Map = None\r | |
329 | FileContent = ConvertSpecialChar(open(IniFile, 'rb').readlines())\r | |
330 | LastIndex = 0\r | |
331 | for Index in range(0, len(FileContent)):\r | |
332 | LastIndex = Index\r | |
333 | Line = FileContent[Index].strip()\r | |
421ccda3 | 334 | if Line == '' or Line.startswith(';'):\r |
4234283c LG |
335 | continue\r |
336 | if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r | |
337 | CurrentKey = ''\r | |
338 | SectionName = Line[1:-1].strip()\r | |
339 | if SectionName not in SectionMap:\r | |
340 | IniParseError(ST.ERR_SECTION_NAME_INVALID % SectionName,\r | |
341 | IniFile, Index+1)\r | |
342 | \r | |
343 | if SectionName in ParsedSection:\r | |
344 | IniParseError(ST.ERR_SECTION_REDEFINE % SectionName,\r | |
345 | IniFile, Index+1)\r | |
346 | else:\r | |
347 | ParsedSection.append(SectionName)\r | |
348 | \r | |
349 | Map = SectionMap[SectionName]\r | |
350 | continue\r | |
351 | if not Map:\r | |
352 | IniParseError(ST.ERR_SECTION_NAME_NONE, IniFile, Index+1)\r | |
353 | TokenList = Line.split(TAB_EQUAL_SPLIT, 1)\r | |
354 | TempKey = TokenList[0].strip()\r | |
355 | #\r | |
356 | # Value spanned multiple or same keyword appears more than one time\r | |
357 | #\r | |
358 | if len(TokenList) < 2 or TempKey not in Map:\r | |
359 | if CurrentKey == '':\r | |
360 | IniParseError(ST.ERR_KEYWORD_INVALID % TempKey,\r | |
361 | IniFile, Index+1)\r | |
362 | elif CurrentKey == 'FileList':\r | |
363 | #\r | |
364 | # Special for FileList\r | |
365 | #\r | |
366 | Valid, Cause = ParseFileList(Line, Map, CurrentKey, \r | |
367 | PathValidator[SectionName])\r | |
368 | if not Valid:\r | |
369 | IniParseError(Cause, IniFile, Index+1)\r | |
370 | \r | |
371 | else:\r | |
372 | #\r | |
373 | # Multiple lines for one key such as license\r | |
374 | # Or if string on the left side of '=' is not a keyword\r | |
375 | #\r | |
376 | Map[CurrentKey] = ''.join([Map[CurrentKey], '\n', Line])\r | |
377 | Valid, Cause = ValidateValues(CurrentKey, \r | |
378 | Map[CurrentKey], SectionName)\r | |
379 | if not Valid:\r | |
380 | IniParseError(Cause, IniFile, Index+1)\r | |
381 | continue\r | |
382 | \r | |
383 | if (TokenList[1].strip() == ''):\r | |
384 | IniParseError(ST.ERR_EMPTY_VALUE, IniFile, Index+1)\r | |
385 | \r | |
386 | #\r | |
387 | # A keyword found\r | |
388 | #\r | |
389 | CurrentKey = TempKey\r | |
390 | if Map[CurrentKey]:\r | |
391 | IniParseError(ST.ERR_KEYWORD_REDEFINE % CurrentKey,\r | |
392 | IniFile, Index+1)\r | |
393 | \r | |
394 | if id(Map) != id(PreMap) and Map['Copyright']:\r | |
395 | PreMap = Map\r | |
396 | Copyright = Map['Copyright'].lower()\r | |
397 | Pos = Copyright.find('copyright')\r | |
398 | if Pos == -1:\r | |
399 | IniParseError(ST.ERR_COPYRIGHT_CONTENT, IniFile, Index)\r | |
400 | if not Copyright[Pos + len('copyright'):].lstrip(' ').startswith('('):\r | |
401 | IniParseError(ST.ERR_COPYRIGHT_CONTENT, IniFile, Index)\r | |
402 | \r | |
403 | if CurrentKey == 'FileList':\r | |
404 | Valid, Cause = ParseFileList(TokenList[1], Map, CurrentKey, \r | |
405 | PathValidator[SectionName])\r | |
406 | if not Valid:\r | |
407 | IniParseError(Cause, IniFile, Index+1)\r | |
408 | else:\r | |
409 | Map[CurrentKey] = TokenList[1].strip()\r | |
410 | Valid, Cause = ValidateValues(CurrentKey,\r | |
411 | Map[CurrentKey], SectionName)\r | |
412 | if not Valid:\r | |
413 | IniParseError(Cause, IniFile, Index+1)\r | |
414 | \r | |
415 | if id(Map) != id(PreMap) and Map['Copyright'] and 'copyright' not in Map['Copyright'].lower():\r | |
416 | IniParseError(ST.ERR_COPYRIGHT_CONTENT, IniFile, LastIndex)\r | |
417 | \r | |
418 | #\r | |
419 | # Check mandatory keys\r | |
420 | # \r | |
421 | CheckMdtKeys(DistMap, IniFile, LastIndex, \r | |
422 | (('ToolsHeader', ToolsMap), ('MiscellaneousFilesHeader', MiscMap))\r | |
423 | )\r | |
424 | \r | |
425 | return CreateXml(DistMap, ToolsMap, MiscMap, IniFile)\r | |
426 | \r | |
427 | \r | |
428 | ## CheckMdtKeys\r | |
429 | #\r | |
430 | # @param MdtDistKeys: All mandatory keys\r | |
431 | # @param DistMap: Dist content\r | |
432 | # @param IniFile: Ini file\r | |
433 | # @param LastIndex: Last index of Ini file\r | |
434 | # @param Maps: Tools and Misc section name and map. (('section_name', map),*)\r | |
435 | #\r | |
436 | def CheckMdtKeys(DistMap, IniFile, LastIndex, Maps): \r | |
437 | MdtDistKeys = ['Name', 'GUID', 'Version', 'Vendor', 'Copyright', 'License', 'Abstract', 'XmlSpecification']\r | |
438 | for Key in MdtDistKeys:\r | |
439 | if Key not in DistMap or DistMap[Key] == '':\r | |
440 | IniParseError(ST.ERR_KEYWORD_MANDATORY % Key, IniFile, LastIndex+1)\r | |
441 | \r | |
442 | if '.' not in DistMap['Version']:\r | |
443 | DistMap['Version'] = DistMap['Version'] + '.0'\r | |
444 | \r | |
445 | DistMap['Date'] = str(strftime("%Y-%m-%dT%H:%M:%S", localtime()))\r | |
446 | \r | |
447 | #\r | |
448 | # Check Tools Surface Area according to UPT Spec\r | |
449 | # <Tools> {0,}\r | |
450 | # <Header> ... </Header> {0,1}\r | |
451 | # <Filename> ... </Filename> {1,}\r | |
452 | # </Tools>\r | |
453 | # <Header>\r | |
454 | # <Name> xs:normalizedString </Name> {1}\r | |
455 | # <Copyright> xs:string </Copyright> {0,1}\r | |
456 | # <License> xs:string </License> {0,1}\r | |
457 | # <Abstract> xs:normalizedString </Abstract> {0,1}\r | |
458 | # <Description> xs:string </Description> {0,1}\r | |
459 | # </Header>\r | |
460 | #\r | |
461 | for Item in Maps:\r | |
462 | Map = Item[1]\r | |
463 | NonEmptyKey = 0\r | |
464 | for Key in Map:\r | |
465 | if Map[Key]:\r | |
466 | NonEmptyKey += 1\r | |
467 | \r | |
468 | if NonEmptyKey > 0 and not Map['FileList']:\r | |
469 | IniParseError(ST.ERR_KEYWORD_MANDATORY % (Item[0] + '.FileList'), IniFile, LastIndex+1)\r | |
470 | \r | |
471 | if NonEmptyKey > 0 and not Map['Name']:\r | |
472 | IniParseError(ST.ERR_KEYWORD_MANDATORY % (Item[0] + '.Name'), IniFile, LastIndex+1)\r | |
473 | \r | |
474 | ## CreateXml\r | |
475 | #\r | |
476 | # @param DistMap: Dist Content\r | |
477 | # @param ToolsMap: Tools Content\r | |
478 | # @param MiscMap: Misc Content\r | |
479 | # @param IniFile: Ini File\r | |
480 | #\r | |
481 | def CreateXml(DistMap, ToolsMap, MiscMap, IniFile): \r | |
482 | Attrs = [['xmlns', 'http://www.uefi.org/2011/1.1'],\r | |
483 | ['xmlns:xsi', 'http:/www.w3.org/2001/XMLSchema-instance'],\r | |
484 | ]\r | |
485 | Root = CreateXmlElement('DistributionPackage', '', [], Attrs)\r | |
486 | CreateHeaderXml(DistMap, Root)\r | |
487 | CreateToolsXml(ToolsMap, Root, 'Tools')\r | |
488 | CreateToolsXml(MiscMap, Root, 'MiscellaneousFiles')\r | |
489 | \r | |
490 | FileAndExt = IniFile.rsplit('.', 1)\r | |
491 | if len(FileAndExt) > 1:\r | |
492 | FileName = FileAndExt[0] + '.xml'\r | |
493 | else:\r | |
494 | FileName = IniFile + '.xml'\r | |
495 | File = open(FileName, 'w')\r | |
496 | \r | |
497 | try:\r | |
498 | File.write(Root.toprettyxml(indent = ' '))\r | |
499 | finally:\r | |
500 | File.close()\r | |
501 | return FileName\r | |
502 | \r |