Aprende cómo Convertir un fichero con datos XML a JSON e Importar este archivo JSON a MongoDB utilizando Python y contenedores Docker.
Objetivos a cumplir:
Descargar el código fuente
Se descarga el repositorio Convert-XML-to-JSON-and-Import-JSON-to-MongoDB en GitHub. Este repositorio recoge las configuraciones Docker necesarias para levantar los servicios Python y MongoDB con Docker-Compose. En estos casos, te invito a que, si deseas participar en la mejora del mismo, bienvenido sea tu aporte al repositorio, que también es tuyo.
Clonas el repositorio por medio de Git.
git clone https://github.com/jersonmartinez/Convert-XML-to-JSON-and-Import-JSON-to-MongoDB.git
Arrancar el proyecto con Docker Compose
Para poner en marcha la instalación de los servicios y que los contenedores sean creados. Es tan sencillo como ir a la terminal donde puedas correr Docker y ubicarse en el repositorio "Convert-XML-to-JSON-and-Import-JSON-to-MongoDB" que anteriormente se ha clonado y lanzar la siguiente instrucción:
$ docker-compose up --build -d
Creating network "convert-xml-to-json-and-import-json-to-mongodb_default" with the default driver
Pulling database (mongo:latest)...
latest: Pulling from library/mongo
3b65ec22a9e9: Pull complete
016bc871e2b3: Pull complete
9ddd649edd82: Pull complete
39bf776c01e4: Pull complete
f7f0405a2fe3: Pull complete
417812e2676c: Pull complete
905384a6c9a9: Pull complete
768aa2a1becc: Pull complete
623c0121bf78: Pull complete
Digest: sha256:6f90d92eb8ed5c52eb602a734697b329a0441949d9bb737ddcd5dae56552cac9
Status: Downloaded newer image for mongo:latest
Building web
[+] Building 60.7s (10/15)
...
Creating mongodb ... done
Creating api ... done
Se verifica que los contenedores estén creados, porque levantado solo uno y es el MongoDB. El primero contenedor donde se encuentra Python, este solo se ejecutó para correr el script Python que se ha señalado para realizar todas las operaciones mencionadas en los objetivos.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e2820f321600 convert-xml-to-json-and-import-json-to-mongodb_web "python ./import-mon…" About a minute ago Exited (0) About a minute ago api
ac19e1fa894f mongo:latest "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:27017-27019->27017-27019/tcp mongodb
Contenedores Python y MongoDB
El Dockerfile invocado desde el Docker Compose contiene las configuraciones para descargar la imagen python:3, además de ubicarse en el directorio /app. Copia el fichero requirements.txt, donde contiene las librerías de Python que se necesitan para lograr el cometido del algoritmo y de esta práctica. Ejecuta por medio de comandos, la instrucción python ./import-mongo.py.
# syntax=docker/dockerfile:1
FROM python:3
WORKDIR /app
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . .
CMD [ "python", "./import-mongo.py" ]
El fichero de configuración docker-compose.yml tiene dos servicios, el de Python y MongoDB.
version: '3.9'
services:
web:
env_file:
- .env
container_name: ${WEB_HOST}
hostname: ${WEB_HOST}
build: ./app
links:
- database
depends_on:
- database
volumes:
- ./app:/app
networks:
- default
database:
image: mongo:latest
env_file:
- .env
container_name: ${MONGO_HOST}
hostname: ${MONGO_HOST}
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASS}
MONGO_INITDB_DATABASE: ${MONGO_DB}
volumes:
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongo-volume:/data/db
- ./mongo-volume/log:/var/log/mongodb/
ports:
- '27017-27019:27017-27019'
networks:
- default
volumes:
persistent:
Ficheros de configuración (.env, mongo-init.js) donde se definen las credenciales del MongoDB, además de las variables de entorno.
.env
WEB_HOST=api
MONGO_HOST=mongodb
MONGO_PORT=27017
MONGO_USER=root-master
MONGO_PASS=password-master
MONGO_DB=db-sports
mongo-init.js
db.createUser(
{
user: 'root-master',
pwd: 'password-master',
roles: [
{
role: 'readWrite',
db: 'db-sports'
}
]
}
)
De este modo, se logra el cometido de levantar los contenedores con la configuración necesaria.
Convertir XML a JSON e Importar JSON a MongoDB
El algoritmo está conformado en una clase y 4 sencillos métodos:
import os
import xmltodict
import json
import requests
from pymongo import MongoClient
class getScriptXML:
def __init__(self, url, save_folder, filename):
self.url = url
self.save_folder = save_folder
self.filename = filename
def getData(self):
if not os.path.isdir(self.save_folder):
os.system("mkdir " + self.save_folder)
path = self.save_folder + "/" + self.filename
response = requests.get(self.url)
with open(path, 'wb') as file:
file.write(response.content)
self.convertXMLtoJSON(path)
def convertXMLtoJSON(self, path):
with open(path, "r") as xmlfileObj:
#Converting xml data to dictionary
data_dict = xmltodict.parse(xmlfileObj.read())
xmlfileObj.close()
#Creating JSON object using dictionary object
jsonObj = json.dumps(data_dict)
if not os.path.isdir("JSON"):
os.system("mkdir " + "JSON")
#storing json data to json file
with open("JSON/sports.json", "w") as jsonfileObj:
jsonfileObj.write(jsonObj)
jsonfileObj.close()
self.importJSONtoMongoDB()
def getDB(self):
mongoClient = MongoClient("mongodb://root-master:password-master@mongodb:27017/?authMechanism=DEFAULT&authSource=db-sports")
return mongoClient["db-sports"]
def importJSONtoMongoDB(self):
db = self.getDB()
Collection = db["sports"]
with open('JSON/sports.json') as file:
file_data = json.load(file)
if isinstance(file_data, list):
Collection.insert_many(file_data)
else:
Collection.insert_one(file_data)
if __name__ == "__main__":
getScriptXML(
'https://fx-nunchee-assets.s3.amazonaws.com/data/sports.xml',
'XML',
'sports.xml'
).getData()
Implementación del algoritmo y manipulación de contenedores
La forma en que este script es ejecutado es de dos maneras:
Iniciar el contenedor "api".
$ docker start api
api
El contenedor "api" en cuanto se inicia, ejecuta el algoritmo por medio de la instrucción python import-mongo.py que fue definido en el Dockerfile. En cuanto finalice la ejecución, el contenedor también cumple su ciclo de vida, siendo este terminado. Por tal razón, si deseas volver a ejecutar le script, será iniciar el contenedor "api" específicamente. Lo contrario sucede con el MongoDB que siempre se mantiene activo.
Eliminando los contenedores y sus volúmenes
$ docker-compose down --volumes
Stopping mongodb ... done
Removing api ... done
Removing mongodb ... done
Removing network convert-xml-to-json-and-import-json-to-mongodb_default
Removing volume convert-xml-to-json-and-import-json-to-mongodb_persistent
Eliminando la cache de los contenedores en Docker
Esta instrucción es solo por si existe algún problema al levantar los contenedores. Puede que haya que hacer alguna limpieza.
docker system prune -a -f && docker build prune -a -f
Eliminando los ficheros creados por MongoDB
El directorio mongo-value se usa para almacenar los registros del MongoDB, siendo este un volumen de datos señalado en el docker-compose.yml. Es importante volver a crearlo.
rm -rf mongo-value app/JSON app/XML && mkdir mongo-value
Concluyo en lo siguiente:
With supporting text below as a natural lead-in to additional content.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled.