]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Library / Xml / XmlRoutines.py
1 ## @file
2 # This is an XML API that uses a syntax similar to XPath, but it is written in
3 # standard python so that no extra python packages are required to use it.
4 #
5 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6 #
7 # SPDX-License-Identifier: BSD-2-Clause-Patent
8 #
9
10 '''
11 XmlRoutines
12 '''
13
14 ##
15 # Import Modules
16 #
17 import xml.dom.minidom
18 import re
19 import codecs
20 from Logger.ToolError import PARSER_ERROR
21 import Logger.Log as Logger
22
23 ## Create a element of XML
24 #
25 # @param Name
26 # @param String
27 # @param NodeList
28 # @param AttributeList
29 #
30 def CreateXmlElement(Name, String, NodeList, AttributeList):
31 Doc = xml.dom.minidom.Document()
32 Element = Doc.createElement(Name)
33 if String != '' and String is not None:
34 Element.appendChild(Doc.createTextNode(String))
35
36 for Item in NodeList:
37 if isinstance(Item, type([])):
38 Key = Item[0]
39 Value = Item[1]
40 if Key != '' and Key is not None and Value != '' and Value is not None:
41 Node = Doc.createElement(Key)
42 Node.appendChild(Doc.createTextNode(Value))
43 Element.appendChild(Node)
44 else:
45 Element.appendChild(Item)
46 for Item in AttributeList:
47 Key = Item[0]
48 Value = Item[1]
49 if Key != '' and Key is not None and Value != '' and Value is not None:
50 Element.setAttribute(Key, Value)
51
52 return Element
53
54 ## Get a list of XML nodes using XPath style syntax.
55 #
56 # Return a list of XML DOM nodes from the root Dom specified by XPath String.
57 # If the input Dom or String is not valid, then an empty list is returned.
58 #
59 # @param Dom The root XML DOM node.
60 # @param String A XPath style path.
61 #
62 def XmlList(Dom, String):
63 if String is None or String == "" or Dom is None or Dom == "":
64 return []
65 if Dom.nodeType == Dom.DOCUMENT_NODE:
66 Dom = Dom.documentElement
67 if String[0] == "/":
68 String = String[1:]
69 TagList = String.split('/')
70 Nodes = [Dom]
71 Index = 0
72 End = len(TagList) - 1
73 while Index <= End:
74 ChildNodes = []
75 for Node in Nodes:
76 if Node.nodeType == Node.ELEMENT_NODE and Node.tagName == \
77 TagList[Index]:
78 if Index < End:
79 ChildNodes.extend(Node.childNodes)
80 else:
81 ChildNodes.append(Node)
82 Nodes = ChildNodes
83 ChildNodes = []
84 Index += 1
85
86 return Nodes
87
88
89 ## Get a single XML node using XPath style syntax.
90 #
91 # Return a single XML DOM node from the root Dom specified by XPath String.
92 # If the input Dom or String is not valid, then an empty string is returned.
93 #
94 # @param Dom The root XML DOM node.
95 # @param String A XPath style path.
96 #
97 def XmlNode(Dom, String):
98 if String is None or String == "" or Dom is None or Dom == "":
99 return None
100 if Dom.nodeType == Dom.DOCUMENT_NODE:
101 Dom = Dom.documentElement
102 if String[0] == "/":
103 String = String[1:]
104 TagList = String.split('/')
105 Index = 0
106 End = len(TagList) - 1
107 ChildNodes = [Dom]
108 while Index <= End:
109 for Node in ChildNodes:
110 if Node.nodeType == Node.ELEMENT_NODE and \
111 Node.tagName == TagList[Index]:
112 if Index < End:
113 ChildNodes = Node.childNodes
114 else:
115 return Node
116 break
117 Index += 1
118 return None
119
120
121 ## Get a single XML element using XPath style syntax.
122 #
123 # Return a single XML element from the root Dom specified by XPath String.
124 # If the input Dom or String is not valid, then an empty string is returned.
125 #
126 # @param Dom The root XML DOM object.
127 # @param Strin A XPath style path.
128 #
129 def XmlElement(Dom, String):
130 try:
131 return XmlNode(Dom, String).firstChild.data.strip()
132 except BaseException:
133 return ""
134
135 ## Get a single XML element using XPath style syntax.
136 #
137 # Similar with XmlElement, but do not strip all the leading and tailing space
138 # and newline, instead just remove the newline and spaces introduced by
139 # toprettyxml()
140 #
141 # @param Dom The root XML DOM object.
142 # @param Strin A XPath style path.
143 #
144 def XmlElement2(Dom, String):
145 try:
146 HelpStr = XmlNode(Dom, String).firstChild.data
147 gRemovePrettyRe = re.compile(r"""(?:(\n *) )(.*)\1""", re.DOTALL)
148 HelpStr = re.sub(gRemovePrettyRe, r"\2", HelpStr)
149 return HelpStr
150 except BaseException:
151 return ""
152
153
154 ## Get a single XML element of the current node.
155 #
156 # Return a single XML element specified by the current root Dom.
157 # If the input Dom is not valid, then an empty string is returned.
158 #
159 # @param Dom The root XML DOM object.
160 #
161 def XmlElementData(Dom):
162 try:
163 return Dom.firstChild.data.strip()
164 except BaseException:
165 return ""
166
167
168 ## Get a list of XML elements using XPath style syntax.
169 #
170 # Return a list of XML elements from the root Dom specified by XPath String.
171 # If the input Dom or String is not valid, then an empty list is returned.
172 #
173 # @param Dom The root XML DOM object.
174 # @param String A XPath style path.
175 #
176 def XmlElementList(Dom, String):
177 return list(map(XmlElementData, XmlList(Dom, String)))
178
179
180 ## Get the XML attribute of the current node.
181 #
182 # Return a single XML attribute named Attribute from the current root Dom.
183 # If the input Dom or Attribute is not valid, then an empty string is returned.
184 #
185 # @param Dom The root XML DOM object.
186 # @param Attribute The name of Attribute.
187 #
188 def XmlAttribute(Dom, Attribute):
189 try:
190 return Dom.getAttribute(Attribute)
191 except BaseException:
192 return ''
193
194
195 ## Get the XML node name of the current node.
196 #
197 # Return a single XML node name from the current root Dom.
198 # If the input Dom is not valid, then an empty string is returned.
199 #
200 # @param Dom The root XML DOM object.
201 #
202 def XmlNodeName(Dom):
203 try:
204 return Dom.nodeName.strip()
205 except BaseException:
206 return ''
207
208 ## Parse an XML file.
209 #
210 # Parse the input XML file named FileName and return a XML DOM it stands for.
211 # If the input File is not a valid XML file, then an empty string is returned.
212 #
213 # @param FileName The XML file name.
214 #
215 def XmlParseFile(FileName):
216 try:
217 XmlFile = codecs.open(FileName, 'rb')
218 Dom = xml.dom.minidom.parse(XmlFile)
219 XmlFile.close()
220 return Dom
221 except BaseException as XExcept:
222 XmlFile.close()
223 Logger.Error('\nUPT', PARSER_ERROR, XExcept, File=FileName, RaiseError=True)