Je suis entrain de convertir un fichier xml (de plus de 150 000 enregistrements avec plus de 50 tags) et j'ai besoin d'extraire de chaque ligne avec le même id + le contenu de mes références et les exporter dans csv.
voici un exemple simplifié de ce que je souhaite avoir comme résultat
id unique : 1 ; non de la note : "ma note" ; reference _mot : Chaise; reference : 1,2,3;
Mon code m'affiche des erreurs quand à la partie "sources" je n'arrive pas donc à boucler sur les références et stocker chacune dans une ligne avec le même id unique.
Voici à quoi ressemble mon code python + xml
Merci d'avance
SOURCES_REFS = []
SOURCES_DUPS = [ 0 ]
class Note(object):
OLDS = {
'UNIQUE_KEY' : 'key',
'CREATE_DATE' : 'create_date',
'NOM' : 'nom_note',
'AUTEUR' : 'auteur',
'SRC' : 'sources',
}
FIELDS = list(OLDS.values())
TAG = 'NOTE'
def __init__(self, separator=';'):
self.separator = separator
def start(self, e):
if e.tag in self.OLDS.keys():
attr = self.OLDS[e.tag]
value = e.text.strip() if e.text else e.text
if ( attr == 'create_date' or attr == 'modify_date' ):
value = format_date(e.get('display'))
elif attr == 'nom_note' or\
attr == 'auteur':
value = '|'.join(value.split('_RS_'))
#loop arround sources whatever a number...
elif attr == 'sources':
for child in e.iterdescendants():
if child.tag == 'SRC_MOT':
# UNIQUE_KEY
ref = (child.text, ref[1])
elif child.tag == 'S_REF':
refs = child.text.split(';')
for part in refs:
# remove surrounding spaces (trim)
r = part.strip()
# merge multiple spaces into one
r = ' '.join(r.split())
self.add_source_reference((ref[0], r))
setattr(self, attr, value)
return None
def end(self, e):
if e.tag == self.TAG:
values = []
for attr in self.FIELDS:
value = getattr(self, attr, '') or ''
values.append(value)
csv = self.separator.join('"{0}"'.format(w) for w in values)
self.reset()
return csv
return None
def reset(self):
for attr in self.FIELDS:
if hasattr(self, attr):
delattr(self, attr)
def add_source_reference(self, ref):
try:
index = SOURCES_REFS.index(ref)
SOURCES_DUPS[0] += 1
except ValueError: # first reference
index = len(SOURCES_REFS)
SOURCES_REFS.append(ref)
try:
if index not in self.sources:
self.sources.append(index)
except AttributeError:
setattr(self, 'sources', [index, ])
def reset(self):
for attr in self.OLDS.values():
if hasattr(self, attr):
delattr(self, attr)
def format_date(value):
parts = value.split('/')
dd = parts[0].strip()
mm = parts[1].strip()
yyyy = parts[2].strip()[:4]
return '%s/%s/%s' % (yyyy, mm, dd)
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Traceback (most recent call last):
File "C:\Users\sim\Desktop\script export\en cours\convert.py", line 65, in <module>
parse(create_parser().parse_args())
File "C:\Users\sim\Desktop\script export\en cours\convert.py", line 61, in parse
write_csv(fd, context, target)
File "C:\Users\sim\Desktop\en cours\convert.py", line 39, in write_csv
line = getattr(target, action)(e)
File "C:\Users\sim\Desktop\en cours\note.py", line 37, in start
ref = (child.text, ref[1])
UnboundLocalError: local variable 'ref' referenced before assignment
Et sur mon csv la colonne "sources" est vide ! Comment mon code puis générer des lignes qui correspondent aux références "SRC_MOT" et "S_REF" ? cf: mon exemple.
dans le cas où on rentre pas dans cette condition, tu dois définir ta variable ref car ligne 45, cette variable risque de ne pas exister
ou alors vérifier que cette variable existe
elif child.tag == 'S_REF' and ref:
et après ligne 33 définir ref à la valeur None donc ref = None
- Edité par fred1599 16 juin 2021 à 11:44:14
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Traceback (most recent call last):
File "C:\Users\sim\Desktop\script export\en cours\convert.py", line 65, in <module>
parse(create_parser().parse_args())
File "C:\Users\sim\Desktop\script export\en cours\convert.py", line 61, in parse
write_csv(fd, context, target)
File "C:\Users\sim\Desktop\en cours\convert.py", line 39, in write_csv
line = getattr(target, action)(e)
File "C:\Users\sim\Desktop\en cours\note.py", line 37, in start
ref = (child.text, ref[1])
UnboundLocalError: local variable 'ref' referenced before assignment
Et sur mon csv la colonne "sources" est vide ! Comment mon code puis générer des lignes qui correspondent aux références "SRC_MOT" et "S_REF" ? cf: mon exemple.
- Edité par Linus_11 il y a 6 minutes
T'as cherché ce que voulait dire le message d'erreur ? Tu aurais pu répondre à ta question seul.
Ce que ça te dit, c'est que tu cherches à accéder à une valeur (ref[1]) alors que la variable ref n'existe pas encore, puisque que tu es en train de la créer et lui assigner une valeur (ref = ...)
J'ai compris que la variable n'est pas définie Mais quand je fais une initiation de 'value' + ref
le csv est vide cette fois-ci avec une autre erreur
elif attr == 'sources':
value = None
ref = (None, None) # (source, reference)
for child in e.iterdescendants():
if child.tag == 'SRC_MOT':
# UNIQUE_KEY
ref = (child.text, ref[1])
elif child.tag == 'S_REF':
refs = child.text.split(';')
for part in refs:
# remove surrounding spaces (trim)
r = part.strip()
# merge multiple spaces into one
r = ' '.join(r.split())
self.add_source_reference((ref[0], r))
setattr(self, attr, value)
\script export\en cours\note.py", line 78, in add_source_reference
if index not in self.sources:
TypeError: argument of type 'NoneType' is not iterable
ai-je dis qu'il fallait écrire ref = (None, None) ?
ai-je pas dis d'ajouter quelquechose dans ta ligne 9 ?
- Edité par fred1599 16 juin 2021 à 11:51:43
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Faut peut-être un peu que tu comprennes ce que tu fais, la ligne 9 était la ligne représentative de ta ligne 38 dans ton code original.
Donc tu n'as plus rien à faire si ce n'est montré l'ensemble du code avec les modifications, et indiquer les autres erreurs, à savoir que cette modification te permet d'éviter l'erreur "local variable ...".
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
script export\en cours\note.py", line 41, in start
ref = (child.text, ref[1])
TypeError: 'NoneType' object is not subscriptable
J'ai l'impression que c'est le contenue de 'ref[...]' qui pose problème / toujours vide ?
SOURCES_REFS = []
SOURCES_DUPS = [ 0 ]
class Note(object):
OLDS = {
'UNIQUE_KEY' : 'key',
'CREATE_DATE' : 'create_date',
'NOM' : 'nom_note',
'AUTEUR' : 'auteur',
'SRC' : 'sources',
}
FIELDS = list(OLDS.values())
TAG = 'NOTE'
def __init__(self, separator=';'):
self.separator = separator
def start(self, e):
if e.tag in self.OLDS.keys():
attr = self.OLDS[e.tag]
value = e.text.strip() if e.text else e.text
if ( attr == 'create_date' or attr == 'modify_date' ):
value = format_date(e.get('display'))
elif attr == 'nom_note' or\
attr == 'auteur':
value = '|'.join(value.split('_RS_'))
#loop arround sources whatever a number...
elif attr == 'sources':
# this SRC element will become Reference record
value = None # we shouldn't need this, but just in case
#ref = {'source': None, 'reference': None }
ref = None # (source, reference)
for child in e.iterdescendants():
if child.tag == 'SRC_MOT':
# UNIQUE_KEY
ref = (child.text, ref[1])
elif child.tag == 'S_REF' and ref:
refs = child.text.split(';')
for part in refs:
# remove surrounding spaces (trim)
r = part.strip()
# merge multiple spaces into one
r = ' '.join(r.split())
self.add_source_reference((ref[0], r))
setattr(self, attr, value)
return None
def end(self, e):
if e.tag == self.TAG:
values = []
for attr in self.FIELDS:
value = getattr(self, attr, '') or ''
values.append(value)
csv = self.separator.join('"{0}"'.format(w) for w in values)
self.reset()
return csv
return None
def reset(self):
for attr in self.FIELDS:
if hasattr(self, attr):
delattr(self, attr)
def add_source_reference(self, ref):
try:
index = SOURCES_REFS.index(ref)
SOURCES_DUPS[0] += 1
except ValueError: # first reference
index = len(SOURCES_REFS)
SOURCES_REFS.append(ref)
try:
if index not in self.sources:
self.sources.append(index)
except AttributeError:
setattr(self, 'sources', [index, ])
def format_date(value):
parts = value.split('/')
dd = parts[0].strip()
mm = parts[1].strip()
yyyy = parts[2].strip()[:4]
return '%s/%s/%s' % (yyyy, mm, dd)
Euh oui j'avais même pas remarqué cette erreur de logique,
Il faut définir ce qu'est ref et sa valeur avant ces conditions, et elles ne vaudront sans doute pas None
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
D'après ma logique le tuple 'ref' devait être initialisée, puisque elle va accueillir le contenu des tags 'MOT_SRC' et 'S_REF' à chaque fois que la condition est vraie et qu'il y a du contenu dans les balises...
umfred, mon script fonctionne tr-s bien quand les champs sont uniques dans un noeud, ici la particularité est qu'on va chercher plusieurs tags identiques dans le même noeud...
alors pourquoi tu appelles ref[1] si tu l'initialises au même endroit, sachant qu'il n'est pas encore initialisé ?
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
pourquoi ref doit être un tuple ? puisque tu donnes toujours le même 2ème élément et que tu ne récupères que le 1er ensuite
Non parce-que regarde plus bas
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Je ne vois pas où ref[1] est utilisé dans le code sauf sur la ligne d'affectation de ref (ligne 41 du dernier code)
Ce n'est plus un problème python, mais de concept... À lui de revoir la manière dont il doit résoudre ce problème
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
ref = None
for child in e.iterdescendants():
if child.tag == 'SRC_MOT':
# UNIQUE_KEY
ref = child.text
elif child.tag == 'S_REF' and ref:
refs = child.text.split(';')
for part in refs:
# remove surrounding spaces (trim)
r = part.strip()
# merge multiple spaces into one
r = ' '.join(r.split())
self.add_source_reference((ref, r))
ref=None # à rajouter ici, je pense
Je n'ai effectivement plus d'erreurs, en revanche, dans la colonne sources de mon csv reste vide, aucune data n'est générée...
Je me demande c'est c'est pas mieux avec cette logique pour générer les ressources (SRC_MOT et S_REF)
la data est générée dans le csv, j'ai alors une seule la première ressource générée si la ligne et au même niveau que la boucle
value = my_dict
si la ligne est indenté à l'intérieur on génère la dernière
def start(self, e):
if e.tag in self.OLDS.keys():
attr = self.OLDS[e.tag]
value = e.text.strip() if e.text else e.text
if ( attr == 'create_date' or attr == 'modify_date' ):
value = format_date(e.get('display'))
elif attr == 'nom_note' or\
attr == 'auteur':
value = '|'.join(value.split('_RS_'))
#loop arround sources whatever a number...
elif attr == 'sources':
value = None
#ref = {'source': None, 'reference': None }
ref = None
for child in e.iterdescendants():
if child.tag == 'SRC_MOT':
# UNIQUE_KEY
my_dict["Sources_mots"] = child.text
elif child.tag == 'S_REF':
my_dict["references"] = child.text
value = my_dict
setattr(self, attr, value)
return None
- Edité par Linus_11 17 juin 2021 à 16:35:13
Nobody is perfect I'm Nobody...
Boucler sur des balises xml et exporter dans csv
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Nobody is perfect I'm Nobody...
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Nobody is perfect I'm Nobody...
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Nobody is perfect I'm Nobody...
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Nobody is perfect I'm Nobody...
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Nobody is perfect I'm Nobody...
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Nobody is perfect I'm Nobody...
Nobody is perfect I'm Nobody...
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Nobody is perfect I'm Nobody...