python xml 转换csv ,csv 转换xml

来源:互联网 发布:横幅广告制作软件 编辑:程序博客网 时间:2024/05/21 09:26
#!/usr/bin/python
#encoding:utf-8


import os
import csv
import re
import sys
import platform
import logging  
import logging.handlers


from xml.etree import ElementTree


LOG = None
LOG_LEVEL = logging.DEBUG


class ColorFormatter(logging.Formatter):


    def __init__(self, msg):
        logging.Formatter.__init__(self, msg)


    def format(self, record):
        red, green, yellow, blue = range(4)
        colors = {'INFO': green, 'DEBUG': blue,
                  'WARNING': yellow, 'ERROR': red}
        msg = record.msg
        if msg[0] == "+":
            msg = "\33[01m" + msg[1:] + "\033[0m"
        elif msg[0] == "=":
            msg = "\33[07m" + msg + "\033[0m"
        levelname = record.levelname
        if levelname in colors:
            msg_color = "\033[0;%dm" % (
                31 + colors[levelname]) + msg + "\033[0m"
            record.msg = msg_color


        return logging.Formatter.format(self, record)






def csv2full(csv_path, split_sign):
    if not os.path.isfile(csv_path):
        print '%s is not a file' % csv_path
        return
    name, ext = os.path.splitext(csv_path)
    if not ext == '.csv':
        print '%s is not a csv' % csv_path
        return
#    print '== Convert csv to xml start=='
    LOG.info("+Convert csv to xml start ...")
    csv_file = file(csv_path, 'rb')
    csv_file.readline()
    reader = csv.reader(csv_file)
    csv_content = []
    for line in reader:
        csv_content.append(line)


    csv_file.close()
    suite_name = csv_content[0][16].split('/')[2]
    category_name = csv_content[0][12]
    set_name = name.split(split_sign)[-1]
    folder = os.path.dirname(csv_path)
#    folder = os.getcwd()
    full_test_path = '%s%stests.full(%s).xml' % (folder, split_sign, set_name)
    make_full_test(csv_content, full_test_path, suite_name, set_name, category_name)
#    print 'General %s' % full_test_path
    LOG.info('General %s' % full_test_path)
    test_path = '%s%stests(%s).xml' % (folder, split_sign, set_name)
    make_test(csv_content, test_path, suite_name, set_name, category_name)
#    print 'General %s' % test_path
    LOG.info('General %s' % test_path)
#    print '== Convert csv to xml finish=='
    LOG.info("== Convert csv to xml finish==")




def make_full_test(csv_content, full_test_name, suite_name, set_name, category_name):
    full_test_file = open(full_test_name, 'w')
    content = '<?xml version="1.0" encoding="UTF-8"?>\n<?xml-stylesheet type="text/xsl" href="./testcase.xsl"?>\n<test_definition>\n  <suite name="%s" launcher="WRTLauncher" category="%s">\n    <set name="%s">' % (suite_name, category_name, set_name)
    for line in csv_content:
        content += '\n      <testcase purpose="%s" type="%s" status="%s" component="%s" execution_type="%s" priority="%s" id="%s">\n        <description>\n          <test_script_entry>%s</test_script_entry>\n        </description>\n        <specs>\n          <spec>\n            <spec_assertion element_type="%s" element_name="%s" interface="%s" specification="%s" section="%s" category="%s"/>\n            <spec_url>%s</spec_url>\n            <spec_statement/>\n          </spec>\n        </specs>\n      </testcase>' % (line[1],
         line[17],
         line[15],
         line[2],
         line[4],
         line[6],
         line[0],
         line[16],
         line[7],
         line[8],
         line[9],
         line[10],
         line[11],
         line[12],
         line[13])


    content += '\n    </set>\n  </suite>\n</test_definition>'
    full_test_file.seek(0)
    full_test_file.truncate()
    full_test_file.write(content)
    full_test_file.close()




def make_test(csv_content, test_name, suite_name, set_name, category_name):
    test_file = open(test_name, 'w')
    content = '<?xml version="1.0" encoding="UTF-8"?>\n<?xml-stylesheet type="text/xsl" href="./testcase.xsl"?>\n<test_definition>\n  <suite name="%s" category="%s" launcher="WRTLauncher">\n    <set name="%s">' % (suite_name, category_name, set_name)
    for line in csv_content:
        content += '\n      <testcase component="%s" execution_type="%s" id="%s" purpose="%s">\n        <description>\n          <test_script_entry>%s</test_script_entry>\n        </description>\n      </testcase>' % (line[2],
         line[4],
         line[0],
         line[1],
         line[16])


    content += '\n    </set>\n  </suite>\n</test_definition>'
    test_file.seek(0)
    test_file.truncate()
    test_file.write(content)
    test_file.close()




def xml2csv(xml_path, split_sign):
    if not os.path.isfile(xml_path):
        print '%s is not a file' % xml_path
        return
    name, ext = os.path.splitext(xml_path)


    if not ext == '.xml':
        print '%s is not a xml' % xml_path
        return
    if not name.split(split_sign)[-1] == 'tests.full':
        print name
        print '%s is not tests.full.xml' % xml_path
        return
#    print '== Convert xml to csv start=='
    LOG.info("+Convert xml to csv start ...")
    folder = os.path.dirname(xml_path)
#    folder = os.getcwd()
    csv_path = folder + split_sign
    make_csv(xml_path, csv_path)
#    print '== Convert xml to csv finish=='
    LOG.info("===Convert xml to csv finish===")


def make_csv(xml_path, csv_path):
    root_node = ElementTree.parse(xml_path)
    set_node = root_node.find('suite/set')
    csv_file_name = set_node.attrib['name']
    csv_path += csv_file_name + '.csv'
#    print 'General %s' % csv_path
    LOG.info("General: %s" % csv_path)
    writer = csv.writer(file(csv_path, 'wb'))
    writer.writerow(['Name',
     'Description',
     'Component',
     'Onload_Delay',
     'Execution_Type',
     'Package',
     'Priority',
     'ElementType',
     'ElementName',
     'Interface',
     'Specification',
     'Section',
     'Category',
     'SpecURL',
     'SpecStatement',
     'Status',
     'Test_Script_Entry',
     'Type',
     'PreCondition',
     'PostCondition',
     'StepNumber',
     'StepDescription',
     'StepExpectedResult'])
    case_nodes = set_node.findall('testcase')
    for case_node in case_nodes:
        spec_assertion = case_node.find('specs/spec/spec_assertion')
        writer.writerow([case_node.attrib['id'],
         case_node.attrib['purpose'],
         case_node.attrib['component'],
         '',
         case_node.attrib['execution_type'],
         '',
         case_node.attrib['priority'],
         spec_assertion.attrib['element_type'],
         spec_assertion.attrib['element_name'],
         spec_assertion.attrib['interface'],
         spec_assertion.attrib['specification'],
         spec_assertion.attrib['section'],
         spec_assertion.attrib['category'],
         case_node.find('specs/spec/spec_url').text,
         '',
         case_node.attrib['status'],
         case_node.find('description/test_script_entry').text,
         case_node.attrib['type'],
         '',
         '',
         '1',
         '',
         'pass'])


def checkpath(xml_path, split_sign):
    LOG.info("+Check case path, id and purpose start ...")
    root_node = ElementTree.parse(xml_path)
    set_node = root_node.find('suite/set')
    case_nodes = set_node.findall('testcase')
    id_list = []
    purpose_list = []
    for case_node in case_nodes:
        verify_path =  os.path.dirname(xml_path)
        casepath = case_node.find('description/test_script_entry').text
        id_list.append(case_node.attrib['id'])
        purpose_list.append(case_node.attrib['purpose'])
        arraypath =  casepath.split('?')[0].split(split_sign)
        del arraypath[0]
        del arraypath[0]
        del arraypath[0]
        for i in range(len(arraypath)):
            verify_path += split_sign + arraypath[i]
            
        if not os.path.exists(verify_path):
            LOG.warning("path no found: " + verify_path)
    temp_array = []
    for xid in range(len(id_list)):
        if id_list.count(id_list[xid]) > 1 and id_list[xid] not in temp_array: 
            LOG.warning(str(id_list.count(id_list[xid])) + " same id : " + id_list[xid])
            temp_array.append(id_list[xid])
    del temp_array[:]
    for xpurpose in range(len(purpose_list)):
        if purpose_list.count(purpose_list[xpurpose]) > 1 and purpose_list[xpurpose] not in temp_array: 
            LOG.warning(str(purpose_list.count(purpose_list[xpurpose])) + " same purpose: " + purpose_list[xpurpose])
            temp_array.append(purpose_list[xpurpose])
    del temp_array[:]
    LOG.info("===Check case path, id and purpose finish===")
    
def ergodic_folder(root_path, split_sign):
    if not os.path.isdir(root_path):
        print 'Error: %s is not a directory!' % root_path
        return
    print '== Scan and generate mk files in package folder start=='
    paths = [ item for item in os.walk(root_path) ]


    for path, dirs, files in paths:
        folder = path.split(split_sign)[-1]
        if folder.count('-') == 3:
            print 'Find a package folder:', folder
            generate_mk(path)


    print '== Scan and generate mk files in package folder finish=='




def generate_mk(package_folder):
    common_dir_str = 'commondir ='
    SUBDIRS_str = 'SUBDIRS ='
    testdefdir_str = 'testdefdir = $(datadir)/'
    dist_testdef_DATA_str = 'dist_testdef_DATA = tests.xml'
    docdir_str = 'docdir = /opt/'
    dist_doc_DATA_str = 'dist_doc_DATA ='
    subs = os.listdir(package_folder)
    print os.sep
    for sub in subs:
        if os.path.isdir(package_folder + os.sep + sub):
            if sub in ('resources', 'common', 'testkit'):
                common_dir_str += ' ' + sub
            else:
                SUBDIRS_str += ' ' + sub
        elif sub == 'tests.ext.xml':
            dist_testdef_DATA_str += ' ' + sub
        elif sub in ('Changelog', 'COPYING', 'README'):
            dist_doc_DATA_str += ' ' + sub


    SUBDIRS_str += ' $(commondir)'
    testdefdir_str += package_folder
    docdir_str += package_folder
    mk_file_path = package_folder + os.sep + 'Makefile.am'
    mk_file = open(mk_file_path, 'w')
    mk_file.write(common_dir_str + '\n' + SUBDIRS_str + '\n' + testdefdir_str + '\n' + dist_testdef_DATA_str + '\n' + docdir_str + '\n' + dist_doc_DATA_str)
    mk_file.close()
    print '----generate a mk file:%s' % mk_file_path




HEAD = [['<!DOCTYPE html>\n', 'Wrong doctype'],
 ['<!--\n', 'Wrong copyright'],
 ['Copyright (c) 2013 Intel Corporation.\n', 'Wrong copyright'],
 ['\n', 'Wrong copyright'],
 ['Redistribution and use in source and binary forms, with or without modification,\n', 'Wrong copyright'],
 ['are permitted provided that the following conditions are met:\n', 'Wrong copyright'],
 ['\n', 'Wrong copyright'],
 ['* Redistributions of works must retain the original copyright notice, this list\n', 'Wrong copyright'],
 ['  of conditions and the following disclaimer.\n', 'Wrong copyright'],
 ['* Redistributions in binary form must reproduce the original copyright notice,\n', 'Wrong copyright'],
 ['  this list of conditions and the following disclaimer in the documentation\n', 'Wrong copyright'],
 ['  and/or other materials provided with the distribution.\n', 'Wrong copyright'],
 ['* Neither the name of Intel Corporation nor the names of its contributors\n', 'Wrong copyright'],
 ['  may be used to endorse or promote products derived from this work without\n', 'Wrong copyright'],
 ['  specific prior written permission.\n', 'Wrong copyright'],
 ['\n', 'Wrong copyright'],
 ['THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"\n', 'Wrong copyright'],
 ['AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n', 'Wrong copyright'],
 ['IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n', 'Wrong copyright'],
 ['ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,\n', 'Wrong copyright'],
 ['INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n', 'Wrong copyright'],
 ['BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n', 'Wrong copyright'],
 ['DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n', 'Wrong copyright'],
 ['OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n', 'Wrong copyright'],
 ['NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n', 'Wrong copyright'],
 ['EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n', 'Wrong copyright'],
 ['\n', 'Wrong copyright'],
 ['Authors:\n', 'Wrong copyright'],
 ['\n', 'Wrong author format'],
 ['\n', 'Wrong copyright'],
 ['-->\n', 'Wrong copyright'],
 ['\n', 'Wrong copyright']]
DEFINE = [['<meta charset="utf-8">', 'Wrong meta format'],
 ['<title>[Test Area]: [Title/Scope of Test]</title>', 'Wrong title format'],
 ['<link rel="author" title="Intel" href="http://www.intel.com">', 'Wrong author link format'],
 ['<link rel="help" href="http://www.w3.org/TR/[direct link to tested section]">', 'Wrong help link format'],
 ['<script src="/resources/testharness.js"></script>', 'Wrong copyright'],
 ['<script src="/resources/testharnessreport.js"></script>', 'Wrong copyright'],
 ['<link rel="stylesheet" href="/resources/testharness.css">', 'Wrong copyright'],
 ['<div id="log"></div>', 'Wrong copyright'],
 ['<script>', 'Wrong copyright'],
 ['', 'Wrong copyright']]


def echo_error(error, line, file):
    print '%s at line %d %s' % (error, line, file)




def check_file_format(file_path, split_sign, fix):
    if split_sign + 'w3c' + split_sign in file_path or split_sign + 'testkit' + split_sign in file_path:
        return
    line_index = 0
    new_content = ''
    file_content = open(file_path, 'r+')
    for line in file_content.readlines():
        line_index += 1
        if 33 > line_index:
            if line_index == 29:
                reg = re.compile('^\\s{8}\\w+\\.\\w+\\s<\\w+\\.\\w+@intel\\.com>$')
                if not reg.match(line):
                    echo_error(HEAD[line_index - 1][1], line_index, file_path)
            elif HEAD[line_index - 1][0] != line:
                echo_error(HEAD[line_index - 1][1], line_index, file_path)
        else:
            while '\t' in line:
                print 'Find tab at line %d %s' % (line_index, file_path)
                if fix:
                    line = line.replace('\t', '  ')
                    print 'Fix the tab at line %d', line_index
                else:
                    break


            while line[-2:-1] == ' ':
                print 'Find space at line %d %s' % (line_index, file_path)
                if fix:
                    line = line[:-2] + line[-1]
                    print 'Fix the space at line %d' % line_index
                else:
                    break


            while line == '\n':
                print 'Find null line at line %d %s' % (line_index, file_path)
                if fix:
                    line = ''
                    print 'Fix the null line at line %d' % line_index
                else:
                    break


        new_content += line


    file_content.seek(0)
    file_content.truncate()
    file_content.write(new_content)
    file_content.close()




def ergodic_file(root_path, split_sign, fix):
    if not os.path.isdir(root_path):
        print 'Error: %s is not a directory!' % root_path
        return
    if fix:
        print '== Check and fix errors in html files start =='
    else:
        print '== Check errors in html files start =='
    paths = [ item for item in os.walk(root_path) ]
    for path, dirs, files in paths:
        for filename in files:
            if filename.endswith('.html'):
                file_path = path + os.sep + filename
                if ' ' in file_path:
                    print 'Find space in file path %s' % file_path
                    if fix:
                        new_file_path = path + os.sep + filename.replace(' ', '')
                        os.rename(file_path, new_file_path)
                        print 'Fixed file path %s' % new_file_path
                        file_path = new_file_path
                check_file_format(file_path, split_sign, fix)


    if fix:
        print '== Check and fix errors in html files finish =='
    else:
        print '== Check errors in html files finish =='




def echo_about():
    """
    This function will print the user guide and stop toolkit.
    """
    about = 'Xwalk TC Toolkit V1.7\n-c <path>  |  Check the code format of html files under the <path>, except files under w3c and testkit folder.\n              Reference:\n                http://testthewebforward.org/docs/test-templates.html\n                https://otctools.jf.intel.com/review/#/c/7776/\n-f <path>  |  Auto fix all the errors after check the code format.\n-m <path>  |  Generate the Makefile.am file under the package folder in the <path> and its sub folders.\n-v <path>  |  Convert csv file to tests.full.xml and tests.xml\n-b <path>  |  Convert tests.full.xml to csv file.\n-P <path>  | Check case path, id and purpose are wright\n'
    print about
    sys.exit()




def main():
    """
    main function will call different functions according to the command line argvs followed the toolkit.
    """
    global LOG
    LOG = logging.getLogger("pack-tool")
    LOG.setLevel(LOG_LEVEL)
    stream_handler = logging.StreamHandler()
    stream_handler.setLevel(LOG_LEVEL)
    stream_formatter = ColorFormatter("[%(asctime)s] %(message)s")
    stream_handler.setFormatter(stream_formatter)
    LOG.addHandler(stream_handler)


    sys_name = platform.system()
    if sys_name == 'Windows':
        split_sign = '\\'
    elif sys_name == 'Linux':
        split_sign = '/'
    if len(sys.argv) != 3:
        print 'Error: No enough argv!'
        echo_about()
    else:
        {'-c': lambda : ergodic_file(sys.argv[2], split_sign, False),
         '-f': lambda : ergodic_file(sys.argv[2], split_sign, True),
         '-m': lambda : ergodic_folder(sys.argv[2], split_sign),
         '-v': lambda : csv2full(sys.argv[2], split_sign),
         '-p': lambda : checkpath(sys.argv[2], split_sign),
         '-b': lambda : xml2csv(sys.argv[2], split_sign)}[sys.argv[1]]()




if __name__ == '__main__':
    main()
# decompiled 1 files: 1 okay, 0 failed, 0 verify failed
# 2014.08.05 11:22:39 CST
0 0
原创粉丝点击