忽略Python和Jinja2中的重复块

时间:2019-06-19 07:22:54

标签: python yaml jinja2

我需要避免输出中出现重复信息。我有一个yaml配置文件,如下所示。

**##CONFIG FILE**
vm_details: 
  vm1: 
    vm_flavour_name: small40
    vm_name: VM1
    vdu_connection_point: 
      CP1: 
        cp_name: OAM
        cp_net: NET1
        cp_interface_name: eth0
        cp_allowed_address_pairs: 10.69.15.0/24
      CP2: 
        cp_name: Tunnel
        cp_net: NET2
        cp_interface_name: eth1
        cp_allowed_address_pairs: 10.69.16.0/24
  vm2: 
    vm_flavour_name: small40
    vm_name: VM2
    vdu_connection_point: 
      CP1: 
        cp_name: OAM
        cp_net: NET1
        cp_interface_name: eth0
        cp_allowed_address_pairs: 10.69.15.0/24
      CP2: 
        cp_name: Tunnel
        cp_net: NET2
        cp_interface_name: eth1
        cp_allowed_address_pairs: 10.69.16.0/24
      CP3: 
        cp_name: EMX
        cp_net: NET3
        cp_interface_name: eth2
        cp_allowed_address_pairs: 10.69.17.0/24


**##Template File**

{% for vm_id, vm_info in vm_details.items()%}
    {% for cp_id,cp_info in vm_info.vm_connection_point.items() %}

<vm_details>
<id>{{ loop.index }}</id>
<cp_name>{{ cp_info['cp_name'] }}</cp_name>
<cp_net>{{ cp_info['cp_net_name'] }}</cp_net>
    <vm_depends_on>
{% set cp_name_vm_name = cp_info.cp_name %}
    {% for vm_id_alloc, vm_info_alloc in vm_details.items()%}
        {% for cp_id_alloc,cp_info_alloc in vm_info_alloc.vm_connection_point.items() %}
            {% if cp_info_alloc.cp_name == cp_name_vm_name %}
                    <vm>{{ vm_info_alloc['vm_name'] }}</vm>
            {% endif %}
        {% endfor %}
    {% endfor %}
    </vm_depends_on>
</vm_details>
{% endfor %}
{% endfor %}


**##Python Code**

from jinja2 import Environment, FileSystemLoader, PackageLoader, select_autoescape

import yaml
import sys
import os
import os.path
import string
import platform
import uuid
import urllib2, base64, json
import ConfigParser, glob
import io
import shutil
import variable


sample_config = yaml.load(open('tosca_config.yml').read())
print sample_config

file_loader = FileSystemLoader('templates')
env = Environment(loader=file_loader,autoescape=True,trim_blocks=False,keep_trailing_newline=True)
template = env.get_template('vldd.txt')
autoescape = select_autoescape(['html', 'xml', 'Txt', 'txt', 'ml', 'ms', 'script.txt', 'Script.Txt']),

with open("templates/vld_temp.xml", "w") as fh:

    output_from_parsed_template=template.render(sample_config)

print(output_from_parsed_template)

with open("templates/vld_temp.xml", "w") as fh:
     fh.write(output_from_parsed_template)

with open('templates/vld_temp.xml') as infile, open('templates/vld.xml', 'w') as outfile:
    for line in infile:
        if not line.strip(): continue  # skip the empty line
        outfile.write(line)  # non-empty line. Write it to output

os.remove('templates/vld_temp.xml')

我能够使用模板从配置文件中解析数据并从中创建xml文件。但是问题是我也要得到重复的设置。

想法是为cp_name和cp_net创建vm_depends_on列表。

**###Expected-Result:**
<vm_details>
<id>1</>
<cp_name>OAM</cp_name>
<cp_net>NET1</cp_net>
<vm_depends_on>
    <vm>VM1</vm>
    <vm>VM2</vm>
</vm_depends_on>
</vm_details>

<vm_details>
<id>2</>
<cp_name>Tunnel</cp_name>
<cp_net>NET2</cp_net>
<vm_depends_on>
    <vm>VM1</vm>
    <vm>VM2</vm>
</vm_depends_on>
</vm_details>

<vm_details>
<id>3</>
<cp_name>EMX</cp_name>
<cp_net>NET3</cp_net>
<vm_depends_on>
    <vm>VM2</vm>
</vm_depends_on>
</vm_details>

**###Current-Result:**

<vm_details>
    <id>1</id>
    <cp_name>OAM</cp_name>
    <cp_net>NET1</cp_net>
    <vm_depends_on>
        <vm>VM2</vm>
        <vm>VM1</vm>
    </vm_depends_on>
</vm_details>
<vm_details>
    <id>2</id>
    <cp_name>Tunnel</cp_name>
    <cp_net>NET2</cp_net>
    <vm_depends_on>
        <vm>VM2</vm>
        <vm>VM1</vm>
    </vm_depends_on>
</vm_details>
<vm_details>
    <id>3</id>
    <cp_name>EMX</cp_name>
    <cp_net>NET3</cp_net>
    <vm_depends_on>
        <vm>VM2</vm>
    </vm_depends_on>
</vm_details>
<vm_details>
    <id>1</id>
    <cp_name>OAM</cp_name>
    <cp_net>NET1</cp_net>
    <vm_depends_on>
        <vm>VM2</vm>
        <vm>VM1</vm>
    </vm_depends_on>
</vm_details>
<vm_details>
    <id>2</id>
    <cp_name>Tunnel</cp_name>
    <cp_net>NET2</cp_net>
    <vm_depends_on>
        <vm>VM2</vm>
        <vm>VM1</vm>
    </vm_depends_on>
</vm_details>

1 个答案:

答案 0 :(得分:0)

看起来您的输入YML与预期的输出结构非常相似。您最好只在应用程序逻辑中进行一些必要的数据转换,然后使用XML库,您可以利用dicttoxml之类的库。另外,我强烈建议您使用Python 3代替2,Python 2 end of life is in half a year

Python代码

import yaml
from dicttoxml import dicttoxml
# … other imports here

def transform_vm_config(config_data):  
   pass
   # Your data transformations here

# Transform input YML to output XML-format
sample_config = yaml.load(open('tosca_config.yml').read())
vm_data = transform_vm_config(sample_config)
vm_xml = dicttoxml(vm_data)

# Write to file
print(vm_xml)