Cisco DevNet Associate course 005 Software Development and Design Parsing of common data format XML to Python data structures
Watch Full Demo on YouTube:
Introduction:
In the world of software development and network automation, data rarely comes in a neatly organized format. More often than not, it’s structured in formats like XML, JSON, or YAML — especially when dealing with configuration files, APIs, or network device outputs.
In a previous lesson, we explored what XML is and how it’s structured. Now, let’s go one step further: parsing XML data into Python.
Whether you’re preparing for your Cisco DevNet Associate certification or just want to build confidence working with structured data, parsing XML is a key skill that will help you interact with configuration files, API responses, and more.
🗂 Sample XML File: device.xml
Let’s imagine a scenario where you’re working with network device configurations. You receive this configuration as an XML file:
<?xml version="1.0" encoding="UTF-8"?>
<NetworkDeviceConfig>
<Device>
<Hostname>Router01</Hostname>
<Location>DataCenter1</Location>
<Vendor>Cisco</Vendor>
<Model>ISR4451-X</Model>
<OSVersion>IOS-XE 17.9.3</OSVersion>
</Device>
<Interfaces>
<Interface>
<Name>GigabitEthernet0/0</Name>
<Description>WAN Link</Description>
<IPAddress>203.0.113.1</IPAddress>
<SubnetMask>255.255.255.252</SubnetMask>
<Status>up</Status>
</Interface>
<Interface>
<Name>GigabitEthernet0/1</Name>
<Description>LAN Segment</Description>
<IPAddress>192.168.1.1</IPAddress>
<SubnetMask>255.255.255.0</SubnetMask>
<Status>up</Status>
</Interface>
</Interfaces>
<Routing>
<StaticRoutes>
<Route>
<Destination>0.0.0.0</Destination>
<Mask>0.0.0.0</Mask>
<NextHop>203.0.113.2</NextHop>
</Route>
</StaticRoutes>
<OSPF>
<ProcessID>1</ProcessID>
<RouterID>1.1.1.1</RouterID>
<Networks>
<Network>
<IP>192.168.1.0</IP>
<Wildcard>0.0.0.255</Wildcard>
<Area>0</Area>
</Network>
</Networks>
</OSPF>
</Routing>
</NetworkDeviceConfig>
📋 Explanation of XML Structure
This XML represents the configuration of a router:
<Device>
: Basic device info like hostname, location, vendor, and OS version.<Interfaces>
: A list of network interfaces with their IPs and statuses.<Routing>
: Routing configurations, including static routes and OSPF (Open Shortest Path First) settings.
Each tag is a container, and nested tags represent a hierarchy of related data.
🐍 Python Script to Parse the XML: parse_xml_config.py
Let’s parse this XML using Python’s built-in xml.etree.ElementTree
module. Here’s the script:
import xml.etree.ElementTree as ET
def parse_xml_config(file_path):
tree = ET.parse(file_path)
root = tree.getroot()
# Parse device info
print("=== Device Information ===")
device = root.find("Device")
for elem in device:
print(f"{elem.tag}: {elem.text}")
# Parse interfaces
print("\n=== Interfaces ===")
interfaces = root.find("Interfaces")
for interface in interfaces.findall("Interface"):
print("--- Interface ---")
for elem in interface:
print(f"{elem.tag}: {elem.text}")
# Parse routing info
print("\n=== Routing ===")
routing = root.find("Routing")
# Static Routes
static_routes = routing.find("StaticRoutes")
print("Static Routes:")
for route in static_routes.findall("Route"):
print(" - Route:")
for elem in route:
print(f" {elem.tag}: {elem.text}")
# OSPF
ospf = routing.find("OSPF")
print("OSPF Configuration:")
for elem in ospf:
if elem.tag != "Networks":
print(f" {elem.tag}: {elem.text}")
else:
print(" Networks:")
for network in elem.findall("Network"):
print(" - Network:")
for net_elem in network:
print(f" {net_elem.tag}: {net_elem.text}")
if __name__ == "__main__":
xml_file = "device.xml"
parse_xml_config(xml_file)
🧠 Line-by-Line Explanation
Imports:
import xml.etree.ElementTree as ET
We import ElementTree
, which is part of the standard Python library and is used for parsing and navigating XML files.
Define a function
def parse_xml_config(file_path):
Here we define a function parse_xml_config() that accepts a file path. This allows us to reuse the function with any XML file path we choose.
Load and Parse the XML
tree = ET.parse(file_path)
root = tree.getroot()
We parse the XML file and load its contents into an ElementTree
object called tree
.
This grabs the root element (in our case, <NetworkDevice>
) so we can start traversing the XML structure.
🔎 Parsing Device Info
print("=== Device Information ===")
device = root.find("Device")
for elem in device:
print(f"{elem.tag}: {elem.text}")
We locate the tag and iterate through each of its children (, , ) to print their tag name and corresponding value.
🌐 Parsing Interface Configurations
print("\n=== Interfaces ===")
interfaces = root.find("Interfaces")
for interface in interfaces.findall("Interface"):
print("--- Interface ---")
for elem in interface:
print(f"{elem.tag}: {elem.text}")
- find() gets the container.
- findall(“Interface”) gives us all interface entries.
- We extract data like interface name, IP address, and status.
🛣️ Parsing Routing Section
print("\n=== Routing ===")
routing = root.find("Routing")
Now we locate the block so we can handle both static and dynamic (OSPF) configurations.
This uses a path-like syntax to go into <Routing>
and then into <StaticRoutes>
, fetching each <Route>
and displaying destination, mask, and next hop.
🔁 Static Routes
static_routes = routing.find("StaticRoutes")
print("Static Routes:")
for route in static_routes.findall("Route"):
print(" - Route:")
for elem in route:
print(f" {elem.tag}: {elem.text}")
We dive into the <StaticRoutes> section and iterate through each <Route>, printing route-specific elements like <Destination>, <Mask>, and <NextHop>.
📡 OSPF Configuration
ospf = routing.find("OSPF")
print("OSPF Configuration:")
for elem in ospf:
if elem.tag != "Networks":
print(f" {elem.tag}: {elem.text}")
else:
print(" Networks:")
for network in elem.findall("Network"):
print(" - Network:")
for net_elem in network:
print(f" {net_elem.tag}: {net_elem.text}")
Here we’re digging into <OSPF>
, and finally extracting network entries advertised in OSPF with IP, wildcard, and area.
▶️ Running the Script
if __name__ == "__main__":
xml_file = "device.xml"
parse_xml_config(xml_file)
This standard Python idiom ensures that parse_xml_config() is only executed if the script is run directly, not when imported as a module. We pass “device.xml” as the file path.
🧾 Conclusion
Parsing XML might feel a bit overwhelming at first, but once you understand the structure and how to navigate it with Python, it becomes a powerful tool in your automation and network engineering toolbox.
Parsing XML data in Python using the xml.etree.ElementTree
module gives you a straightforward and flexible way to work with structured data. Whether you’re pulling configurations from network devices or reading output from APIs, being able to break down and extract information from XML files is an essential
In this post, we broke down each part of an XML file and a corresponding Python script to show how you can navigate and process data line by line. The parse_xml_config()
function is a reusable tool you can expand on in your projects.
Whether you’re working on automation, DevNet certification, or just improving your Python skills — learning to parse data like XML is a fundamental building block for building smarter, more dynamic tools.
References:
Cisco Certified DevNet Expert (v1.0) Equipment and Software List