#python
#python
Вопрос:
У меня есть скрипт на Python 3.7.3, который считывает XML, анализирует то, что мне нужно, и должен экспортировать результаты в CSV. Мне пришлось углубиться в XML-дерево, используя цикл for in для одного из полей, который показывает, как другие операторы for in добавляются в csv.
При выполнении приведенного ниже моего выходного файла не отображаются разные V-ID (обратитесь к третьему дочернему оператору for в root …), однако все остальные поля верны. V-ID отображается правильно, когда я удаляю последнюю инструкцию for in и перемещаю инструкцию firstFile.write на 2 вкладки влево, но тогда у меня нет статуса, поэтому я знаю, что проблема в последней инструкции. Кстати, если я переместу оператор firstFile.write полностью влево, он вернет только одну строку в csv, но их должно быть 5.
Есть ли способ создать список из выходных данных, а затем объединить их все, или, возможно, переместить инструкцию firstFile.write на две вкладки влево и добавить последнюю инструкцию for in в определенный столбец (по сути, разбив инструкцию firstFile.write)? Или у вас есть какие-либо другие предложения?
import os
import sys
import glob
import xml.etree.ElementTree as ET
firstFile = open("myfile.csv", "a")
firstFile.write("V-ID,")
firstFile.write("HostName,")
firstFile.write("Status,")
firstFile.write("Comments,")
firstFile.write("Finding Details,")
firstFile.write("STIG Name,")
basePath = os.path.dirname(os.path.realpath(__file__))
xmlFile = os.path.join(basePath, "C:\Users\myUserName\Desktop\Scripts\Python\XMLtest.xml")
tree = ET.parse(xmlFile)
root = tree.getroot()
for child in root.findall('{http://checklists.nist.gov/xccdf/1.2}title'):
d = child.text
for child in root:
for children in child.findall('{http://checklists.nist.gov/xccdf/1.2}target'):
b = children.text
for child in root.findall('{http://checklists.nist.gov/xccdf/1.2}Group'):
x = (str(child.attrib))
x = (x.split('_')[6])
a = x[:-2]
for child in root:
for children in child:
for childrens in children.findall('{http://checklists.nist.gov/xccdf/1.2}result'):
x = childrens.text
if ('pass' in x):
c = 'Completed'
else:
c = 'Ongoing'
firstFile.write("n" a ',' b ',' c ',' ',' ',' d)
firstFile.close()
Комментарии:
1. Не могли бы вы, пожалуйста, приложить свой XMLtest.xml файл?
2. Также было бы неплохо, если бы вы опубликовали ожидаемый файл CSV, чтобы лучше понять вашу проблему
3. это своего рода отстой, но я не могу опубликовать XML, он является собственностью моего работодателя. Однако я обновлю свой основной пост с использованием формата CSV.
4. Было бы, безусловно, полезно, если вы публикуете исходный XML, нам нужно понимать структуру, чтобы вы могли удалить все записи, кроме одной или двух, и заменить данные некоторыми заполнителями
5. К настоящему моменту я могу сказать, что вы перебираете записи неправильным образом. Вы выполняете итерацию по первому полю (title), затем по второму полю (target) и из каждого столбца сохраняете только последнее значение. Что вам нужно сделать, это выполнить итерацию по записям (не отдельным полям), а затем получить данные из каждой записи и записать в файл.
Ответ №1:
Наконец, потребовалось около недели, чтобы разобраться в этом. Я преобразовал выходные данные в CSV, затем прочитал их обратно в список для каждого столбца, проанализировал пробелы и записал их снова. Ниже показано, как я это сделал.
import os
import sys
import glob
import csv
import xml.etree.ElementTree as ET
firstFile = open("myfile.csv", "a")
path = 'C:\Users\JT\Desktop\Scripts\Python\xccdf\'
for fileName in glob.glob(os.path.join(path, '*.xml')):
with open('C:\Users\JT\Desktop\Scripts\Python\myfile1.csv', 'w', newline='') as csvFile1:
csvWriter = csv.writer(csvFile1, delimiter=',')
# do your stuff
tree = ET.parse(fileName)
root = tree.getroot()
# Stig Title
for child in root.findall('{http://checklists.nist.gov/xccdf/1.2}title'):
d = child.text
# hostName
for child in root:
for children in child.findall('{http://checklists.nist.gov/xccdf/1.2}target'):
b = children.text
# V-ID
for child in root.findall('{http://checklists.nist.gov/xccdf/1.2}Group'):
x = (str(child.attrib))
x = (x.split('_')[6])
a = x[:-2]
firstFile.write(a 'n')
# Status
for child in root:
for children in child:
for childrens in children.findall('{http://checklists.nist.gov/xccdf/1.2}result'):
x = childrens.text
firstFile.write(',' b ',' x ',' ',' ',' d 'n')
with open('C:\Users\JT\Desktop\Scripts\Python\myfile.csv', 'r') as csvFile:
csvReader = csv.reader(csvFile, delimiter=',')
vIDs = []
hostNames = []
status = []
stigTitles = []
for line in csvReader:
vID = line[0]
vIDs.append(vID)
try:
hostName = line[1]
hostNames.append(hostName)
except:
pass
try:
state = line[2]
status.append(state)
except:
pass
try:
stigTitle = line[5]
stigTitles.append(stigTitle)
except:
pass
with open('C:\Users\JT\Desktop\Scripts\Python\myfile1.csv', 'a', newline='') as csvFile1:
csvWriter = csv.writer(csvFile1, delimiter=',')
vIDMod = list(filter(None, vIDs))
hostNameMod = list(filter(None, hostNames))
statusMod = list(filter(None, status))
stigTitlesMod = list(filter(None, stigTitles))
csvWriter.writerows(zip(vIDMod, hostNameMod, statusMod, stigTitlesMod))
firstFile.close()