- Merged the local copy of XmlRoutines.py in buildgen into upper directory's XmlRouti...
[mirror_edk2.git] / Tools / Python / XmlRoutines.py
CommitLineData
77afa5eb 1#!/usr/bin/env python
2
3b7a53b6 3# Copyright (c) 2007, Intel Corporation
4# All rights reserved. This program and the accompanying materials
5# are licensed and made available under the terms and conditions of the BSD License
6# which accompanies this distribution. The full text of the license may be found at
7# http://opensource.org/licenses/bsd-license.php
8#
9# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12"""This is an XML API that uses a syntax similar to XPath, but it is written in
13standard python so that no extra python packages are required to use it."""
77afa5eb 14
15import xml.dom.minidom
16
17def XmlList(Dom, String):
18 """Get a list of XML Elements using XPath style syntax."""
2082f936 19 if String == None or String == "" or Dom == None or Dom == "":
4040421a 20 return []
77afa5eb 21 if Dom.nodeType==Dom.DOCUMENT_NODE:
2082f936 22 Dom = Dom.documentElement
77afa5eb 23 if String[0] == "/":
2082f936 24 String = String[1:]
25 tagList = String.split('/')
26 nodes = [Dom]
27 index = 0
28 end = len(tagList) - 1
29 while index <= end:
30 childNodes = []
31 for node in nodes:
32 if node.nodeType == node.ELEMENT_NODE and node.tagName == tagList[index]:
33 if index < end:
34 childNodes.extend(node.childNodes)
35 else:
36 childNodes.append(node)
37 nodes = childNodes
38 childNodes = []
39 index += 1
40
77afa5eb 41 return nodes
42
4040421a 43def XmlNode (Dom, String):
44 """Return a single node that matches the String which is XPath style syntax."""
2082f936 45 if String == None or String == "" or Dom == None or Dom == "":
46 return ""
47 if Dom.nodeType==Dom.DOCUMENT_NODE:
48 Dom = Dom.documentElement
49 if String[0] == "/":
50 String = String[1:]
51 tagList = String.split('/')
52 index = 0
53 end = len(tagList) - 1
54 childNodes = [Dom]
55 while index <= end:
56 for node in childNodes:
57 if node.nodeType == node.ELEMENT_NODE and node.tagName == tagList[index]:
58 if index < end:
59 childNodes = node.childNodes
60 else:
61 return node
62 break
63 index += 1
64 return ""
4040421a 65
77afa5eb 66def XmlElement (Dom, String):
67 """Return a single element that matches the String which is XPath style syntax."""
68 try:
2082f936 69 return XmlNode (Dom, String).firstChild.data.strip()
77afa5eb 70 except:
71 return ''
72
73def XmlElementData (Dom):
74 """Get the text for this element."""
2082f936 75 if Dom == None or Dom == '' or Dom.firstChild == None:
76 return ''
8d4243f1 77 return Dom.firstChild.data.strip()
77afa5eb 78
3b7a53b6 79def XmlAttribute (Dom, AttName):
80 """Return a single attribute named AttName."""
2082f936 81 if Dom == None or Dom == '':
82 return ''
77afa5eb 83 try:
3b7a53b6 84 return Dom.getAttribute(AttName)
77afa5eb 85 except:
86 return ''
87
e853a9d4 88def XmlTopTag(Dom):
89 """Return the name of the Root or top tag in the XML tree."""
8d4243f1 90 return Dom.firstChild.nodeName
91
92def XmlParseFile (FileName):
93 """Parse an XML file into a DOM and return the DOM."""
94 try:
95 f = open(FileName, 'r')
96 Dom = xml.dom.minidom.parse(f)
97 f.close()
98 return Dom
99 except:
100 return xml.dom.minidom.parseString('<empty/>')
101
24a86f9a 102def XmlParseString (Str):
103 """Parse an XML string into a DOM and return the DOM."""
104 try:
105 return xml.dom.minidom.parseString(Str)
106 except:
107 return xml.dom.minidom.parseString('<empty/>')
108
8d4243f1 109def XmlParseFileSection (FileName, Tag):
110 """Parse a section of an XML file into a DOM(Document Object Model) and return the DOM."""
111 try:
112 f = open(FileName, 'r')
113 except:
114 return xml.dom.minidom.parseString('<empty/>')
115 Start = '<' + Tag
116 End = '</' + Tag + '>'
117 File = ''
118 while File.find(Start) < 0 or File.find(End) < 0:
119 Section = f.read(0x1000)
120 if Section == '':
121 break
122 File += Section
123 f.close()
124 if File.find(Start) < 0 or File.find(End) < 0:
125 return xml.dom.minidom.parseString('<empty/>')
126 File = File[File.find(Start):File.find(End)+len(End)]
127 try:
128 return xml.dom.minidom.parseString(File)
129 except:
130 return xml.dom.minidom.parseString('<empty/>')
131
4040421a 132def XmlParseStringSection (XmlString, Tag):
133 """Parse a section of an XML string into a DOM(Document Object Model) and return the DOM."""
134 Start = '<' + Tag
135 End = '</' + Tag + '>'
136 File = XmlString
137 if File.find(Start) < 0 or File.find(End) < 0:
138 return xml.dom.minidom.parseString('<empty/>')
139 File = File[File.find(Start):File.find(End)+len(End)]
140 try:
141 return xml.dom.minidom.parseString(File)
142 except:
143 return xml.dom.minidom.parseString('<empty/>')
144
8d4243f1 145def XmlSaveFile (Dom, FileName, Encoding='UTF-8'):
146 """Save a DOM(Document Object Model) into an XML file."""
147 try:
148 f = open(FileName, 'w')
149 f.write(Dom.toxml(Encoding).replace('&quot;','"').replace('&gt;','>'))
150 f.close()
151 return True
152 except:
153 return False
154
155def XmlRemoveElement(Node):
156 """Remove an element node from DOM(Document Object Model) tree."""
157 ParentNode = Node.parentNode
158 if ParentNode == None:
159 return False
160 PreviousSibling = Node.previousSibling
161 while PreviousSibling != None and PreviousSibling.nodeType == PreviousSibling.TEXT_NODE and PreviousSibling.data.strip() == '':
162 Temp = PreviousSibling
163 PreviousSibling = PreviousSibling.previousSibling
164 ParentNode.removeChild(Temp)
165 ParentNode.removeChild(Node)
166 return True
167
168def XmlAppendChildElement(ParentNode, TagName, ElementText='', AttributeDictionary = {}):
169 """Add a child element to a DOM(Document Object Model) tree with optional Attributes."""
170 TagName = TagName.strip()
171 if TagName == '':
f0a3fde1 172 return None
8d4243f1 173 Depth = 0
174 Dom = ParentNode
175 while Dom != None and Dom.nodeType != Dom.DOCUMENT_NODE:
176 Dom = Dom.parentNode
177 Depth += 1
178 if Dom == None:
f0a3fde1 179 return None
8d4243f1 180 ParentNode.appendChild(Dom.createTextNode('\n%*s' % (Depth * 2, '')))
181 ElementNode = Dom.createElement(TagName)
182 if ElementText != '':
183 ElementNode.appendChild(Dom.createTextNode(ElementText))
184 for Item in AttributeDictionary:
185 ElementNode.setAttribute(Item, AttributeDictionary[Item])
186 ParentNode.appendChild(ElementNode)
f0a3fde1 187 return ElementNode
e853a9d4 188
189
77afa5eb 190# This acts like the main() function for the script, unless it is 'import'ed into another
191# script.
192if __name__ == '__main__':
193
194 # Nothing to do here. Could do some unit tests.
195 pass