2017-10-11 1 views
1

J'ai besoin de convertir un fichier spec csv en fichier YAML pour les besoins du projet. J'ai écrit un petit morceau de code python pour ça mais ça ne fonctionne pas comme prévu. Je ne peux pas utiliser de convertisseur en ligne parce que le client pour lequel je travaille n'acceptera pas cela. Voici le code python je:Conversion CSV vers Yaml en utilisant le script Python

import csv 
csvfile = open('custInfo.csv', 'r') 

datareader = csv.reader(csvfile, delimiter=',', quotechar='"') 
data_headings = [] 

yaml_pretext = "sourceTopic : 'BIG_PARTY'" 
yaml_pretext += "\n"+'validationRequired : true'+"\n" 
yaml_pretext += "\n"+'columnMappingEntityList :'+"\n" 
for row_index, row in enumerate(datareader): 
    if row_index == 0: 
     data_headings = row 
    else: 
     # new_yaml = open('outfile.yaml', 'w') 
     yaml_text = "" 
     for cell_index, cell in enumerate(row): 
      lineSeperator = " " 
      cell_heading = data_headings[cell_index].lower().replace(" ", "_").replace("-", "") 
      if (cell_heading == "source"): 
       lineSeperator = ' - ' 

      cell_text = lineSeperator+cell_heading + " : " + cell.replace("\n", ", ") + "\n" 

      yaml_text += cell_text 
     print yaml_text 

csvfile.close() 

Le fichier csv a 4 colonnes et voici:

source    destination  type  childFields 
fra:AppData   app_data   array application_id,institute_nm 
fra:ApplicationId application_id  string null 
fra:InstituteName institute_nm  string null 
fra:CustomerData  customer_data  array name,customer_address,telephone_number 
fra:Name    name    string null 
fra:CustomerAddress customer_address array street,pincode 
fra:Street   street    string null 
fra:Pincode   pincode   string null 
fra:TelephoneNumber telephone_number string null 

Voici le fichier YAML que je reçois en sortie

- source : fra:AppData 
    destination : app_data 
    type : array 
    childfields : application_id,institute_nm 

    - source : fra:ApplicationId 
    destination : application_id 
    type : string 
    childfields : null 

    - source : fra:InstituteName 
    destination : institute_nm 
    type : string 
    childfields : null 

    - source : fra:CustomerData 
    destination : customer_data 
    type : array 
    childfields : name,customer_address,telephone_number 

    - source : fra:Name 
    destination : name 
    type : string 
    childfields : null 

    - source : fra:CustomerAddress 
    destination : customer_address 
    type : array 
    childfields : street,pincode 

    - source : fra:Street 
    destination : street 
    type : string 
    childfields : null 

    - source : fra:Pincode 
    destination : pincode 
    type : string 
    childfields : null 

    - source : fra:TelephoneNumber 
    destination : telephone_number 
    type : string 
    childfields : null 

Lorsque le type est array, j'ai besoin de la sortie en tant que childField, à la place dans une nouvelle ligne. Donc, la sortie désirée sera:

- source : fra:AppData 
    destination : app_data 
    type : array 
    childfields : application_id,institute_nm 
     - source : fra:ApplicationId 
     destination : application_id 
     type : string 
     childfields : null 

     - source : fra:InstituteName 
     destination : institute_nm 
     type : string 
     childfields : null 

    - source : fra:CustomerData 
    destination : customer_data 
    type : array 
    childfields : name,customer_address,telephone_number 
     - source : fra:Name 
     destination : name 
     type : string 
     childfields : null 

     - source : fra:CustomerAddress 
     destination : customer_address 
     type : array 
     childfields : street,pincode 
      - source : fra:Street 
      destination : street 
      type : string 
      childfields : null 

      - source : fra:Pincode 
      destination : pincode 
      type : string 
      childfields : null 

     - source : fra:TelephoneNumber 
     destination : telephone_number 
     type : string 
     childfields : null 

Quelqu'un peut-il m'aider s'il vous plaît comment puis-je obtenir cela? Appréciez votre aide

Merci à l'avance

Krishna

+0

Vous avez donc besoin de deux en-tête principal seulement - AppData ou CustomerData? –

+0

Pas exactement. Il ne s'agit pas d'avoir des en-têtes principaux, Si le type est array, il aura des champs enfants. alors les champs enfants seront disponibles avec un peu d'indentation – user3444971

Répondre

1

Vous n'êtes pas utiliser une bibliothèque YAML pour générer la sortie. Ceci est une mauvaise pratique, car vous ne vérifiez pas si le contenu de la chaîne que vous produisez contient des caractères spéciaux YAML qui devraient l'être.

Ensuite, ce n'est pas YAML valide:

childfields : application_id,institute_nm 
     - source : fra:ApplicationId 
     destination : application_id 
     type : string 
     childfields : null 

childfields ne peut pas avoir à la fois une valeur scalaire (application_id,institute_nm) et une valeur de séquence (en commençant par l'élément - source : fra:ApplicationId).

Essayez la génération de votre structure avec des listes et dicts puis Dump structure:

import yaml,csv 

csvfile = open('custInfo.csv', 'r') 
datareader = csv.reader(csvfile, delimiter=",", quotechar='"') 
result = list() 
type_index = -1 
child_fields_index = -1 

for row_index, row in enumerate(datareader): 
    if row_index == 0: 
    # let's do this once here 
    data_headings = list() 
    for heading_index, heading in enumerate(row): 
     fixed_heading = heading.lower().replace(" ", "_").replace("-", "") 
     data_headings.append(fixed_heading) 
     if fixed_heading == "type": 
     type_index = heading_index 
     elif fixed_heading == "childfields": 
     child_fields_index = heading_index 
    else: 
    content = dict() 
    is_array = False 
    for cell_index, cell in enumerate(row): 
     if cell_index == child_fields_index and is_array: 
     content[data_headings[cell_index]] = [{ 
      "source" : "fra:" + value.capitalize(), 
      "destination" : value, 
      "type" : "string", 
      "childfields" : "null" 
      } for value in cell.split(",")] 
     else: 
     content[data_headings[cell_index]] = cell 
     is_array = (cell_index == type_index) and (cell == "array") 
    result.append(content) 
print yaml.dump(result)