Convertir un document XML stocké dans une base de données XML (BaseX) au format CSV (en utilisant Python)

Contenu de l'article

Supposons que vous ayez plusieurs fichiers XML à portée de main et que vous souhaitiez peser ces données. Il est difficile pour les humains de comparer plusieurs fichiers XML, je vais donc les convertir en fichiers CSV contenant une ligne par fichier XML. Si vous ouvrez le fichier CSV avec Excel, etc., il sera plus facile de comparer et d'examiner les données. J'ai implémenté la conversion en CSV en Python, mais pardonnez-moi que le code ne se comporte pas très bien.

environnement

--OS: Windows10 (je ne l'ai pas essayé, mais il peut être exécuté sur un autre système d'exploitation)

URL de référence (merci)

Charger un document XML dans BaseX

Tout d'abord, chargez plusieurs documents XML à portée de main dans BaseX. J'ai écrit le code Python suivant et l'ai fait fonctionner en faisant référence à Code here.


from pathlib import Path
import os
import pprint
from BaseXClient import BaseXClient

#Créer une session
session = BaseXClient.Session('localhost', 1984, 'admin', 'admin')

try:
    #Fichier XML à stocker dans la base de données
    xml_directory = Path("C:\\") / "xml_data"
    list_xml_path = sorted(xml_directory.glob("*.xml"), key=os.path.getmtime)
    print("Fichier XML à charger:")
    pprint.pprint(list_xml_path)

    #DB ouvert
    session.execute("open testdb")
    print(session.info())

    #Lisez le fichier xml et ajoutez-le à la base de données
    for path in list_xml_path:
        with open(path, mode='r', encoding="utf-8") as fi:
            str_xml = fi.read()

        session.add(path.name, str_xml)
        print(session.info())

    #Afficher le contenu de DB
    print("\n" + session.execute("xquery /"))
    print("Terminé normalement\n")

finally:
    #Fermer la session
    if session:
        session.close()

Pour compléter l'explication sur le code,

--Chargez le document XML dans la base de données existante "testdb". Cet article peut être utilisé comme référence pour savoir comment créer une base de données.

Lorsque j'ai exécuté le code, le document XML était chargé avec l'affichage suivant:

Fichier XML à charger:
[WindowsPath('C:/xml_data/sample-1.xml'),
 WindowsPath('C:/xml_data/sample-2.xml'),
 WindowsPath('C:/xml_data/sample-3.xml'),
 WindowsPath('C:/xml_data/sample-4.xml'),
 WindowsPath('C:/xml_data/sample-5.xml'),
 WindowsPath('C:/xml_data/sample-7.xml'),
 WindowsPath('C:/xml_data/sample-6.xml'),
 WindowsPath('C:/xml_data/sample-8.xml')]
Database 'testdb' was opened in 1.48 ms.

Resource(s) added in 3.72 ms.

Resource(s) added in 1.93 ms.

Resource(s) added in 8.89 ms.

Resource(s) added in 1.91 ms.

Resource(s) added in 2.05 ms.

Resource(s) added in 2.05 ms.

Resource(s) added in 1.93 ms.

(Omis)

Terminé normalement

Émettre une requête vers BaseX et la sortie dans un fichier CSV

Ensuite, il interroge BaseX pour générer un fichier CSV qui forme un document XML sur une ligne. J'ai écrit le code Python suivant et cela a fonctionné.


import pprint
from BaseXClient import BaseXClient


#Propre classe d'exception
class MyException(Exception):
    pass


#Lire le xpath de l'élément racine dans la base de données
def read_xpath_root(session):
    set_xpath_root = set()

    query = f'''\
for $root in /*
return fn:path($root)
'''

    query_obj = session.query(query)
    query_obj.execute()

    #Ajouter des xpaths pour tous les éléments racine à un ensemble unique
    for typecode, item in query_obj.iter():
        set_xpath_root.add(item)

    print("XPath de l'élément racine:")
    pprint.pprint(set_xpath_root)

    query_obj.close()

    #J'ai décidé de n'autoriser qu'un seul type d'élément racine.
    if len(set_xpath_root) == 1:
        pass
    else:
        msg = f"assert len(set_xpath_root)<{len(set_xpath_root)}> == 1"
        raise MyException(msg)

    return set_xpath_root.pop().replace("[1]", "[01]") + '/'


#Collectez tous les types de xpath d'élément de texte à partir de DB
def read_xpath_text(session):
    set_xpath_text = set()

    query = f'''\
for $text in //text()
return fn:path($text)
'''

    query_obj = session.query(query)
    query_obj.execute()

    #Ajouter xpath de tous les éléments de texte à l'ensemble non dupliqué
    for typecode, item in query_obj.iter():
        set_xpath_text.add(item)

    query_obj.close()

    #Je veux trier, alors passe d'un ensemble à une liste
    list_xpath_text = []
    for xpath_text in set_xpath_text:
        list_xpath_text.append(
            #Lors du tri[1]Mais[10]Pour les problèmes qui seront plus tard. Pour le moment
            xpath_text
                .replace("[1]", "[01]")
                .replace("[2]", "[02]")
                .replace("[3]", "[03]")
                .replace("[4]", "[04]")
                .replace("[5]", "[05]")
                .replace("[6]", "[06]")
                .replace("[7]", "[07]")
                .replace("[8]", "[08]")
                .replace("[9]", "[09]")
        )
    list_xpath_text.sort()
    print("XPath de l'élément de texte (tous types):")
    pprint.pprint(list_xpath_text)
    return list_xpath_text


#Créer une session
session = BaseXClient.Session('localhost', 1984, 'admin', 'admin')

try:
    #DB ouvert
    session.execute("open testdb")
    print(session.info())

    #lire xpath de l'élément racine
    xpath_root = read_xpath_root(session)

    #Collectez tous les types de xpath d'élément de texte (utilisez le nom de colonne csv)
    list_xpath_text = read_xpath_text(session)

    #Assemblez et émettez une requête qui renvoie une ligne de csv
    csv_header = "input_path"
    query = f'''\
for $root in /*
let $base_uri := fn:base-uri($root)
order by $base_uri
return <ROW>"{{fn:substring($base_uri, fn:string-length(db:name($root)) + 3)}}"\
'''

    #boucle de colonne csv
    for xpath_text in list_xpath_text:
        # xpath_Mettre en forme correctement du texte à l'en-tête csv,+=
        csv_header += ',' \
                      + xpath_text\
                          .replace(xpath_root, "")\
                          .replace("/text()[01]", "")\
                          .replace("Q{}", "")

        # xpath_Format à partir du texte pour XQuery,+=
        query += ',"{' + xpath_text.replace(xpath_root, "$root/") + '}"'

    query += "</ROW>"

    #Enquête DB
    query_obj = session.query(query)
    query_obj.execute()

    #Nom du fichier de sortie
    basename = xpath_root\
                       .replace("Q{}", "")\
                       .replace("[01]", "")\
                       .replace('/', "")

    #Sortie de l'instruction de requête
    with open(basename + "_xquery.txt", 'w') as fo:
        fo.write(query)
        fo.write('\n')

    #sortie csv
    with open(basename + ".csv", 'w') as fo:
        #Sortie d'en-tête
        fo.write(csv_header)
        fo.write('\n')

        #Sortie ligne
        for typecode, item in query_obj.iter():
            fo.write(item.replace("<ROW>", "").replace("</ROW>", '\n'))

    query_obj.close()
    print("Terminé normalement\n")

finally:
    #Fermer la session
    if session:
        session.close()

Pour compléter l'explication sur le code,

--Ce code exige que tous les documents XML de la base de données aient le même nom d'élément racine.

Quand j'ai exécuté le code, ce qui suit était affiché et le fichier CSV "manyosyu.csv" était sorti.

Database 'testdb' was opened in 1.12 ms.

XPath de l'élément racine:
{'/Q{}manyosyu[1]'}
XPath de l'élément de texte (tous types):
['/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[01]/Q{}image[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[01]/Q{}mean[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[01]/Q{}mkana[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[01]/Q{}pno[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[01]/Q{}poet[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[01]/Q{}yomi[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[02]/Q{}image[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[02]/Q{}mean[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[02]/Q{}mkana[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[02]/Q{}pno[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[02]/Q{}poet[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[02]/Q{}yomi[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[03]/Q{}image[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[03]/Q{}mean[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[03]/Q{}mkana[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[03]/Q{}pno[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[03]/Q{}poet[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[03]/Q{}yomi[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[04]/Q{}image[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[04]/Q{}mean[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[04]/Q{}mean[01]/text()[02]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[04]/Q{}mkana[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[04]/Q{}pno[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[04]/Q{}poet[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[04]/Q{}yomi[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[05]/Q{}image[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[05]/Q{}mean[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[05]/Q{}mkana[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[05]/Q{}pno[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[05]/Q{}poet[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[05]/Q{}yomi[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[06]/Q{}image[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[06]/Q{}mean[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[06]/Q{}mkana[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[06]/Q{}pno[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[06]/Q{}poet[01]/text()[01]',
 '/Q{}manyosyu[01]/Q{}volume[01]/Q{}poem[06]/Q{}yomi[01]/text()[01]']
Terminé normalement

Le fichier de débogage de l'instruction de requête suivant est également généré.

manyosyu_xquery.txt



for $root in /*
let $base_uri := fn:base-uri($root)
order by $base_uri
return <ROW>"{fn:substring($base_uri, fn:string-length(db:name($root)) + 3)}","{$root/Q{}volume[01]/Q{}poem[01]/Q{}image[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[01]/Q{}mean[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[01]/Q{}mkana[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[01]/Q{}pno[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[01]/Q{}poet[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[01]/Q{}yomi[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[02]/Q{}image[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[02]/Q{}mean[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[02]/Q{}mkana[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[02]/Q{}pno[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[02]/Q{}poet[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[02]/Q{}yomi[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[03]/Q{}image[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[03]/Q{}mean[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[03]/Q{}mkana[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[03]/Q{}pno[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[03]/Q{}poet[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[03]/Q{}yomi[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[04]/Q{}image[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[04]/Q{}mean[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[04]/Q{}mean[01]/text()[02]}","{$root/Q{}volume[01]/Q{}poem[04]/Q{}mkana[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[04]/Q{}pno[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[04]/Q{}poet[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[04]/Q{}yomi[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[05]/Q{}image[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[05]/Q{}mean[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[05]/Q{}mkana[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[05]/Q{}pno[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[05]/Q{}poet[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[05]/Q{}yomi[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[06]/Q{}image[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[06]/Q{}mean[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[06]/Q{}mkana[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[06]/Q{}pno[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[06]/Q{}poet[01]/text()[01]}","{$root/Q{}volume[01]/Q{}poem[06]/Q{}yomi[01]/text()[01]}"</ROW>

Ouvrons le "manyosyu.csv" généré dans Excel.

manyosyu.png

Une ligne CSV a été générée pour chaque fichier XML chargé dans la base de données.

Recommended Posts

Convertir un document XML stocké dans une base de données XML (BaseX) au format CSV (en utilisant Python)
Convertir / renvoyer des objets de classe au format JSON en Python
Convertir Markdown en PDF en Python
[Python] Comment convertir un fichier db en csv
Convertir les données au format XML en données au format txt (yolov3)
Comment convertir csv en tsv dans la CLI
[Python] Convertit les délimiteurs de fichier csv en délimiteurs de tabulation
Convertir un fichier psd en png en Python
Connectez-vous à Slack à l'aide de requêtes en Python
Convertir le type de date Python au format RFC822
Convertir de Markdown en HTML en Python
Téléchargez des fichiers dans n'importe quel format en utilisant Python
Convertir une URL absolue en URL relative en Python
Remarque: [Python3] Convertissez datetime en chaîne dans le format de votre choix
Je souhaite convertir une table convertie en PDF en Python en CSV
Comment tracer les données de lumière visible d'une galaxie à l'aide de la base de données OpenNGC en python
J'ai créé un script en python pour convertir des fichiers .md au format Scrapbox
Prétraitement avec Python. Convertir les résultats de recherche de balises de la vidéo Nico Nico au format CSV
Mauvais message pour utiliser "animeface-2009" en Python et implémentation de la fonction pour générer un fichier XML au format PASCAL VOC
Convertir le fichier FBX en ASCII <-> BINARY en Python
Convertissez des PDF en images en masse avec Python
[Python] Conversion de DICOM en PNG ou CSV
Convertir les données csv, tsv en une matrice avec MovieLens en utilisant python comme exemple
Convertir des fichiers CSV UTF-8 pour les lire dans Excel
Convertir STL en maillage Voxel à l'aide de Python VTK
CSV en Python
Convertir les données au format json en txt (en utilisant yolo)
format en python
Convertir un float exponentiel en str en Python
Convertir le code de maillage cubique en WKT en Python
Convertir une chaîne au format de liste caractère par caractère avec python
Passer des dataframes contenant True / False de Python à R au format csv (pd.DataFrame-> tbl_df)
Convertir la date et l'heure zonées en temps Unixtime dans Python2.7
Je veux écrire en Python! (1) Vérification du format de code
Convertir le masque de réseau de notation CIDR en notation décimale à points en Python
[Python] Convertir le texte PDF en CSV pour chaque page (2/24 postscript)
Comment convertir des nombres à virgule flottante en nombres binaires en Python
Convertissez l'image au format .zip en PDF avec Python
Comment convertir un fichier JSON en fichier CSV avec Python Pandas
Convertir l'API asynchrone de style callback en async / await en Python
Comment quitter lors de l'utilisation de Python dans Terminal (Mac)
[Python] Création d'une méthode pour convertir la base en 1 seconde
Comment récupérer plusieurs tableaux à l'aide de slice en python.
Comment convertir des fichiers Json au format CSV ou au format EXCEL
Convertir le type d'entité Webpay en type Dict (récursivement en Python)
Comment exécuter une commande à l'aide d'un sous-processus en Python
Comment lire un csv contenant uniquement des entiers en Python
Convertir le fichier XML au format Pascal VOC en fichier json au format COCO
Analyser XML en Python
Format d'image en Python
Essayez de le faire avec GUI, PyQt en Python
Conversion de Pandas DataFrame en System.Data.DataTable à l'aide de Python pour .NET
Comment sortir un document au format pdf avec Sphinx
Python / datetime> Implémentation pour convertir le format AAAAMMJJ en AAAA / MM / JJ
[R] [Python] Memo pour lire plusieurs fichiers csv dans plusieurs fichiers zip
Pour renvoyer char * dans une fonction de rappel à l'aide de ctypes en Python
Conversion par lots de tous les fichiers xlsx du dossier en fichiers CSV
Autoriser l'exécution rapide des scripts Python dans Cloud Run à l'aide du répondeur
Résolvez le problème japonais lors de l'utilisation du module CSV en Python.
Précautions lors de l'utilisation de Python avec AtCoder