Data loading, with the help of AI

Data loading, with the help of AI

In today’s fast-paced development world, efficiency is paramount. AI can significantly accelerate the coding process, including the creation of scripts to interact with various data formats. This blog post will explore how to use AI assistance to generate Python code for loading a custom XML file.

This is a use case for those of us who work with data, that we can use to solve challenges which we have in development. While it’s a specific example, the approach is very re-usable and can be applied to many sources and databases.

Using AI to parse an XML file and create python code to load it to a MySQL database

For the sake of simplicity, and what’s going to be familiar to most data engineers (including open source software), I’m using an XML file I found, and coding in python loading to a MySQL database.

What is XML?

For anyone who isn’t so familiar with it (most technologies use json now) XML (Extensible Markup Language) is a simple, text-based format for representing structured data. It’s like a universal language that computers and humans can both understand.  

Here’s a breakdown:

  • Structure: XML uses tags (like <name>, <age>) to define the structure and meaning of the data.
  • Data: The actual information is placed within these tags.  
  • Flexibility: You can create your own custom tags, making it adaptable to various data types and structures.

A simple sample example is:

<person>
  <name>John Doe</name>
  <age>30</age>
  <city>New York</city>
</person>

My (more complicated) XML file

For this example, I’ve found an XML file which contains nested structured data. We can envisage having a collection of these files which we have to understand and load into a format which is usable for data consumption (cut down example below, full file can be seen on my github).

<?xml version="1.0" encoding="utf-8"?>
<product id="Animated Canvases" name="Animated Canvases" version="1" singlecontent="true">
<volume id="Animated Canvases Collection 3" name="Animated Canvases Collection 3" number="3" sourcefiletype="mov" preview_discid="ACNV_V03D01D_R1" preview_suffix=".mov" preview_install_dir="Juicer3" preview_path_on_disc="Juicer3/" preview_thumbnail_suffix=".jpg" install_size_img="1" install_size_img_mov="10" totalPreviewSize="185" totalSourceSize="14464.62" baseJ3Version="3.03 Build 258">
<disc id="ACNV_V03D01D_R1" number="1">
<parent id="Source">
<content id="All Star_HD" type="1" name="" originalfps="30" frames="300" description="Animated Background" resolution="hd" resx="1920" resy="1080" base=""><keywords></keywords></content>
<content id="Amber Rays_HD" type="1" name="" originalfps="30" frames="300" description="Animated Background" resolution="hd" resx="1920" resy="1080" base=""><keywords></keywords></content>
<content id="Approaching Doom_HD" type="1" name="" originalfps="30" frames="600" description="Animated Background" resolution="hd" resx="1920" resy="1080" base=""><keywords></keywords></content>
</parent>
</disc>
<disc id="ACNV_V03D02D_R1" number="2">
<parent id="Source">
<content id="Hiding Magic_HD" type="1" name="" originalfps="30" frames="300" description="Animated Background" resolution="hd" resx="1920" resy="1080" base=""><keywords></keywords></content>
<content id="Higher Than The Sky_HD" type="1" name="" originalfps="30" frames="450" description="Animated Background" resolution="hd" resx="1920" resy="1080" base=""><keywords></keywords></content>
</parent>
</disc>
</volume>
</product>

Historically I’d use a local text editor (with syntax highlighting) to explore the file and work out what objects are in it, or an online equivalent such as: https://jsonformatter.org/xml-formatter

Using AI

In this case, I’m using ChatGPT to speed up my process. You can see the whole conversation here (the relevant parts are copied below).

Viewing the structure and content of the file

Yes, XML is very human readable, with indentation it’s even clearer what the hierarchy is. But asking AI to do some of this is even more readable.

Describe the hierarchy of data structures in the attached XML file

Click to view full response

The hierarchy of data structures in the XML file is organized as follows:

Root Element:

<product>: Represents the top-level element of the file. It includes attributes like id, name, version, and others. This serves as the main container for all subsequent elements.

Volume:

<volume>: Nested within <product>. Represents a collection of discs and related content. It includes attributes such as id, name, number, and metadata about file types and sizes.

Disc:

<disc>: Nested within <volume>. Represents individual discs in the collection. Each <disc> has attributes like id and number.

Parent:

<parent>: Nested within <disc>. Represents a grouping for source content, identified by an id attribute, usually set to “Source”.

Content:

<content>: Nested within <parent>. Represents individual animated background items. Each <content> element contains attributes like id, type, name, description, resolution, and frame-related metadata (e.g., originalfps, frames).

Keywords:

<keywords>: Nested within <content>. A placeholder element for additional metadata about each animated background item. It is currently empty in the provided XML file.

Example Hierarchy

  • <product>
    • <volume>
      • <disc>
        • <parent>
          • <content>
            • <keywords>

This hierarchy reflects a clear structure to organize animated background content across collections, discs, and specific items within those discs.

Convert this xml into tables for product, volume, disc, and content

Click to view full response

Here’s a tabular representation of the XML data, broken down by Product, Volume, Disc, and Content.

Table: Product

IDNameVersionSingleContent
Animated CanvasesAnimated Canvases1true

Table: Volume

IDNameNumberSourceFileTypePreviewDiscIDPreviewSuffixPreviewInstallDirPreviewPathOnDiscPreviewThumbnailSuffixInstallSizeImgInstallSizeImgMovTotalPreviewSizeTotalSourceSizeBaseJ3Version
Animated Canvases Collection 3Animated Canvases Collection 33movACNV_V03D01D_R1.movJuicer3Juicer3/.jpg11018514464.623.03 Build 258

Table: Disc

IDVolumeIDNumber
ACNV_V03D01D_R1Animated Canvases Collection 31
ACNV_V03D02D_R1Animated Canvases Collection 32

Table: Content

IDDiscIDTypeNameOriginalFPSFramesDescriptionResolutionResXResYBaseKeywords
All Star_HDACNV_V03D01D_R1130300Animated Backgroundhd19201080
Amber Rays_HDACNV_V03D01D_R1130300Animated Backgroundhd19201080
Approaching Doom_HDACNV_V03D01D_R1130600Animated Backgroundhd19201080
Balloon Rise_HDACNV_V03D01D_R1130600Animated Backgroundhd19201080
Blending Pipes_HDACNV_V03D01D_R1130450Animated Backgroundhd19201080
Bundle Of Joy_HDACNV_V03D01D_R1130600Animated Backgroundhd19201080
Center Of Attention_HDACNV_V03D01D_R1130300Animated Backgroundhd19201080
Hiding Magic_HDACNV_V03D02D_R1130300Animated Backgroundhd19201080
Higher Than The Sky_HDACNV_V03D02D_R1130450Animated Backgroundhd19201080

This approach captures a normalized structure suitable for a database. Each table includes key fields that uniquely identify and relate the elements. If needed, additional rows can be added for the remaining content.

It didn’t get it exactly right, an ID was missing, fortunately I can ask for it to be added

include disc id for content, volume id for disc, product id for volume

Click to view full response

Here’s the updated tabular representation with the Product ID included in the Volume table:

Table: Product

IDNameVersionSingleContent
Animated CanvasesAnimated Canvases1true

Table: Volume

IDProductIDNameNumberSourceFileTypePreviewDiscIDPreviewSuffixPreviewInstallDirPreviewPathOnDiscPreviewThumbnailSuffixInstallSizeImgInstallSizeImgMovTotalPreviewSizeTotalSourceSizeBaseJ3Version
Animated Canvases Collection 3Animated CanvasesAnimated Canvases Collection 33movACNV_V03D01D_R1.movJuicer3Juicer3/.jpg11018514464.623.03 Build 258

Table: Disc

IDVolumeIDNumber
ACNV_V03D01D_R1Animated Canvases Collection 31
ACNV_V03D02D_R1Animated Canvases Collection 32

Table: Content

IDDiscIDTypeNameOriginalFPSFramesDescriptionResolutionResXResYBaseKeywords
All Star_HDACNV_V03D01D_R1130300Animated Backgroundhd19201080
Amber Rays_HDACNV_V03D01D_R1130300Animated Backgroundhd19201080
Approaching Doom_HDACNV_V03D01D_R1130600Animated Backgroundhd19201080
Balloon Rise_HDACNV_V03D01D_R1130600Animated Backgroundhd19201080
Blending Pipes_HDACNV_V03D01D_R1130450Animated Backgroundhd19201080
Bundle Of Joy_HDACNV_V03D01D_R1130600Animated Backgroundhd19201080
Center Of Attention_HDACNV_V03D01D_R1130300Animated Backgroundhd19201080
Hiding Magic_HDACNV_V03D02D_R1130300Animated Backgroundhd19201080
Higher Than The Sky_HDACNV_V03D02D_R1130450Animated Backgroundhd19201080

This updated structure ensures that Volume is directly associated with the Product, creating a complete relational model.

Creating the code to load the data

Just a question away for the part that can take more time as a developer.

generate python code to extract the data from the XML in this structure, and load it into a MySQL database

Click to view full response

Here’s the Python code to extract data from the XML file and load it into a MySQL database:

Code

import xml.etree.ElementTree as ET
import mysql.connector

# Parse the XML file
xml_file = "ACNV_V03D01D_R1.xml"
tree = ET.parse(xml_file)
root = tree.getroot()

# MySQL connection
db = mysql.connector.connect(
    host="localhost",
    user="your_username",
    password="your_password",
    database="your_database"
)
cursor = db.cursor()

# Create tables
cursor.execute("""
CREATE TABLE IF NOT EXISTS Product (
    id VARCHAR(255) PRIMARY KEY,
    name VARCHAR(255),
    version INT,
    singlecontent BOOLEAN
)
""")

cursor.execute("""
CREATE TABLE IF NOT EXISTS Volume (
    id VARCHAR(255) PRIMARY KEY,
    product_id VARCHAR(255),
    name VARCHAR(255),
    number INT,
    sourcefiletype VARCHAR(50),
    preview_discid VARCHAR(255),
    preview_suffix VARCHAR(10),
    preview_installdir VARCHAR(255),
    preview_path_on_disc VARCHAR(255),
    preview_thumbnail_suffix VARCHAR(10),
    install_size_img INT,
    install_size_img_mov INT,
    total_preview_size INT,
    total_source_size FLOAT,
    base_j3_version VARCHAR(255),
    FOREIGN KEY (product_id) REFERENCES Product(id)
)
""")

cursor.execute("""
CREATE TABLE IF NOT EXISTS Disc (
    id VARCHAR(255) PRIMARY KEY,
    volume_id VARCHAR(255),
    number INT,
    FOREIGN KEY (volume_id) REFERENCES Volume(id)
)
""")

cursor.execute("""
CREATE TABLE IF NOT EXISTS Content (
    id VARCHAR(255) PRIMARY KEY,
    disc_id VARCHAR(255),
    type INT,
    name VARCHAR(255),
    originalfps INT,
    frames INT,
    description VARCHAR(255),
    resolution VARCHAR(50),
    resx INT,
    resy INT,
    base VARCHAR(255),
    keywords TEXT,
    FOREIGN KEY (disc_id) REFERENCES Disc(id)
)
""")

# Extract and insert Product
product = root.attrib
product_id = product["id"]
cursor.execute("""
INSERT INTO Product (id, name, version, singlecontent)
VALUES (%s, %s, %s, %s)
ON DUPLICATE KEY UPDATE name=VALUES(name), version=VALUES(version), singlecontent=VALUES(singlecontent)
""", (product["id"], product["name"], int(product["version"]), product["singlecontent"] == "true"))

# Extract and insert Volume
for volume in root.findall("volume"):
    volume_attrib = volume.attrib
    cursor.execute("""
    INSERT INTO Volume (id, product_id, name, number, sourcefiletype, preview_discid, preview_suffix, preview_installdir,
                        preview_path_on_disc, preview_thumbnail_suffix, install_size_img, install_size_img_mov,
                        total_preview_size, total_source_size, base_j3_version)
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
    ON DUPLICATE KEY UPDATE name=VALUES(name), number=VALUES(number), sourcefiletype=VALUES(sourcefiletype),
                            preview_discid=VALUES(preview_discid), preview_suffix=VALUES(preview_suffix),
                            preview_installdir=VALUES(preview_installdir), preview_path_on_disc=VALUES(preview_path_on_disc),
                            preview_thumbnail_suffix=VALUES(preview_thumbnail_suffix), install_size_img=VALUES(install_size_img),
                            install_size_img_mov=VALUES(install_size_img_mov), total_preview_size=VALUES(total_preview_size),
                            total_source_size=VALUES(total_source_size), base_j3_version=VALUES(base_j3_version)
    """, (volume_attrib["id"], product_id, volume_attrib["name"], int(volume_attrib["number"]),
          volume_attrib["sourcefiletype"], volume_attrib["preview_discid"], volume_attrib["preview_suffix"],
          volume_attrib["preview_install_dir"], volume_attrib["preview_path_on_disc"],
          volume_attrib["preview_thumbnail_suffix"], int(volume_attrib["install_size_img"]),
          int(volume_attrib["install_size_img_mov"]), int(volume_attrib["totalPreviewSize"]),
          float(volume_attrib["totalSourceSize"]), volume_attrib["baseJ3Version"]))

    # Extract and insert Disc
    for disc in volume.findall("disc"):
        disc_attrib = disc.attrib
        cursor.execute("""
        INSERT INTO Disc (id, volume_id, number)
        VALUES (%s, %s, %s)
        ON DUPLICATE KEY UPDATE volume_id=VALUES(volume_id), number=VALUES(number)
        """, (disc_attrib["id"], volume_attrib["id"], int(disc_attrib["number"])))

        # Extract and insert Content
        for content in disc.findall(".//content"):
            content_attrib = content.attrib
            keywords = content.find("keywords").text if content.find("keywords") is not None else ""
            cursor.execute("""
            INSERT INTO Content (id, disc_id, type, name, originalfps, frames, description, resolution, resx, resy, base, keywords)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            ON DUPLICATE KEY UPDATE type=VALUES(type), name=VALUES(name), originalfps=VALUES(originalfps), frames=VALUES(frames),
                                    description=VALUES(description), resolution=VALUES(resolution), resx=VALUES(resx),
                                    resy=VALUES(resy), base=VALUES(base), keywords=VALUES(keywords)
            """, (content_attrib["id"], disc_attrib["id"], int(content_attrib["type"]), content_attrib.get("name", ""),
                  int(content_attrib["originalfps"]), int(content_attrib["frames"]), content_attrib["description"],
                  content_attrib["resolution"], int(content_attrib["resx"]), int(content_attrib["resy"]),
                  content_attrib.get("base", ""), keywords))

# Commit and close
db.commit()
cursor.close()
db.close()

print("Data successfully loaded into MySQL!")

Steps:

  1. Install Dependencies: Ensure mysql-connector-python is installed:bashCopy codepip install mysql-connector-python
  2. Create MySQL Database: Replace placeholders (your_username, your_password, your_database) with actual database credentials.
  3. Run the Script: Save the XML file as ACNV_V03D01D_R1.xml in the script’s directory and execute the Python script. It will parse the XML, create tables if they don’t exist, and load the data.

This approach ensures deduplication using ON DUPLICATE KEY UPDATE and maintains referential integrity via foreign keys.

I’m now given python code which I can test

Testing my new data load process

For simplicity I’ll do it all on a local machine, also I’m not focusing on security here.

Creating the database & user

Again, this can be simplified by AI (this time I used Gemini from Google) asking:

generate MySQL sql to create a database called xml_loader_example, and grant all access to it to a new user called xml_loader_example_user

-- Create the database
CREATE DATABASE IF NOT EXISTS xml_loader_example;

-- Create the user (if it doesn't already exist)
CREATE USER IF NOT EXISTS 'xml_loader_example_user'@'%' IDENTIFIED BY 'some_strong_password'; -- Replace with a real password!

-- Grant all privileges on the database to the user
GRANT ALL PRIVILEGES ON xml_loader_example.* TO 'xml_loader_example_user'@'%';

-- Flush privileges to ensure the changes take effect
FLUSH PRIVILEGES;

Setting up the virtual environemnt

I’m using Linux, if you don’t know about a virtual environment, check out the python venv documentation.

# Create the virtual environment
python -m venv venv

# Activate it
source venv/bin/activate

# Update pip (always good practice with a new virtual environment)
pip install --upgrade pip

Install the dependencies as suggested by ChatGPT

pip install mysql-connector-python

Modify the code to contain the database credentials

# MySQL connection
db = mysql.connector.connect(
    host="localhost",
    user="xml_loader_example_user",
    password="some_strong_password",
    database="xml_loader_example"
)

And now the magic moment, does it work?

python xml_loader.py
Data successfully loaded into MySQL!

My first thought was “Wow, that was fast… There were no errors, Did it work first time without any issues?”

Test it in MySQL

Again, I asked ChatGPT to create the SQL I wanted.

generate SQL to show content ID and description, disc ID, volume name and product name

SELECT 
    c.id AS content_id,
    c.description AS content_description,
    d.id AS disc_id,
    v.name AS volume_name,
    p.name AS product_name
FROM 
    Content c
INNER JOIN 
    Disc d ON c.disc_id = d.id
INNER JOIN 
    Volume v ON d.volume_id = v.id
INNER JOIN 
    Product p ON v.product_id = p.id;

Here is the output (with the help of tableconvert.com to quickly format for the blog post):

content_idcontent_descriptiondisc_idvolume_nameproduct_name
All Star_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
All Star_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Amber Rays_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Amber Rays_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Approaching Doom_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Approaching Doom_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Balloon Rise_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Balloon Rise_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Blending Pipes_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Blending Pipes_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Bundle Of Joy_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Bundle Of Joy_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Center Of Attention_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Center Of Attention_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Cloud Interference_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Cloud Interference_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Coin Collection_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Coin Collection_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Dazzling Moonlight_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Dazzling Moonlight_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Diagonal Slide_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Diagonal Slide_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Different Positions_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Different Positions_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Firefly Goodbye_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Firefly Goodbye_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Fitting Frames_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Fitting Frames_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Flying Colors_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Flying Colors_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Frame Impression_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Frame Impression_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
French Parade_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
French Parade_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Garden Whispers_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Garden Whispers_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Happy Summer_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Happy Summer_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Heavenly Beam_HDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Heavenly Beam_SDAnimated BackgroundACNV_V03D01D_R1Animated Canvases Collection 3Animated Canvases
Hiding Magic_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Hiding Magic_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Higher Than The Sky_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Higher Than The Sky_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Hue Progression_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Hue Progression_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
I Put A Spell On You_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
I Put A Spell On You_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Magic Unleashed_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Magic Unleashed_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Restricted Area_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Restricted Area_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Sahara Evenings_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Sahara Evenings_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Sea Outside_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Sea Outside_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Searchlights_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Searchlights_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Sharp Stops_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Sharp Stops_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Shifting Midnight_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Shifting Midnight_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Slowly Spreading_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Slowly Spreading_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Smooth Ripples_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Smooth Ripples_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Soul Of Sin_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Soul Of Sin_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Square Resolution_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Square Resolution_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Star Attraction_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Star Attraction_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Start The Party_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Start The Party_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Strange Divisions_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Strange Divisions_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Stripe Intentions_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Stripe Intentions_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Suburban Summer_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Suburban Summer_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Surprising Revelation_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Surprising Revelation_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Tricky Footing_HDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases
Tricky Footing_SDAnimated BackgroundACNV_V03D02D_R1Animated Canvases Collection 3Animated Canvases

Final thoughts

The solution was generated in a matter of minutes, something which would probably take a developer who doesn’t use python regularly a lot longer to write and debug. As a data professional, learning to use AI to support our development processes will enable us to be far more efficient.

There are other approaches I could have taken, this is a very ETL (Extract Transform Load) approach, rather than an ELT (Extract Load Transform) approach of loading the XML into the database and using XML parsing there to extract the required data.

One thing I didn’t include in the sample above was iterating over files (it only loads the one file). Of course, to iterate over multiple files I just had to ask:

modify the python code to iterate over XML files in a directory

Security, governance & good practice

  • Don’t trust anything generated by AI without reading/checking it first, it can make mistakes.
  • Don’t share sensitive company information/data with an AI platform.
  • Changes will have to be made to the code/database for security/limiting access (including not sticking with the default password suggested by Gemini).

Tools which do this for us

As a side note, If we just had one small simple file to load, then there are some online tools which I’d recommend developers have a play with. They use AI and general logic approaches to parse files and generate the content in SQL:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.