################################################################################# # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Frederic Quin. # # This simple but useful tool was created for the interest of my company. # You can use it and change it as well as you want... # # Please report bugs and suggests to me : # Frederic Quin # fquin@profile4u.com # # To know more about it, please read the README file # ################################################################################# import sys import string ################################################################################# # # # If you are not using this tool with Zope, you better try: # # from xml import * # # from pyexpat import * # # # ################################################################################# from Shared.DC.xml import * from Shared.DC.xml.pyexpat import * ################################################################################# # # # A Class which uses pyexpat module to generate a dictionary from a xml string # # # ################################################################################# class XMLStringToDictionary: # A Handler of pyexpat module def start_element(self, name, attrs): # Go to the right knot of the tree index = self.xml_dict for i in self.tags_stack: index = index[i] # Build the key of the current dictionary i = 1 dict_key = name + '_' + str(i) while index.has_key(dict_key): i = i + 1 dict_key = name + '_' + str(i) # Build the value indexed by the current key i = 0 index[dict_key] = {} while ( i < len(attrs) ): index[dict_key][attrs[i]] = attrs[i+1] i = i + 2 self.tags_stack.append( dict_key ) print "start : name=" + name + "; attrs=" + str(attrs) + "; stack=" + str(self.tags_stack) + "; dict=" + str(self.xml_dict) # Another handler def end_element(self, name): self.tags_stack.pop() # print "end : name=" + name + "; stack=" + str(self.tags_stack) + "; dict=" + str(self.xml_dict) # Another one... def char_data(self, data): index = self.xml_dict # Go to the right knot of the tree for i in self.tags_stack: index = index[i] # Update the value indexed by this knot index['value'] = data # print "data : data=" + data + "; stack=" + str(self.tags_stack) + "; dict=" + str(self.xml_dict) # New constructor for this class def __init__(self): self.xml_dict = {} self.tags_stack = [] # One method is enough def parseXML( self, xml_string ): p = ParserCreate() p.StartElementHandler = self.start_element p.EndElementHandler = self.end_element p.CharacterDataHandler= self.char_data if (len(xml_string) > 0): p.Parse(xml_string) return self.xml_dict ################################################################################# # # # A simple function to use this tool. You can use it as an External Method... # # # ################################################################################# def XMLStringToDict( xml_string ): parser = XMLStringToDictionary() return parser.parseXML( xml_string ) ################################################################################# # # # An example of Class you can use in association with Z SQL Methods. # # It's impossible with the first one. # # Read the README file to know more about it... # # # # In the following example, self.XMLSTRING is the current result of the column # # XMLSTRING... # # # ################################################################################# class ZXMLStringToDictionary: def parseXML( self ): parser = XMLStringToDictionary() return parser.parseXML( self.XMLSTRING ) ################################################################################# # # # The reverse engineering : generate a xml string from a dictionary # # # ################################################################################# # Sub function which test the tag to know if there is attributes, value and sub-tags def testTag( xml_dict ): has_attribs = 0 has_value = 0 has_subtags = 0 for i in xml_dict.keys(): if (i == 'value'): has_value = 1 elif (type(xml_dict[i]) == type(xml_dict)): has_subtags = 1 else: has_attribs = 1 return [ has_attribs, has_value, has_subtags ] # Sub function which return the attributes string def tagAttributesToString( xml_dict ): attribs_string = "" attribs = [] for i in xml_dict.keys(): if ((type(xml_dict[i]) != type(xml_dict)) and (i != 'value')): attribs.append( i ) for attrib in attribs: attribs_string = attribs_string + " " + attrib + "=\"" + xml_dict[attrib] + "\"" return attribs_string # Main function def XMLDictionaryToString( xml_dict ): xml_string = "" tags = [] # List the tag names of the tree for key in xml_dict.keys(): if (type(xml_dict[key]) == type(xml_dict)): tags.append( key ) # Treat the tags for tag in tags: real_name_tag = tag[:string.rfind(tag, "_")] tests = testTag( xml_dict[tag] ) has_attribs = tests[0] has_value = tests[1] has_subtags = tests[2] tag_closed = 0 if (has_attribs == 0): xml_string = xml_string + "<" + real_name_tag + ">" if (has_value == 1): xml_string = xml_string + xml_dict[tag]['value'] if (has_subtags == 1): xml_string = xml_string + XMLDictionaryToString( xml_dict[tag] ) else: xml_string = xml_string + "<" + real_name_tag + tagAttributesToString( xml_dict[tag] ) if (has_value == 0): if (has_subtags == 0): xml_string = xml_string + " />" tag_closed = 1 else: xml_string = xml_string + ">" + XMLDictionaryToString( xml_dict[tag] ) else: xml_string = xml_string + '>' + xml_dict[tag]['value'] if (has_subtags == 1): xml_string = xml_string + XMLDictionaryToString( xml_dict[tag] ) if (tag_closed == 0): xml_string = xml_string + "" return xml_string if __name__ == '__main__': xml = "" print xml, "\n\n" dict = XMLStringToDict( xml ) print dict, "\n\n" xml = XMLDictionaryToString(dict) print xml