7

我正在尝试从 yaml 文件中解析具有类似于 jinaj2 模板语法的表达式的数据,目标是删除或添加一些项目到文件中。

AddCodesList.yaml

AddCodesList:
  body:
    list:
    {% for elt in customer %}
      - code: {{ elt.code }}
        name: {{ elt.name }}
        country: {{ elt.country }}
    {% endfor %}   
  result:
    json:
      responseCode: {{ responseCode }}
      responseMsg: {{ responseMsg }}
      responseData: {{ responseData }}

解析文件.py

import ruamel.yaml
from ruamel.yaml.util import load_yaml_guess_indent

data,indent,block_seq_indent=load_yaml_guess_indent(open('AddCodesList.yaml'), preserve_quotes=True)

#delete item
del data['body']['list']['code']
#add new item
data['parameters'].insert(2, 'ssl_password','xxxxxx')#create new file
ruamel.yaml.round_trip_dump(data, open('missingCode.yaml', 'w'), explicit_start=True)

执行 parseFile.py 脚本时出现以下错误:

    Traceback (most recent call last):
      File "d:/workspace/TEST/manageItem.py", line 4, in <module>
        data, indent, block_seq_indent = load_yaml_guess_indent(open('AddCodesList.
...
        if self.check_token(ValueToken):
      File "C:\Python34\lib\site-packages\ruamel\yaml\scanner.py", line 1534, in ch
        self.fetch_more_tokens()
      File "C:\Python34\lib\site-packages\ruamel\yaml\scanner.py", line 269, in fet
        % utf8(ch), self.get_mark())
    ruamel.yaml.scanner.ScannerError: while scanning for the next token
    found character '%' that cannot start any token
      in "<unicode string>", line 4, column 6:
            {% for elt in customer %}
             ^ (line: 4)
4

2 回答 2

5

在 YAML 中,'{' 启动流式映射,因此 ( %) 将成为该映射的第一个键的开始,并且该字符不允许作为第一个字符。

通常您会先处理文件的模板,然后再应用 YAML。您不能轻易地逆转该过程,因为 list 的值必须是有效的 YAML 构造。

使其可解析的解决方案之一是将值更改为list有效的 YAML,例如:

list:
  - {% for elt in customer %}
  - code: {{ elt.code }}
    name: {{ elt.name }}
    country: {{ elt.country }}
  - {% endfor %} 

或者:

list: |
    {% for elt in customer %}
      - code: {{ elt.code }}
        name: {{ elt.name }}
        country: {{ elt.country }}
    {% endfor %} 

这将不再使其成为可模板化的 bij jinja2。

您可以更改 jinja2 from 中的开始顺序,{%但这对您没有帮助(即您仍然无法获得有效的 YAML)。我目前看到的唯一真正的解决方案是完全放弃 jinja2 并for使用 Python 中的一些类似对象的列表来实现循环(在访问时得到扩展)。

如果允许在应用 jinja2 之前始终进行预处理,则可以将文件更改为:

AddCodesList:
  body:
    list:
    # {% for elt in customer %}
      - code: '{{ elt.code }}'
        name: '{{ elt.name }}'
        country: '{{ elt.country }}'
    # {% endfor %}   

因为那会加载,但您可能需要在运行模板引擎之前将其更改# b{为。{

单引号之间的引用只有单引号具有特殊含义。使用双引号,您通常会得到预处理器插入的内容,这会使 YAML 不正确(例如 DOS/Windows 样式的完整文件路径:'C:\yaml\abc.yaml'是正确的,但"c:\yaml\abc.yaml"会在 YAML 解析期间给您一个错误。

于 2017-02-16T10:20:31.287 回答
2

通过以下结构解决了该问题:

AddCodesList:
  body:
    list:
    # {% for elt in customer %}
      - code: "{{ elt.code }}"
        name: "{{ elt.name }}"
        country: "{{ elt.country }}"
    # {% endfor %}  
于 2017-02-16T16:04:45.483 回答