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.
--OS: Windows10 (je ne l'ai pas essayé, mais il peut être exécuté sur un autre système d'exploitation)
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
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.
Une ligne CSV a été générée pour chaque fichier XML chargé dans la base de données.
Recommended Posts