import re import sys, os import datetime #=============================================== def readXML(theFileName): lines = file(theFileName,'rb').read() return lines #=============================================== def splitTags(theLines): # seems not working p2a = re.compile('|<[^>]+>') m2a = p2a.findall(theLines) #print m2a #for elm in m2a: # print elm return m2a #=============================================== def splitAttribute(theElement,theKey): p2a = re.compile(theKey+'=\"[^\"]+\"') m2a = p2a.findall(theElement) #print m2a try: elm = m2a[0] elm = elm[len(theKey)+2:] elm = elm[:-1] except: elm = "" return elm #=============================================== def setSpaces(theLevel): spc = "" for i in xrange(theLevel): spc += " " return spc #=============================================== def splitSmart(string, delimiter, subDelimiter): """ splits a string by 2 delimiters. input: string - the string to split delimiter - the first delimiter to split by subDelimiter - the second delimiter to split by, may be a substr of original delimiter """ a=[] for element in string.split(delimiter): b = element.split(subDelimiter) #a += [ele for ele in b if ele != ''] a += [ele for ele in b] return a #=============================================== def handleTree(theTree,theLine,theLevel,theIsTest): """ add new node to tree if prev line is leaf but not a test than delete it 0 - level 1 - 0=folder 1=test 2 - name """ if theIsTest == TYPE_CATEGORY and len(theTree) == 1: # category should be first element in tree tmp = theTree[0] theTree.append([theLevel,theIsTest,theLine]) theTree[0] = theTree[1] theTree[1] = tmp else: while True: elm1 = theTree[len(theTree)-1] if elm1[0] >= theLevel and elm1[1] == 0: del theTree[-1] else: break theTree.append([theLevel,theIsTest,theLine]) #=============================================== #globals TYPE_FOLDER = 0 TYPE_TEST = 1 TYPE_CATEGORY = 2 TYPE_TESTCASE = 3 TYPE_UNKNOWN = 10 TYPE_REQUIR = 11 TYPE_SPEC = 12 TYPE_PREREQUISITE = 13 TYPE_DESCR = 14 #=============================================== def parseTree_old(theLines): lines1 = theLines.replace("\r","") tags = splitTags(lines1) level = 1 listTree = [] listTree.append([level,0,"root"]) totalTests = 0 # 10-unknown, 11-require, 12-spec, 13-preq, 14-descr dataType = TYPE_UNKNOWN for e9 in tags: e9A = splitSmart(e9, " ", ">") if e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0][0:8] == "","") descp1 = descp1.replace("[","") cases[len(cases)-1][3] = descp1 a2 = [cat,fold,cases,testId,testDescp,testPrio,testCanoPath] return a2 #=============================================== def addTestCaseStep(theOldData): cat = theOldData[0] fold = theOldData[1] cases = theOldData[2] testId = theOldData[3] testDescp = theOldData[4] testPrio = theOldData[5] testCanoPath = theOldData[6] #replace description in last TC oldSteps = (cases[len(cases)-1][4]) cases[len(cases)-1][4] = oldSteps + 1 a2 = [cat,fold,cases,testId,testDescp,testPrio,testCanoPath] return a2 #=============================================== def replaceTestDescription(theOldData,theDescription): cat = theOldData[0] fold = theOldData[1] cases = theOldData[2] testId = theOldData[3] testDescp = theOldData[4] testPrio = theOldData[5] testCanoPath = theOldData[6] #replace description in last Test descp1 = theDescription.replace("]]>","") descp1 = descp1.replace("[","") a2 = [cat,fold,cases,testId,descp1,testPrio,testCanoPath] return a2 #=============================================== def parseTree(theLines,theDict): lines1 = theLines.replace("\r","") tags = splitTags(lines1) level = 1 listTree = [] listTree.append([level,0,"root"]) totalTests = 0 lastCategory = "" lastFolder="" folderList = [] lastTest = "" lastTestCase = "" isTestLastItem = True # 10-unknown, 11-require, 12-spec, 13-preq, 14-descr dataType = TYPE_UNKNOWN for e9 in tags: e9A = splitSmart(e9, " ", ">") if e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0] == "": pass elif e9A[0][0:8] == "",True) printHtml(theFileout,"",True) for elm in theListAll: if elm[1] == 1: type1 = "Test: " testsCount += 1 elif elm[1] == 2: type1 = " Data: " if theIsPrintData == False: continue else: type1 = "" g3 = elm[2] g3 = g3.replace("
","
\n "+setSpaces(elm[0])+setSpaces(len(type1))) g3 = g3.replace("
  • ","
  • "+setSpaces(elm[0])+setSpaces(len(type1))) if elm[1] == 2: printHtml(theFileout,"",False) elif elm[1] == 1: printHtml(theFileout,"",False) else: printHtml(theFileout,"",False) printHtml(theFileout,setSpaces(elm[0])+" "+type1+g3,True) printHtml(theFileout,"",False) ID += 1 printHtml(theFileout,"",True) printHtml(theFileout,"",True) print "total tests in tree=",testsCount #=============================================== def printGantt(theFileout,theListAll): ID = 1 testsCount = 0 printLine(fout,createMppHeader()) for elm in theListAll: if elm[1] == 1: type1 = "Test: " testsCount += 1 elif elm[1] == 2: #comment not printed in gantt continue else: type1 = "" K1 = createMppLine() #id K1[0] = str(ID) K1[1] = str(ID) #title K1[2] = type1+" "+elm[2] #level K1[5] = str(elm[0]) #duration K1[3] = str(1) #startdate,enddate,notBefore today = datetime.date.today() difference1 = datetime.timedelta(days=1) nextday = today+difference1 d1 = today.day m1 = today.month y1 = today.year d2 = nextday.day m2 = nextday.month y2 = nextday.year if elm[1] == 1: K1[8] = str(str(m1)+"/"+str(d1)+"/"+str(y1)) K1[9] = str(str(m2)+"/"+str(d2)+"/"+str(y2)) else: K1[8] = str(str(m1)+"/"+str(d1)+"/"+str(y1)) K1[9] = str(str(m2)+"/"+str(d2)+"/"+str(y2)) K1[23] = K1[8] printLine(fout,K1) ID += 1 print "total tests in tree=",testsCount #=============================================== def printHtml(theFileout,theLine,theIsNewLine): L1 = theLine.replace(' ', '  ') if theIsNewLine: theFileout.write(L1+"
    ") else: theFileout.write(L1) theFileout.write("\n") #=============================================== def printLine(theFileout,theLine): v1 = "\t".join(theLine) L1 = replaceHebrew(v1,False) theFileout.write(L1) theFileout.write("\n") #=============================================== def createMppHeader(): L1 = ["ID","Unique_ID","Task_Name","Duration","Type","Outline_Level", "Baseline_Duration","Predecessors","Start_Date","Finish_Date","Early_Start","Early_Finish","Late_Start", "Late_Finish","Free_Slack","Total_Slack","Leveling_Delay","Percent_Complete","Actual_Start", "Actual_Finish","Baseline_Start","Baseline_Finish","Constraint_Type","Constraint_Date", "Stop","Resume","Created","Scheduled_Work","Baseline_Work","Actual_Work","Cost","Fixed_Cost", "Baseline_Cost","Actual_Cost","Remaining_Cost","WBS","Priority","Milestone","Summary","Rollup","Text1", "Text2","Text3","Text4","Text5","Text6","Text7","Text8","Text9","Text10","Cost1","Cost2", "Cost3","Duration1","Duration2","Duration3","Flag1","Flag2","Flag3","Flag4","Flag5","Flag6", "Flag7","Flag8","Flag9","Flag10","Marked","Number1","Number2","Number3","Number4","Number5", "Subproject_File"] return L1 #=============================================== def createMppLine(): L1 = ['11', '11', 'rtrtrtr', '3 Days', 'ConstUnits', '2', '0 Days?', '', '2/7/10', '2/9/10', '2/7/10', '2/9/10', '2/7/10', '2/9/10', '0 Days', '0 Days', '0 Days-KKK', '0%', 'NA', 'NA', 'NA', 'NA', 'StartNotBefore', '2/7/10', 'NA', 'NA', '1/26/10', '0 HOURS', '0 HOURS', '0 HOURS', '$0.00', '$0.00', '$0.00', '$0.00', '$0.00', '2.2', '500', 'NONO', 'NONO', 'NONO', '', '', '', '', '', '', '', '', '', '', '$0.00', '$0.00', '$0.00', '0 Days', '0 Days', '0 Days', 'NONO', 'NONO', 'NONO', 'NONO', 'NONO', 'NONO', 'NONO', 'NONO', 'NONO', 'NONO', 'NONO', '0', '0','0', '0', '0', ''] return L1 #=============================================== def replaceHebrew(theLine,theFromHebrew): L1 = theLine S1 = ["\xe4\xfa\xe7\xec\xe4 \xec\xe0 \xec\xf4\xf0\xe9","StartNotBefore","\xe9\xee\xe9\xed","Days","\xe9\xe7\xe9\xe3\xe5\xfa \xf7\xe1\xe5\xf2\xe5\xfa","ConstUnits","\xee\xf9\xea \xf7\xe1\xe5\xf2","ConstDuration","\xee\xe5\xf7\xe3\xed \xeb\xeb\xec \xe4\xe0\xf4\xf9\xf8","ASAP","\xf9\xf2\xe5\xfa","HOURS","\xec\xe0","NONO","\xf7","KKK","\xeb\xef","YESYES"] if theFromHebrew: for v1 in xrange(0,len(S1),2): L1 = L1.replace(S1[v1],S1[v1+1]) else: for v1 in xrange(0,len(S1),2): L1 = L1.replace(S1[v1+1],S1[v1]) return L1 #=============================================== def returnDates(theSday,theSmonth,theSyear,theDuration): K2 = datetime.date(theSyear, theSmonth, theSday) duration = theDuration - 1 d1 = 1 K2A = K2+datetime.timedelta(d1-1) while duration > 0: d1 += 1 K2A = K2+datetime.timedelta(d1-1) if K2A.isoweekday() in [5,6]: # friday,saturday, (sunday=7) pass else: duration -= 1 #print duration,d1,K2A.day,K2A.month,K2A.year return [d1,K2A] #=============================================== def returnDuration(theSday,theSmonth,theSyear,theEday,theEmonth,theEyear): K2 = datetime.date(theSyear, theSmonth, theSday) K3 = datetime.date(theEyear, theEmonth, theEday) duration = 1 d1 = 1 K2A = K2+datetime.timedelta(d1-1) while K2A != K3: d1 += 1 K2A = K2+datetime.timedelta(d1-1) if K2A.isoweekday() in [5,6]: # friday,saturday, (sunday=7) pass else: duration += 1 return duration #=============================================== def ModifyRequirement(theReq): v1 = theReq v1 = v1.replace("
    ","") v1 = v1.replace("]]>","") v1 = v1.replace("\n","") v1 = v1.replace("\r","") return v1 #=============================================== def RequirementsCrossRef(theNameHeader,theFileout,theTree): """ each line in tree is: [theLevel,theIsTest,theLine] theFileout.write(L1) theFileout.write("\n") """ theFileout.write("\n") theFileout.write("\n") theFileout.write("\n") theFileout.write("\n") theFileout.write("\n") theFileout.write("\n") theFileout.write("Name: "+theNameHeader) theFileout.write("\n") theFileout.write("\n") ReqList = [] for elm in theTree: if elm[1] == 11: found = False v2 = ModifyRequirement(elm[2]) for e1 in ReqList: if e1 == v2: found = True break if found == False: ReqList.append(v2) for e1 in xrange(len(ReqList)): theFileout.write(str(e1)+": "+ReqList[e1]) theFileout.write("\n") theFileout.write("\n") theFileout.write("\n") for e1 in xrange(len(ReqList)): theFileout.write(","+str(e1)) theFileout.write("\n") folderList = [] currentTest = "" CurrentReq = [] for elm in theTree: if elm[0] > len(folderList): folderList.append(elm[2]) if elm[0] < len(folderList): for x1 in xrange(len(folderList) - elm[0] + 1): del folderList[-1] folderList.append(elm[2]) if elm[1] == 0 or elm[1] == 1: if len(currentTest) > 0: theFileout.write(currentTest) for e1 in ReqList: theFileout.write(",") for e2 in CurrentReq: if e2 == e1: theFileout.write("AAA") theFileout.write("\n") currentTest = "" CurrentReq = [] # keep new test if elm[1] == 1: currentTest = " / ".join(folderList) if elm[1] == 11: CurrentReq.append(ModifyRequirement(elm[2])) #=============================================== def GetFileName(theDefaultFileName,theIndex): """ """ tmpInFile = theDefaultFileName inFileName = raw_input("in File"+str(theIndex)+" : ["+tmpInFile+"] ") if inFileName == "": inFileName = tmpInFile return inFileName #=============================================== def ConvertToString(theList,theSeparator): txt2 = theSeparator.join(theList) return txt2 #=============================================== def CreateCsv_old(theFile,theTree): cat1 = "" path1 = [] isFirst = 1 testWithoutTestcase = 0 for elm in theTree: #print elm if elm[1] == TYPE_FOLDER: for i in range(elm[0]-1,len(path1)): del path1[elm[0]-1] path1.append(elm[2]) pass elif elm[1] == TYPE_TESTCASE: testCaseName = elm[2] testWithoutTestcase = 0 pass elif elm[1] == TYPE_TEST: if testWithoutTestcase == 1: testCaseName = "????" print "Test without Test Case",testName,testCaseName if isFirst == 0: #print cat1,path1,testName,testCaseName theFile.write(cat1+","+"|".join(path1[1:])+","+testName[0]+","+testName[1]+","+testName[2]+","+PreReq+","+Descr+","+testCaseName[0]+","+testCaseName[1]+","+testCaseName[2]+","+"TC de NA?") theFile.write("\n") else: theFile.write("category,folder,name,priority,canonicalpath,prerequisite,description,testcase name,Tcimplemented,TC useDescAsTestplan,TC description") theFile.write("\n"); testName = elm[2] Descr = "" PreReq = "" isFirst = 0 testWithoutTestcase = 1 pass elif elm[1] == TYPE_CATEGORY: cat1 = elm[2] pass elif elm[1] == TYPE_UNKNOWN: pass elif elm[1] == TYPE_REQUIR: pass elif elm[1] == TYPE_SPEC: pass elif elm[1] == TYPE_PREREQUISITE: PreReq = elm[2].replace(",",".") pass elif elm[1] == TYPE_DESCR: Descr = elm[2].replace(",",".") pass else: print "wrong type in tree"+str(elm[1]) #save last element theFile.write(cat1+","+"|".join(path1[1:])+","+testName[0]+","+testName[1]+","+testName[2]+","+PreReq+","+Descr+","+testCaseName[0]+","+testCaseName[1]+","+testCaseName[2]+","+"TC de NA?") theFile.write("\n") #=============================================== def prepareForCsv(theInput): tmpStr = theInput.replace(",",".") return tmpStr #=============================================== def CreateCsv(theFile,theTree): keys1 = theTree.keys() for e1 in xrange(len(keys1)): for e2 in xrange(len(keys1)): g1 = keys1[e2] g2 = theTree[g1] g3 = g2[3]-1 if (g3 == e1) and (g3 != e2): k1 = keys1[e1] k2 = theTree[k1] keys1[e1] = g1 keys1[e2] = k1 theFile.write("category,folder,name,priority,canonicalpath,prerequisite,description,testcase name,Tcimplemented,TC useDescAsTestplan,TC description,Steps,Result(0/1)") theFile.write("\n"); for e3 in xrange(len(keys1)): g2 = theTree[keys1[e3]] if len(g2[2]) == 0: theFile.write(prepareForCsv(g2[0])+",") theFile.write(prepareForCsv(g2[1])+",") theFile.write(prepareForCsv(keys1[e3])+",") theFile.write(prepareForCsv(str(g2[5]))+",") theFile.write(prepareForCsv(str(g2[6]))+",") theFile.write(""+",") theFile.write(prepareForCsv(g2[4])+",") theFile.write(""+",") theFile.write(""+",") theFile.write(""+",") theFile.write(""+",") theFile.write(""+",") theFile.write("----") theFile.write("\n") pass else: for e4 in xrange(len(g2[2])): theFile.write(prepareForCsv(g2[0])+",") theFile.write(prepareForCsv(g2[1])+",") theFile.write(prepareForCsv(keys1[e3])+",") theFile.write(prepareForCsv(str(g2[5]))+",") theFile.write(prepareForCsv(str(g2[6]))+",") theFile.write(""+",") theFile.write(prepareForCsv(g2[4])+",") theFile.write(prepareForCsv(g2[2][e4][0])+",") theFile.write(prepareForCsv(g2[2][e4][1])+",") theFile.write(prepareForCsv(g2[2][e4][2])+",") theFile.write(prepareForCsv(g2[2][e4][3])+",") theFile.write(prepareForCsv(str(g2[2][e4][4]))+",") theFile.write("") theFile.write("\n") #------------------ main -------------------------------------- print "xstudio-tests-to-csv Ver 1.3" inFileName = "testplan_2010-03-30.xml" newDir = "C:/yehuda/develop/python/xstudio-xml-results/current/python/src/examples" interactive1 = False if interactive1: curDir = os.getcwd()+"/examples" newDir = raw_input("current dir: ["+curDir+"] ") if newDir == "": newDir = curDir inFileName = GetFileName("testplan_2010-03-28.xml",1) outfname = newDir + "/"+inFileName + "_out.csv" fout = open(outfname,"w+") doc1 = readXML(newDir + "/"+inFileName) dictTree = {} tree1 = parseTree(doc1,dictTree) #CreateCsv_old(fout,tree1) CreateCsv(fout,dictTree) #print dictTree fout.close()