Only the first open port in the <ports> </ports> tag is listed in the CSV output file; no other open ports are listed. The output is printed to the csv file but only the first line in the ports tag is output to the csv file. You can try by run the nmap command "nmap -sV -Pn -oX Output_3.xml scanme.nmap.org"
`import xml.etree.ElementTree as ET
import csv
def main():
in_xml_port = 'Output_1.xml'
xml_tree_port = ET.parse(in_xml_port)
xml_root_port = xml_tree_port.getroot()
# To save the output to csv file
with open('detected_hosts.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['IP', 'Hostname', 'Status', 'Port', 'Service', 'Protocol', 'Product'])
for host in xml_root_port.findall('host'):
# finding all the necessary details from the xml tags
master_ip = host.find('address').get('addr')
master_hostnames = host.findall('hostnames')
master_hostname = master_hostnames[0].findall('hostname')[0].attrib['name']
port_status = host.findall('ports')
port_status_1 = port_status[0].findall('port')
port_state = port_status_1[0].findall('state')[0].attrib['state']
port_element = host.findall('ports')
port_id = port_element[0].findall('port')[0].attrib['portid']
open_service = host.findall('ports')
open_service_1 = open_service[0].findall('port')
service_name = open_service_1[0].findall('service')[0].attrib['name']
potocol_element = host.findall('ports')
port_protocol = potocol_element[0].findall('port')[0].attrib['protocol']
product_element = host.findall('ports')
product_element_1 = product_element[0].findall('port')
product_name = product_element_1[0].findall('service')[0].attrib['product']
if port_state == 'open':
host_status = 'open'
writer.writerow([master_ip, master_hostname, port_state, port_id, service_name, port_protocol, product_name])
if __name__ == '__main__':
main()`