hmm i made a xml parser/writer for a project i was doing it works for what i need it to the parser part is about 180 lines including the comments and blank lines
adn the writer is like 44 lines… it could probably be way better but it works for me
# Crappy XML Parser #
# By: scabootssca #
# On:2/12/07 #
#Each split is a node.
class parserNode:
def __init__(self,tag="",meta={},index=[None,None],data="",inside="",parent=None,children=[]):
self.tag = tag
self.meta = meta
self.index = index
self.data = data
self.inside = inside
self.parent = parent
self.children = children[:]
self.parsed = 0
def getChild(self,**keys):
candidates = self.children[:]
for child in candidates:
for key in keys:
if key in child.meta:
if child.meta[key] != keys[key]:
candidates.remove(child)
else:
candidates.remove(child)
if candidates: return candidates[0]
else: return 0
def getChildByTag(self,tag,index=0):
currentIndex = 0
for child in self.children:
if child.tag == tag:
if currentIndex == index: return child
else: currentIndex += 1
class xmlParser:
def __init__(self,xmlData):
self.xmlData = xmlData
self.meta = {}
def readMeta(self):
index = self.xmlData.find("<?xml")
meta = {}
if not index == -1:
endIndex = self.xmlData.find("?>",index)
data = self.xmlData[index+5:endIndex].split('"')
for index in range(0,len(data),2):
key = data[index].strip()
if key:
meta[key[:-1]] = data[index+1]
self.xmlData = self.xmlData[endIndex+2:]
self.meta = meta
return meta
def removeComments(self):
itera=0
while "<!--" in self.xmlData and itera<20:
itera+=1
index = self.xmlData.find("<!--")
endIndex = self.xmlData.find("-->",index)
before = self.xmlData[:index]
after = self.xmlData[endIndex+3:]
self.xmlData = before+after
def findEnd(self,node,data=None):
nested = 0
findTag = node.tag
if not data:
if node.data: data = node.data
else: data = self.xmlData
for index,line in enumerate(data.splitlines()):
for tag in line.split("<"):
if not tag.startswith("?") and len(tag.strip()):
tag = tag.strip().strip("<>").split(">")[0].split()[0]
if tag == findTag:
nested += 1
if tag == "/"+findTag:
nested -= 1
if nested == 0:
return index
def getRootTagAndIndex(self):
for index,line in enumerate(self.xmlData.splitlines()):
for tag in line.split("<"):
if not tag.startswith("?") and len(tag.strip()):
return index,tag.strip().strip("<>").split(">")[0]
def getChildren(self,node):
children = []
data = "
".join(node.data.splitlines()[1:-1])
split = data.split("<")
currentTag = None
currentData = ""
for tag in split:
tag = tag.strip()
if not currentTag:
if len(tag):
currentTag = tag.split()[0].split(">")[0]
if currentTag and tag.strip("<>") == "/"+currentTag:
children.append([currentTag,tag])
currentTag = None
searchOffset = 0
for iteration,child in enumerate(children):
#print "-"*50
data = node.data[node.data.find("<"+child[0],searchOffset):node.data.find(child[1],searchOffset)+len(child[1])]
line = " ".join(data.split(">")[0].strip("<>").split()[1:]).split('"')
tag = child[0]
meta = {}
for split in range(0,len(line),2):
if len(line[split]):
meta[line[split].strip("=").strip()] = line[split+1]
childNode = parserNode(tag,meta)
childIndex = [None,None]
for index,line in enumerate(node.data[searchOffset:].strip().splitlines()):
prelude = len(node.data[:searchOffset].splitlines())
if "<"+child[0] in line:
childIndex[0] = index+prelude
if child[1] in line:
childIndex[1] = index+prelude
if childIndex[0]!=None and childIndex[1]!=None:
break
childNode.index = childIndex
childNode.data = data
childNode.inside = data.split(">",1)[1:][0].rsplit("<",1)[0]
searchOffset = len(node.data[:node.data.find(child[1],searchOffset)+len(child[1])])
childNode.parent = node
node.children.append(childNode)
#print childNode.children
return node.children
def getRoot(self):
index,root = self.getRootTagAndIndex()
tag = root.split()[0]
meta = {}
line = " ".join(root.split()[1:]).split('"')
for split in range(0,len(line),2):
if len(line[split]):
meta[line[split].strip("=").strip()] = line[split+1]
self.root = parserNode(tag,meta)
endIndex = self.findEnd(self.root)
self.root.index = [index,endIndex]
self.root.data = "
".join(self.xmlData.splitlines()[index:endIndex+1])
def depthFirstSearch(self,node):
node.parsed = 1
children = self.getChildren(node)
for child in children:
if not child.parsed:
self.depthFirstSearch(child)
def parse(self):
self.readMeta()
self.removeComments()
self.getRoot()
self.depthFirstSearch(self.root)
return self.root
# Crappy XML Generator #
# By: scabootssca #
# On:2/17/07 #
class node:
def __init__(self,tag,header={},parent=None):
self.tag = tag
self.header = header
self.parent = parent
if parent: parent.addChild(self)
self.children = []#children
self.written = 0
self.indent = ""
self.inner = ""
def addChild(self,child):
if not self.inner:
child.parent = 1
self.children.append(child)
return child
def setInner(self,data):
self.children = []
self.inner = str(data)
def writeChildren(file,node,indent):
node.written = 1
node.indent = indent
file.write("
"+node.indent+"<"+node.tag)
header = []
indent += " "
for data in node.header: header.append(' %s="%s"'%(data,str(node.header[data]).replace("'",'"')))
file.write(",".join(header)+">")
if node.inner: file.write(node.indent+indent+node.inner)
for child in node.children:
if not child.written:
writeChildren(file,child,indent)
file.write(node.indent+"</%s>
"%node.tag)
def compile(path,root):
f = file(path,"w")
writeChildren(f,root,"")
f.close()
#root = node("root")
#print root.children
#a = node("objects",parent=root)
#root.addChild("objects")
#b = root.addChild("groups")
#c = root.addChild("events")
#print root.children
#print a.children
##compile("saveTest.txt",root)