Search code examples
yamlpyyaml

YAML appending DATA within a file


I have a YAML file of this sort:

Main_part1:
   label1: Main PArt1


Main_part2:
   label2: Main Part2


A_part1:
  label3: part1 of A

A_part2:
   label4: part 2 of A

B_part1:
    label5: this is part 1 of B

B_part2:
  label6: this is part 2 of B

I have an html file with 2 <div> tags for A and B. Whenever A is clicked, contents of A_part1 should append to Main_part1 and A_part2 should append to contents of Main_part2. Similarly for B. And send a response back to web page that contents of A/B added.

Finally, I want to Create a final YAML file merging Main_Part1 and Main_Part2.

Any sort of solution(Java/Python etc) can be used.

I have created different labels to show that inside info in all blocks are different. As an example:

Say you click A, YAML file will look like:

Main_part1:
   label1: Main PArt1
   label3: part1 of A
Main_part2:
   label2: Main Part2
   label4: part 2 of A

A_part1:
   label3: part1 of A

A_part2:
   label4: part 2 of A

B_part1:
   label5: this is part 1 of B

B_part2:
   label6: this is part 2 of B

And then a final YAML file merging Main_part1 and Main_part2.


Solution

  • The keys as you have them don't really work that well for this operation, so the best thing to do is parse the keys of the toplevel key to an alternate dictionary, with keys pointing to the same (dictionary) values as the original mapping/dict:

    import sys
    import ruamel.yaml
    
    yaml_str = """\
    Main_part1:
       label1: Main PArt1
    Main_part2:
       label2: Main Part2
    A_part1:
      label3: part1 of A
    A_part2:
       label4: part 2 of A
    B_part1:
        label5: this is part 1 of B
    B_part2:
      label6: this is part 2 of B
    """
    
    data = ruamel.yaml.round_trip_load(yaml_str)
    alt = {}
    for key in data:
        section, part = key.split('_')
        alt[(section, part)] = data[key]
    alt[('Main', 'part1')].update(alt[('Main', 'part2')])
    

    after that you need a little helper, call it and dump the original:

    def collapse(collapse_key):
        for key in alt:
            if key[0] == collapse_key:
                alt[('Main', key[1])].update(alt[key])
    
    collapse('A')  # <- this should be a parameter to your script based on the click.
    
    ruamel.yaml.round_trip_dump(data, sys.stdout)
    

    gives:

    Main_part1:
      label1: Main PArt1
      label3: part1 of A
      label2: Main Part2
      label4: part 2 of A
    Main_part2:
      label2: Main Part2
      label4: part 2 of A
    A_part1:
      label3: part1 of A
    A_part2:
      label4: part 2 of A
    B_part1:
      label5: this is part 1 of B
    B_part2:
      label6: this is part 2 of B
    

    It would of course be somewhat easier if you created the keys in a way that you are going to use them (i.e. with two elements):

    (Main, part1):
       label1: Main PArt1
    (Main, part2):
       label2: Main Part2
    (A, part1):
      label3: part1 of A
    (A, part2):
       label4: part 2 of A
    (B, part1):
        label5: this is part 1 of B
    (B, part2):
      label6: this is part 2 of B
    

    the above is perfectly fine YAML, although not accepted by all parsers.