00001 """
00002 Copyright 2008 Free Software Foundation, Inc.
00003 This file is part of GNU Radio
00004
00005 GNU Radio Companion is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009
00010 GNU Radio Companion is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 GNU General Public License for more details.
00014
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00018 """
00019
00020
00021
00022
00023 from lxml import etree
00024 from Utils import odict
00025
00026 XMLSyntaxError = etree.XMLSyntaxError
00027
00028 def validate_dtd(xml_file, dtd_file=None):
00029 """!
00030 Validate an xml file against its dtd.
00031 @param xml_file the xml file
00032 @param dtd_file the optional dtd file
00033 @throws Exception validation fails
00034 """
00035 if dtd_file:
00036 dtd = etree.DTD(dtd_file)
00037 xml = etree.parse(xml_file)
00038 if not dtd.validate(xml.getroot()):
00039 raise XMLSyntaxError, '\n'.join(map(str, dtd.error_log.filter_from_errors()))
00040 else:
00041 parser = etree.XMLParser(dtd_validation=True)
00042 xml = etree.parse(xml_file, parser=parser)
00043 if parser.error_log:
00044 raise XMLSyntaxError, '\n'.join(map(str, parser.error_log.filter_from_errors()))
00045
00046 def from_file(xml_file):
00047 """!
00048 Create nested data from an xml file using the from xml helper.
00049 @param xml_file the xml file path
00050 @return the nested data
00051 """
00052 xml = etree.parse(xml_file).getroot()
00053 return _from_file(xml)
00054
00055 def _from_file(xml):
00056 """!
00057 Recursivly parse the xml tree into nested data format.
00058 @param xml the xml tree
00059 @return the nested data
00060 """
00061 tag = xml.tag
00062 if not len(xml):
00063 return odict({tag: xml.text or ''})
00064 nested_data = odict()
00065 for elem in xml:
00066 key, value = _from_file(elem).items()[0]
00067 if nested_data.has_key(key): nested_data[key].append(value)
00068 else: nested_data[key] = [value]
00069
00070 for key, values in nested_data.iteritems():
00071 if len(values) == 1: nested_data[key] = values[0]
00072 return odict({tag: nested_data})
00073
00074 def to_file(nested_data, xml_file):
00075 """!
00076 Write an xml file and use the to xml helper method to load it.
00077 @param nested_data the nested data
00078 @param xml_file the xml file path
00079 """
00080 xml = _to_file(nested_data)[0]
00081 open(xml_file, 'w').write(etree.tostring(xml, xml_declaration=True, pretty_print=True))
00082
00083 def _to_file(nested_data):
00084 """!
00085 Recursivly parse the nested data into xml tree format.
00086 @param nested_data the nested data
00087 @return the xml tree filled with child nodes
00088 """
00089 nodes = list()
00090 for key, values in nested_data.iteritems():
00091
00092 if not isinstance(values, (list, set, tuple)):
00093 values = [values]
00094 for value in values:
00095 node = etree.Element(key)
00096 if isinstance(value, (str, unicode)): node.text = value
00097 else: node.extend(_to_file(value))
00098 nodes.append(node)
00099 return nodes
00100
00101 if __name__ == '__main__':
00102 """Use the main method to test parse xml's functions."""
00103 pass