* get encoding to work a bit, not there yet... so many changes to list :(
This commit is contained in:
+6
-1
@@ -31,7 +31,8 @@ def getNodeAttribute(node, attrname):
|
|||||||
return node.getAttribute(attrname)
|
return node.getAttribute(attrname)
|
||||||
|
|
||||||
def getTagByName(parent, childName):
|
def getTagByName(parent, childName):
|
||||||
return [x for x in parent.childNodes if x.nodeType == x.ELEMENT_NODE if x.tagName == childName]
|
return [x for x in parent.childNodes
|
||||||
|
if x.nodeType == x.ELEMENT_NODE if x.tagName == childName]
|
||||||
|
|
||||||
def getNodeText(node, tagpath = ""):
|
def getNodeText(node, tagpath = ""):
|
||||||
"""get the first child and expect it to be text!"""
|
"""get the first child and expect it to be text!"""
|
||||||
@@ -131,6 +132,10 @@ def addNode(dom, node, tagpath, newnode = None):
|
|||||||
tags = []
|
tags = []
|
||||||
if tagpath != "":
|
if tagpath != "":
|
||||||
tags = tagpath.split('/') # tag chain
|
tags = tagpath.split('/') # tag chain
|
||||||
|
else:
|
||||||
|
addTagPath(dom, node, [], newnode)
|
||||||
|
return node
|
||||||
|
|
||||||
assert len(tags)>0 # we want a chain
|
assert len(tags)>0 # we want a chain
|
||||||
|
|
||||||
# iterative code to search for the path
|
# iterative code to search for the path
|
||||||
|
|||||||
+64
-53
@@ -163,6 +163,7 @@ class autoxml(type):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(cls, name, bases, dict):
|
def __init__(cls, name, bases, dict):
|
||||||
|
"""entry point for metaclass code"""
|
||||||
print 'generating class', name
|
print 'generating class', name
|
||||||
|
|
||||||
# add XmlFile as one of the superclasses, we're smart
|
# add XmlFile as one of the superclasses, we're smart
|
||||||
@@ -202,6 +203,7 @@ class autoxml(type):
|
|||||||
# generate top-level helper functions
|
# generate top-level helper functions
|
||||||
cls.initializers = inits
|
cls.initializers = inits
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
|
# XmlFile.__init__(self, cls.tag)
|
||||||
for init in self.__class__.initializers:
|
for init in self.__class__.initializers:
|
||||||
init(self)
|
init(self)
|
||||||
cls.__init__ = initialize
|
cls.__init__ = initialize
|
||||||
@@ -217,6 +219,7 @@ class autoxml(type):
|
|||||||
node = xml.newNode(cls.tag)
|
node = xml.newNode(cls.tag)
|
||||||
for encode_member in self.__class__.encoders:
|
for encode_member in self.__class__.encoders:
|
||||||
encode_member(self, xml, node)
|
encode_member(self, xml, node)
|
||||||
|
xml.dom.documentElement = node
|
||||||
return node
|
return node
|
||||||
cls.encode = encode
|
cls.encode = encode
|
||||||
|
|
||||||
@@ -238,33 +241,42 @@ class autoxml(type):
|
|||||||
assert type(tag_type) == type(type)
|
assert type(tag_type) == type(type)
|
||||||
def readtext(node, attr):
|
def readtext(node, attr):
|
||||||
return getNodeAttribute(node, attr)
|
return getNodeAttribute(node, attr)
|
||||||
def createnode(xml, attr):
|
def createnode(xml, attr_name):
|
||||||
return xml.newAttribute(attr)
|
return xml.newAttribute(attr_name) # create an attribute node
|
||||||
def writetext(node, attr, text):
|
def writetext(xml, attr, nil, text):
|
||||||
attr.value = text
|
attr.value = text
|
||||||
node.setAttributeNode(attr)
|
|
||||||
anonfuns = cls.gen_anon_basic(attr, spec, readtext, createnode, writetext)
|
anonfuns = cls.gen_anon_basic(attr, spec, readtext, createnode, writetext)
|
||||||
def mergetext(node, attr):
|
def mergetext(node, attr):
|
||||||
pass
|
node.setAttributeNode(node, attr)
|
||||||
return cls.gen_named_comp(attr, spec, anonfuns, mergetext)
|
return cls.gen_named_comp(attr, spec, anonfuns, mergetext)
|
||||||
|
|
||||||
def gen_tag_member(cls, tag):
|
def gen_tag_member(cls, tag):
|
||||||
"""generate helper funs for tag member of class"""
|
"""generate helper funs for tag member of class"""
|
||||||
spec = getattr(cls, 't_' + tag)
|
spec = getattr(cls, 't_' + tag)
|
||||||
def readtext(node, tagpath):
|
anonfuns = cls.gen_tag(tag, spec)
|
||||||
return getNodeText(getNode(node, tagpath))
|
def mergetext(node, newnode):
|
||||||
def createnode(xml, tag):
|
print 'mergenode', node, newnode
|
||||||
return xml.newNode(tag)
|
node.appendChild(newnode)
|
||||||
def writetext(node, text):
|
|
||||||
node.addText(node, text)
|
|
||||||
anonfuns = cls.gen_tag(tag, spec, createnode, readtext, writetext)
|
|
||||||
def mergetext(xml, node, tagpath):
|
|
||||||
pass
|
|
||||||
head, tail = cls.tagpath_head_last(tagpath)
|
|
||||||
subnode = xml.newNode(tail)
|
|
||||||
return cls.gen_named_comp(tag, spec, anonfuns, mergetext)
|
return cls.gen_named_comp(tag, spec, anonfuns, mergetext)
|
||||||
|
|
||||||
def gen_named_comp(cls, token, spec, anonfuns, createnode):
|
def gen_tag(cls, tag, spec):
|
||||||
|
"""generate readers and writers for the tag"""
|
||||||
|
tag_type = spec[0]
|
||||||
|
if type(tag_type) is types.TypeType:
|
||||||
|
def readtext(node, tagpath):
|
||||||
|
return getNodeText(node, tagpath)
|
||||||
|
def createnode(xml, tag):
|
||||||
|
return xml.newNode(tag)
|
||||||
|
def writetext(xml, node, tagpath, text):
|
||||||
|
xml.addTextNodeUnder(node, tagpath, text)
|
||||||
|
return cls.gen_anon_basic(tag, spec, readtext,
|
||||||
|
createnode, writetext)
|
||||||
|
elif type(tag_type) is types.ListType:
|
||||||
|
return cls.gen_list_tag(tag, spec)
|
||||||
|
elif type(tag_type) is autoxml or type(tag_type) is types.ClassType:
|
||||||
|
return cls.gen_class_tag(tag, spec)
|
||||||
|
|
||||||
|
def gen_named_comp(cls, token, spec, anonfuns, mergetext):
|
||||||
"""generate a named component tag/attr. a decoration of
|
"""generate a named component tag/attr. a decoration of
|
||||||
anonymous functions that do not bind to variable names"""
|
anonymous functions that do not bind to variable names"""
|
||||||
name = cls.mixed_case(token)
|
name = cls.mixed_case(token)
|
||||||
@@ -286,7 +298,9 @@ class autoxml(type):
|
|||||||
value = getattr(self, name)
|
value = getattr(self, name)
|
||||||
else:
|
else:
|
||||||
value = None
|
value = None
|
||||||
return encode_a(xml, self.dom.documentElement, value)
|
newnode = encode_a(xml, value)
|
||||||
|
if newnode:
|
||||||
|
mergetext(node, newnode)
|
||||||
|
|
||||||
def format(self):
|
def format(self):
|
||||||
if hasattr(self, name):
|
if hasattr(self, name):
|
||||||
@@ -299,28 +313,20 @@ class autoxml(type):
|
|||||||
|
|
||||||
return (init, decode, encode, format)
|
return (init, decode, encode, format)
|
||||||
|
|
||||||
def gen_tag(cls, tag, spec, readtext, createnode, writetext):
|
|
||||||
"""generate readers and writers for the tag"""
|
|
||||||
tag_type = spec[0]
|
|
||||||
if type(tag_type) is types.TypeType:
|
|
||||||
return cls.gen_anon_basic(tag, spec, readtext, createnode, writetext)
|
|
||||||
elif type(tag_type) is types.ListType:
|
|
||||||
return cls.gen_list_tag(tag, spec)
|
|
||||||
elif type(tag_type) is autoxml or type(tag_type) is types.ClassType:
|
|
||||||
return cls.gen_class_tag(tag, spec)
|
|
||||||
|
|
||||||
def mixed_case(cls, identifier):
|
def mixed_case(cls, identifier):
|
||||||
"""helper function to turn token name into mixed case"""
|
"""helper function to turn token name into mixed case"""
|
||||||
identifier_p = identifier[0].lower() + identifier[1:]
|
if identifier is "":
|
||||||
return identifier_p
|
return ""
|
||||||
|
else:
|
||||||
|
return identifier[0].lower() + identifier[1:]
|
||||||
|
|
||||||
def tagpath_head_last(cls, tag_path):
|
def tagpath_head_last(cls, tagpath):
|
||||||
"returns split of the tag path into last tag and the rest"
|
"returns split of the tag path into last tag and the rest"
|
||||||
try:
|
try:
|
||||||
lastsep = tagpath.rindex('/')
|
lastsep = tagpath.rindex('/')
|
||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
return ('', tag_path)
|
return ('', tagpath)
|
||||||
return (tag_path[:laststep], tag_path[laststep+1:])
|
return (tagpath[:lastsep], tagpath[lastsep+1:])
|
||||||
|
|
||||||
def parse_spec(cls, token, spec):
|
def parse_spec(cls, token, spec):
|
||||||
"""decompose member specification"""
|
"""decompose member specification"""
|
||||||
@@ -364,12 +370,12 @@ class autoxml(type):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def encode(xml, node, value):
|
def encode(xml, value):
|
||||||
"""encode given value inside DOM node"""
|
"""encode given value inside DOM node"""
|
||||||
if value:
|
if value:
|
||||||
path = cls.tagpath_head_last(tagpath)
|
head, last = cls.tagpath_head_last(tagpath)
|
||||||
node = createnode(xml, token)
|
node = createnode(xml, last)
|
||||||
writetext(node, str(value))
|
writetext(xml, node, head, str(value))
|
||||||
return node
|
return node
|
||||||
else:
|
else:
|
||||||
if req == mandatory:
|
if req == mandatory:
|
||||||
@@ -424,17 +430,19 @@ class autoxml(type):
|
|||||||
def gen_list_tag(cls, tag, spec):
|
def gen_list_tag(cls, tag, spec):
|
||||||
"""generate a list datatype"""
|
"""generate a list datatype"""
|
||||||
name, tag_type, req, path = cls.parse_spec(tag, spec)
|
name, tag_type, req, path = cls.parse_spec(tag, spec)
|
||||||
|
head, last = cls.tagpath_head_last(path)
|
||||||
|
|
||||||
if len(tag_type) != 1:
|
if len(tag_type) != 1:
|
||||||
raise Error('List type must contain only one element')
|
raise Error('List type must contain only one element')
|
||||||
|
|
||||||
def readtext(node, tagpath):
|
# def readtext(node, tagpath):
|
||||||
return getNodeText(getNode(node, tagpath))
|
# print 'shit', node, tagpath
|
||||||
def createnode(xml, tag):
|
# return getNodeText(node)
|
||||||
return xml.newNode(tag)
|
# def createnode(xml, tag):
|
||||||
def writetext(node, text):
|
# return xml.newNode(last)
|
||||||
node.addText(node, text)
|
# def writetext(node, text):
|
||||||
x = cls.gen_tag(tag, [tag_type[0], mandatory],
|
# node.addText(node, text)
|
||||||
readtext, createnode, writetext)
|
x = cls.gen_tag(last, [tag_type[0], mandatory])
|
||||||
(init_item, decode_item, encode_item, format_item) = x
|
(init_item, decode_item, encode_item, format_item) = x
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
@@ -447,16 +455,18 @@ class autoxml(type):
|
|||||||
if len(nodes) is 0 and req is mandatory:
|
if len(nodes) is 0 and req is mandatory:
|
||||||
raise Error('Mandatory list empty')
|
raise Error('Mandatory list empty')
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
l.append(decode_item(node))
|
dummy = node.ownerDocument.createElement(last)
|
||||||
|
dummy.appendChild(node)
|
||||||
|
l.append(decode_item(dummy))
|
||||||
return l
|
return l
|
||||||
|
|
||||||
def encode(xml, node, l):
|
def encode(xml, l):
|
||||||
|
dummy = xml.newNode("Dummy")
|
||||||
if len(l) > 0:
|
if len(l) > 0:
|
||||||
for item in l:
|
for item in l:
|
||||||
item_node = xml.newNode(path)
|
item_node = encode_item(xml, item)
|
||||||
encode_item(xml, item, item_node)
|
xml.addNodeUnder(dummy, last, item_node)
|
||||||
xml.addTextNodeUnder(item_node)
|
return getNode(dummy, "Dummy")
|
||||||
return node
|
|
||||||
else:
|
else:
|
||||||
if req is mandatory:
|
if req is mandatory:
|
||||||
raise Error('Mandatory list empty')
|
raise Error('Mandatory list empty')
|
||||||
@@ -519,11 +529,11 @@ class XmlFile(object):
|
|||||||
return self.dom.createTextNode(text)
|
return self.dom.createTextNode(text)
|
||||||
|
|
||||||
def newAttribute(self, attr):
|
def newAttribute(self, attr):
|
||||||
return self.dom.createAttribute(name)
|
return self.dom.createAttribute(attr)
|
||||||
|
|
||||||
# read helpers
|
# read helpers
|
||||||
|
|
||||||
def getNode(self, tagPath):
|
def getNode(self, tagPath = ""):
|
||||||
"""returns the *first* matching node for given tag path."""
|
"""returns the *first* matching node for given tag path."""
|
||||||
self.verifyRootTag()
|
self.verifyRootTag()
|
||||||
return getNode(self.dom.documentElement, tagPath)
|
return getNode(self.dom.documentElement, tagPath)
|
||||||
@@ -590,4 +600,5 @@ class XmlFile(object):
|
|||||||
|
|
||||||
def addTextNodeUnder(self, node, tagPath, text):
|
def addTextNodeUnder(self, node, tagPath, text):
|
||||||
"add a text node under given node with tag path (phew)"
|
"add a text node under given node with tag path (phew)"
|
||||||
|
print "addtextnodeunder", node, tagPath, text
|
||||||
return self.addNodeUnder(node, tagPath, self.newTextNode(text))
|
return self.addNodeUnder(node, tagPath, self.newTextNode(text))
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ class XmlFileTestCase(unittest.TestCase):
|
|||||||
print '*', string
|
print '*', string
|
||||||
#self.assert_(string.startswith('Name'))
|
#self.assert_(string.startswith('Name'))
|
||||||
xml = xmlfile.XmlFile('A')
|
xml = xmlfile.XmlFile('A')
|
||||||
a.encode(xml)
|
a.otherInfo.encode(xml)
|
||||||
xml.writexml('/tmp/a.xml')
|
xml.writexml('/tmp/a.xml')
|
||||||
|
print 'A DONE'
|
||||||
|
return
|
||||||
xml = xmlfile.XmlFile('A')
|
xml = xmlfile.XmlFile('A')
|
||||||
a2 = A()
|
a2 = A()
|
||||||
a2.name = "Baris Metin"
|
a2.name = "Baris Metin"
|
||||||
|
|||||||
Reference in New Issue
Block a user