আমি কীভাবে অন্যের মধ্যে একটি ওয়াইএমএল ফাইল অন্তর্ভুক্ত করতে পারি?


288

সুতরাং আমার কাছে দুটি এআইএএমএল ফাইল রয়েছে, "এ" এবং "বি" এবং আমি চাই চাই যে এ এর ​​বিষয়বস্তু বি এর ভিতরে toোকানো হবে, হয় বিদ্যমান ডাটা স্ট্রাকচারে বিভক্ত করা হবে, অ্যারের মতো, বা একটি উপাদানের শিশু হিসাবে, মান হিসাবে একটি নির্দিষ্ট হ্যাশ কী জন্য।

এটা কি আদৌ সম্ভব? কিভাবে? যদি না হয়, কোনও আদর্শিক রেফারেন্সের জন্য কোনও পয়েন্টার?



1
আমি পাইথনের জন্য হাই হাইপাইকোতে সম্প্রতি ঝাঁপিয়ে পড়েছি যা ঠিক এটি করে। আপনি বিভিন্ন YAML ফাইল একসাথে একত্রী করতে পারেন। এটি একটি খুব সুন্দর পাইথন মডিউল যা জানা দরকার।
এখন

উত্তর:


326

না, YAML কোনও ধরণের "আমদানি" বা "অন্তর্ভুক্ত" বিবৃতি অন্তর্ভুক্ত করে না।


8
আপনি একটি তৈরি করতে পারেন <ফাইল >> হ্যান্ডলার অন্তর্ভুক্ত।
ক্লার্কেভানস

5
@ ক্লার্কেভেনরা নিশ্চিত, তবে এই নির্মাণটি ওয়াইএএমএল ভাষার "বাইরের" হবে।
জামেশফিশার

2
এটা এখন সম্ভব। আমি নীচে একটি উত্তর যুক্ত করেছি ... আশা করি এটি সাহায্য করবে।
ডেভাস্পিনাল

1
আপনি যদি রেলগুলি ব্যবহার করছেন তবে আপনি <% = 'fdsa fdsa'%> ERB সিনট্যাক্স সন্নিবেশ করতে পারেন এবং এটি কাজ করবে
gleenn

9
আমি মনে করি এই উত্তরটিকে "না, স্ট্যান্ডার্ড ওয়াইএএমএল এই ফাংশনটি অন্তর্ভুক্ত করে না as হিসাবে আবার জবাব দেওয়া উচিত Nevertheless তবুও অনেকগুলি বাস্তবায়ন এটি করার জন্য কিছু প্রসার সরবরাহ করে provides"
ফ্রাঙ্কলিন ইউ

112

আপনার প্রশ্নটি পাইথন সমাধানের জন্য জিজ্ঞাসা করে না, তবে এখানে পাই পাইএএমএল ব্যবহার করা হচ্ছে

পাইওয়ামএল আপনাকে কাস্টম কনস্ট্রাক্টরগুলি (যেমন !include) ওয়াইএএমএল লোডারের সাথে সংযুক্ত করার অনুমতি দেয় । আমি একটি মূল ডিরেক্টরি অন্তর্ভুক্ত করেছি যাতে সেট করা যায় যাতে এই সমাধানটি আপেক্ষিক এবং পরম ফাইল রেফারেন্সকে সমর্থন করে।

ক্লাস-ভিত্তিক সমাধান

এখানে একটি শ্রেণিবদ্ধ সমাধান রয়েছে যা আমার আসল প্রতিক্রিয়ার গ্লোবাল রুট ভেরিয়েবলকে এড়িয়ে চলে।

এই দেখুন সারকথা একটি অনুরূপ, আরো শক্তসমর্থ পাইথন 3 সমাধান কাস্টম কন্সট্রাকটর রেজিস্টার করার জন্য একটি ক্লাসের অধীনে একটি ক্লাস ব্যবহার করে জন্য।

import yaml
import os

class Loader(yaml.SafeLoader):

    def __init__(self, stream):

        self._root = os.path.split(stream.name)[0]

        super(Loader, self).__init__(stream)

    def include(self, node):

        filename = os.path.join(self._root, self.construct_scalar(node))

        with open(filename, 'r') as f:
            return yaml.load(f, Loader)

Loader.add_constructor('!include', Loader.include)

একটি উদাহরণ:

foo.yaml

a: 1
b:
    - 1.43
    - 543.55
c: !include bar.yaml

bar.yaml

- 3.6
- [1, 2, 3]

এখন ফাইলগুলি ব্যবহার করে লোড করা যেতে পারে:

>>> with open('foo.yaml', 'r') as f:
>>>    data = yaml.load(f, Loader)
>>> data
{'a': 1, 'b': [1.43, 543.55], 'c': [3.6, [1, 2, 3]]}

এটি একটি ইন্টারেস্টিং বৈশিষ্ট্য, থেক্স। তবে মূল / পুরাতন_রোট দিয়ে এই সমস্ত হেরফেরগুলির উদ্দেশ্য কী? আমি মনে করি includeফাংশনের কোডটি সহজতর করা যায়: `Def অন্তর্ভুক্ত (লোডার, নোড):" "" অন্য একটি YAML ফাইল অন্তর্ভুক্ত করুন "" "" ফাইলের নাম = লোডারকন্ট্রাস্ট_সালার (নোড) ডেটা = ইয়ামললোড (খোলা (ফাইলের নাম)) `
আলিয়াক্সেই রামানাউ

মূল গ্লোবালটি রয়েছে যাতে আপেক্ষিক যে কোনও গভীরতায় কাজ অন্তর্ভুক্ত করে, উদাহরণস্বরূপ যখন কোনও ভিন্ন ডিরেক্টরিতে বসে ফাইল অন্তর্ভুক্ত থাকে তখন সেই ডিরেক্টরিটির সাথে সম্পর্কিত একটি ফাইল অন্তর্ভুক্ত থাকে। সম্পূর্ণ অন্তর্ভুক্ত কাজ করা উচিত। বিশ্বব্যাপী পরিবর্তনশীল ছাড়াই এটি করার একটি ক্লিনার উপায় সম্ভবত রয়েছে, সম্ভবত একটি কাস্টম ইয়ামল.লুডার ক্লাস ব্যবহার করে।
জোশ বোদে

2
এর মতো কিছু পাওয়াও কি সম্ভব: foo.yaml: a: bla bar.yaml: `! Foo.yaml বি: ব্লুববি অন্তর্ভুক্ত করুন যাতে ফলস্বরূপ হয়:` {'এ': ব্লে, 'বি': ব্লাব b
মার্টিন

3
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। এছাড়াও, একটি সুরক্ষার নটপিক, আপনার পরিষেবাটি মালিকানা থেকে বিশেষভাবে তৈরি যমল এড়াতে আপনার yaml.safeload ব্যবহার করা উচিত।
ড্যানিয়েলপপস

1
@ জোশবোড এটি আপনার জন্য কাজ করা উচিত: gist.github.com/danielpops/5a0726f2fb6288da749c4cd604276be8
ড্যানিপপপস

32

আপনি যদি সিএফফোনির ওয়াইএএমএল সংস্করণ ব্যবহার করেন তবে এটি এর মতো সম্ভব:

imports:
    - { resource: sub-directory/file.yml }
    - { resource: sub-directory/another-file.yml }

34
এটি সিমফনি ওয়াইএএমএল এর নিজের অংশের চেয়ে YAML এর ব্যাখ্যা কীভাবে সুনির্দিষ্ট।
জামেশফিশার

9
হ্যাঁ, এজন্য আমি সিমফনি ডক্সের লিঙ্কটি পোস্ট করেছি। প্রশ্নটি জিজ্ঞাসা করে "এটি কি আদৌ সম্ভব? কীভাবে?" ... এভাবেই হয়। ডাউনটোটের কোনও কারণ দেখুন না।
ডেভাস্পিনাল

4
আমি তোমাকে উড়িয়ে দিই নি; আমি কেবল ইঙ্গিত করছি যে এটি সিমফনি ওয়াইএএমএল-এর সাথে নির্দিষ্ট।
জামেশফিশার

9
"YAML এর সিম্ফনি সংস্করণ নেই" ... এটি কেবলমাত্র বিক্রেতা-নির্দিষ্ট YAML- সামঞ্জস্যপূর্ণ লাইব্রেরিতে অতিরিক্ত স্টাফ রয়েছে যা YAML এর অংশ নয়।
dreftymac

3
যদি "শ্রেণিভিত্তিক" উত্তরটি আপগ্রেটেড হয় তবে এই উত্তরটিকে নিম্নমান দেওয়ার কোনও কারণ নেই।
মিখাইল

13

আমি যতদূর জানি ওয়াইএএমএলে অন্তর্ভুক্তগুলি সরাসরি সমর্থন করে না, আপনাকে নিজেই একটি ব্যবস্থা সরবরাহ করতে হবে তবে এটি করা সহজ generally

আমি আমার অজগর অ্যাপগুলিতে কনফিগারেশন ভাষা হিসাবে ওয়াইএএমএল ব্যবহার করেছি এবং এক্ষেত্রে প্রায়শই এই জাতীয় সম্মেলনটি সংজ্ঞায়িত করা হয়:

>>> main.yml <<<
includes: [ wibble.yml, wobble.yml]

তারপরে আমার (অজগর) কোডটিতে আমি এটি করি:

import yaml
cfg = yaml.load(open("main.yml"))
for inc in cfg.get("includes", []):
   cfg.update(yaml.load(open(inc)))

একমাত্র নীচের দিকটি হ'ল এর মধ্যে থাকা ভেরিয়েবলগুলি সর্বদা মূল ভেরিয়েবলগুলিকে ওভাররাইড করে and

কিছুটা ভিন্ন বিন্দুতে, ওয়াইএএমএল সমর্থন করে না কারণ এটি কোনও ফাইল ভিত্তিক মার্ক আপের মতোই কেবল ডিজাইন করা হয়নি। যদি আপনি এজেএক্সের অনুরোধের প্রতিক্রিয়াতে এটি পেয়ে থাকেন তবে এর অর্থ কী হবে?


3
এটি কেবল তখনই কাজ করে যখন ইয়ামল ফাইলে নেস্টেড কনফিগারেশন না থাকে।
স্বাধীনতা

10

পাইথন ব্যবহারকারীদের জন্য, আপনি পাইমল-অন্তর্ভুক্ত করার চেষ্টা করতে পারেন ।

ইনস্টল করুন

pip install pyyaml-include

ব্যবহার

import yaml
from yamlinclude import YamlIncludeConstructor

YamlIncludeConstructor.add_to_loader_class(loader_class=yaml.FullLoader, base_dir='/your/conf/dir')

with open('0.yaml') as f:
    data = yaml.load(f, Loader=yaml.FullLoader)

print(data)

আমাদের যেমন YAML ফাইল রয়েছে তা বিবেচনা করুন :

├── 0.yaml
└── include.d
    ├── 1.yaml
    └── 2.yaml
  • 1.yaml এর বিষয়বস্তু:
name: "1"
  • 2.yaml এর বিষয়বস্তু:
name: "2"

নাম অনুসারে ফাইল অন্তর্ভুক্ত করুন

  • শীর্ষ স্তরে:

    যদি 0.yamlছিল:

!include include.d/1.yaml

আমরা পাবো:

{"name": "1"}
  • ম্যাপিংয়ে:

    যদি 0.yamlছিল:

file1: !include include.d/1.yaml
file2: !include include.d/2.yaml

আমরা পাবো:

  file1:
    name: "1"
  file2:
    name: "2"
  • ক্রমানুসারে:

    যদি 0.yamlছিল:

files:
  - !include include.d/1.yaml
  - !include include.d/2.yaml

আমরা পাবো:

files:
  - name: "1"
  - name: "2"

দ্রষ্টব্য :

ফাইলের নাম হয় পরম (মত /usr/conf/1.5/Make.yml) বা আপেক্ষিক (মত ../../cfg/img.yml) হতে পারে।

ওয়াইল্ডকার্ড দ্বারা ফাইল অন্তর্ভুক্ত

ফাইলের নামটিতে শেল-স্টাইলের ওয়াইল্ডকার্ড থাকতে পারে। ওয়াইল্ডকার্ডগুলির দ্বারা পাওয়া ফাইল (গুলি) থেকে লোড করা ডেটা একটি সিকোয়েন্সে সেট করা হবে।

যদি 0.yamlছিল:

files: !include include.d/*.yaml

আমরা পাবো:

files:
  - name: "1"
  - name: "2"

দ্রষ্টব্য :

  • কারণ Python>=3.5, ওয়াইএএমএল ট্যাগের recursiveযুক্তি যদি হয় তবে প্যাটার্নটি কোনও ফাইল এবং শূন্য বা আরও বেশি ডিরেক্টরি এবং সাব ডিরেক্টরিতে মিলবে।!include true“**”
  • “**”বৃহত ডিরেক্টরি গাছগুলিতে প্যাটার্নটি ব্যবহার করা পুনরাবৃত্ত অনুসন্ধানের কারণে খুব বেশি সময় ব্যয় করতে পারে।

recursiveযুক্তি সক্ষম করার জন্য , আমরা !includeট্যাগ Mappingবা Sequenceমোডে ট্যাগটি লিখব :

  • Sequenceমোডে যুক্তি :
!include [tests/data/include.d/**/*.yaml, true]
  • Mappingমোডে যুক্তি :
!include {pathname: tests/data/include.d/**/*.yaml, recursive: true}

এটি আসলে প্রশ্নের উত্তর দেয় না। এটি পাইথন সমাধানের সাথে সম্পর্কিত, মানক YAML ফর্ম্যাটটি ব্যবহার করে না।
অলিগোফ্রেন

@ অলিগোফ্রেন কাস্টম ট্যাগ হ্যান্ডলারগুলি ওয়াইএএমএলের একটি বৈশিষ্ট্য, পার্সারদের ওয়াইএএমএলকে প্রকারগুলি নির্দিষ্ট করতে এবং এগুলির মতো কাস্টম আচরণগুলি বাস্তবায়নের অনুমতি দেয়। ওয়াইএএমএল স্পেসিফিকেশনের পক্ষে নিজেই যতদূর যেতে পারে যে সমস্ত অসম্পূর্ণ ওএস পাথ স্পেস, ফাইল সিস্টেম ইত্যাদির সাথে ফাইল অন্তর্ভুক্তি কীভাবে কাজ করা উচিত তা নির্ধারণ করার জন্য এটি একটি দীর্ঘ প্রসারিত হতে পারে
অ্যান্টন স্ট্রাগনফ

@ অ্যান্টন স্ট্রাগনফ এই বিষয়টি আমার নজরে আনার জন্য আপনাকে ধন্যবাদ। আপনি কি আমাকে আরএফসির এমন জায়গায় নির্দেশ করতে পারবেন? এটিতে "রীতিনীতি" শব্দের কোনও উল্লেখ নেই। সূত্র yaml.org/spec/1.2/spec.html
oligofren থেকে

1
@ অলিগফ্রেন আপনাকে স্বাগতম "অ্যাপ্লিকেশন-নির্দিষ্ট" ট্যাগগুলি সন্ধান করুন
আন্তন স্ট্রোগনফ

8

@ জোশ_বোডের উত্তরটি প্রসারিত করার জন্য, এখানে আমার নিজস্ব পাইওয়ামএল সমাধান রয়েছে, যার একটি স্ব-অন্তর্ভুক্ত সাবক্লাস হওয়ার সুবিধা রয়েছে yaml.Loader। এটি কোনও মডিউল-স্তরের গ্লোবালগুলির উপর নির্ভর করে না, বা yamlমডিউলটির বৈশ্বিক অবস্থা সংশোধন করার উপর নির্ভর করে না ।

import yaml, os

class IncludeLoader(yaml.Loader):                                                 
    """                                                                           
    yaml.Loader subclass handles "!include path/to/foo.yml" directives in config  
    files.  When constructed with a file object, the root path for includes       
    defaults to the directory containing the file, otherwise to the current       
    working directory. In either case, the root path can be overridden by the     
    `root` keyword argument.                                                      

    When an included file F contain its own !include directive, the path is       
    relative to F's location.                                                     

    Example:                                                                      
        YAML file /home/frodo/one-ring.yml:                                       
            ---                                                                   
            Name: The One Ring                                                    
            Specials:                                                             
                - resize-to-wearer                                                
            Effects: 
                - !include path/to/invisibility.yml                            

        YAML file /home/frodo/path/to/invisibility.yml:                           
            ---                                                                   
            Name: invisibility                                                    
            Message: Suddenly you disappear!                                      

        Loading:                                                                  
            data = IncludeLoader(open('/home/frodo/one-ring.yml', 'r')).get_data()

        Result:                                                                   
            {'Effects': [{'Message': 'Suddenly you disappear!', 'Name':            
                'invisibility'}], 'Name': 'The One Ring', 'Specials':              
                ['resize-to-wearer']}                                             
    """                                                                           
    def __init__(self, *args, **kwargs):                                          
        super(IncludeLoader, self).__init__(*args, **kwargs)                      
        self.add_constructor('!include', self._include)                           
        if 'root' in kwargs:                                                      
            self.root = kwargs['root']                                            
        elif isinstance(self.stream, file):                                       
            self.root = os.path.dirname(self.stream.name)                         
        else:                                                                     
            self.root = os.path.curdir                                            

    def _include(self, loader, node):                                    
        oldRoot = self.root                                              
        filename = os.path.join(self.root, loader.construct_scalar(node))
        self.root = os.path.dirname(filename)                           
        data = yaml.load(open(filename, 'r'))                            
        self.root = oldRoot                                              
        return data                                                      

2
অবশেষে আমার উত্তরে ক্লাস-ভিত্তিক পদ্ধতির যোগ করার জন্য কাছাকাছি চলে এসেছিল, তবে আপনি আমাকে ঘুষি মারলেন :) দ্রষ্টব্য: আপনি যদি এর yaml.load(f, IncludeLoader)মধ্যে ব্যবহার করেন _includeতবে রুটটি প্রতিস্থাপন করা এড়াতে পারবেন। এছাড়াও, আপনি এটি না করা না থাকলে সমাধান অন্তর্ভুক্ত ডেটা নিয়মিত yaml.Loaderক্লাস ব্যবহার করার কারণে এক স্তরের বেশি কাজ করবে না ।
জোশ বোদে

আমি শব্দ মুছে ফেলুন ছিল rootএর kwargsনির্ধারণের পরে self.rootস্ট্রিং সঙ্গে কাজ এটি পেতে। আমি superকলটির উপরে যদি-অন্য ব্লকটি সরিয়েছি। হতে পারে অন্য কেউ আমার সন্ধানের বিষয়টি নিশ্চিত করতে পারেন বা স্ট্রিংস এবং rootপ্যারামিটার সহ ক্লাসটি কীভাবে ব্যবহার করবেন তা আমাকে দেখাতে পারে ।
ওল্টন

1
দুর্ভাগ্যবশত, এই যেমন রেফারেন্স সাথে কাজ করে না `` অন্তর্ভুক্ত: & অন্তর্ভুক্ত inner.yaml একত্রীকরণ অন্তর্ভুক্ত: <<: * অন্তর্ভুক্ত ``!
অ্যান্টনি

2

আমি আপনার রেফারেন্স জন্য কিছু উদাহরণ তৈরি।

import yaml

main_yaml = """
Package:
 - !include _shape_yaml    
 - !include _path_yaml
"""

_shape_yaml = """
# Define
Rectangle: &id_Rectangle
    name: Rectangle
    width: &Rectangle_width 20
    height: &Rectangle_height 10
    area: !product [*Rectangle_width, *Rectangle_height]

Circle: &id_Circle
    name: Circle
    radius: &Circle_radius 5
    area: !product [*Circle_radius, *Circle_radius, pi]

# Setting
Shape:
    property: *id_Rectangle
    color: red
"""

_path_yaml = """
# Define
Root: &BASE /path/src/

Paths: 
    a: &id_path_a !join [*BASE, a]
    b: &id_path_b !join [*BASE, b]

# Setting
Path:
    input_file: *id_path_a
"""


# define custom tag handler
def yaml_import(loader, node):
    other_yaml_file = loader.construct_scalar(node)
    return yaml.load(eval(other_yaml_file), Loader=yaml.SafeLoader)


def yaml_product(loader, node):
    import math
    list_data = loader.construct_sequence(node)
    result = 1
    pi = math.pi
    for val in list_data:
        result *= eval(val) if isinstance(val, str) else val
    return result


def yaml_join(loader, node):
    seq = loader.construct_sequence(node)
    return ''.join([str(i) for i in seq])


def yaml_ref(loader, node):
    ref = loader.construct_sequence(node)
    return ref[0]


def yaml_dict_ref(loader: yaml.loader.SafeLoader, node):
    dict_data, key, const_value = loader.construct_sequence(node)
    return dict_data[key] + str(const_value)


def main():
    # register the tag handler
    yaml.SafeLoader.add_constructor(tag='!include', constructor=yaml_import)
    yaml.SafeLoader.add_constructor(tag='!product', constructor=yaml_product)
    yaml.SafeLoader.add_constructor(tag='!join', constructor=yaml_join)
    yaml.SafeLoader.add_constructor(tag='!ref', constructor=yaml_ref)
    yaml.SafeLoader.add_constructor(tag='!dict_ref', constructor=yaml_dict_ref)

    config = yaml.load(main_yaml, Loader=yaml.SafeLoader)

    pk_shape, pk_path = config['Package']
    pk_shape, pk_path = pk_shape['Shape'], pk_path['Path']
    print(f"shape name: {pk_shape['property']['name']}")
    print(f"shape area: {pk_shape['property']['area']}")
    print(f"shape color: {pk_shape['color']}")

    print(f"input file: {pk_path['input_file']}")


if __name__ == '__main__':
    main()

আউটপুট

shape name: Rectangle
shape area: 200
shape color: red
input file: /path/src/a

আপডেট 2

এবং আপনি এটি একত্রিত করতে পারেন

# xxx.yaml
CREATE_FONT_PICTURE:
  PROJECTS:
    SUNG: &id_SUNG
      name: SUNG
      work_dir: SUNG
      output_dir: temp
      font_pixel: 24


  DEFINE: &id_define !ref [*id_SUNG]  # you can use config['CREATE_FONT_PICTURE']['DEFINE'][name, work_dir, ... font_pixel]
  AUTO_INIT:
    basename_suffix: !dict_ref [*id_define, name, !product [5, 3, 2]]  # SUNG30

# ↓ This is not correct.
# basename_suffix: !dict_ref [*id_define, name, !product [5, 3, 2]]  # It will build by Deep-level. id_define is Deep-level: 2. So you must put it after 2. otherwise, it can't refer to the correct value.

1

দুর্ভাগ্যক্রমে YAML এটি এর মান সরবরাহ করে না।

তবে আপনি যদি রুবি ব্যবহার করছেন, রুবি ওয়াইএএমএল লাইব্রেরিটি বাড়িয়ে আপনি যে কার্যকারিতাটি জিজ্ঞাসা করছেন তা সরবরাহ করার জন্য একটি রত্ন রয়েছে: https://github.com/entwanderer/yaml_extend


1

আমি মনে করি @ ম্যাক্সি-বি দ্বারা ব্যবহৃত সমাধানটি দুর্দান্ত দেখাচ্ছে। তবে নেস্টেড অন্তর্ভুক্তিতে এটি আমার পক্ষে সফল হয়নি। উদাহরণস্বরূপ যদি কনফিগার_আইএএমএল এ কনফিগার_আমল অন্তর্ভুক্ত থাকে যা কনফিগারেশন অন্তর্ভুক্ত করে yam আইএমএলে লোডারটি নিয়ে একটি সমস্যা ছিল। যাইহোক, আপনি যদি নতুন লোডার শ্রেণিটিকে লোডের উপরে কেবল নিজের দিকে নির্দেশ করেন তবে এটি কার্যকর হয়! বিশেষত, আমরা যদি পুরানো _সামান্য ফাংশনটিকে খুব সামান্য পরিবর্তিত সংস্করণ দিয়ে প্রতিস্থাপন করি:

def _include(self, loader, node):                                    
     oldRoot = self.root                                              
     filename = os.path.join(self.root, loader.construct_scalar(node))
     self.root = os.path.dirname(filename)                           
     data = yaml.load(open(filename, 'r'), loader = IncludeLoader)                            
     self.root = oldRoot                                              
     return data

প্রতিবিম্বিত হওয়ার পরে আমি অন্যান্য মন্তব্যের সাথে একমত হয়েছি, সাধারণভাবে ইয়ামলের জন্য নেস্টেড লোডিং উপযুক্ত নয় কারণ ইনপুট স্ট্রিম কোনও ফাইল নাও হতে পারে, তবে এটি খুব দরকারী!


1

ওয়াইএমএল স্ট্যান্ডার্ড এটি করার কোনও উপায় নির্দিষ্ট করে না । এবং এই সমস্যাটি নিজেকে ওয়াইএমএলে সীমাবদ্ধ করে না। জেএসএনের একই সীমাবদ্ধতা রয়েছে।

অনেকগুলি অ্যাপ্লিকেশন যা ওয়াইএমএল বা জেএসএন ভিত্তিক কনফিগারেশন ব্যবহার করে শেষ পর্যন্ত এই সমস্যাটিতে চলে। এবং যখন এটি হয়, তারা তাদের নিজস্ব সম্মেলন করে

যেমন swagger API সংজ্ঞাগুলির জন্য:

$ref: 'file.yml'

যেমন ডকার রচনা কনফিগারেশনের জন্য:

services:
  app:
    extends:
      file: docker-compose.base.yml

বিকল্প হিসাবে, আপনি যদি কোনও yML ফাইলের বিষয়বস্তুকে একাধিক ফাইলগুলিতে বিভক্ত করতে চান যেমন সামগ্রীর গাছ, আপনি নিজের ফোল্ডার-কাঠামো কনভেনশনটি সংজ্ঞায়িত করতে পারেন এবং একটি (বিদ্যমান) মার্জ স্ক্রিপ্ট ব্যবহার করতে পারেন।



0

স্ট্যান্ডার্ড YAML 1.2 এ বৈশিষ্ট্যটি স্থানীয়ভাবে অন্তর্ভুক্ত করে না। তবুও অনেক বাস্তবায়ন এটি করার জন্য কিছু এক্সটেনশন সরবরাহ করে।

আমি জাভা এবং snakeyaml:1.24(জাভা লাইব্রেরি ওয়াইএএমএল ফাইলগুলি পার্স করতে / নির্গমন করতে) এর মাধ্যমে এটি অর্জনের একটি উপায় উপস্থাপন করেছি যা নিম্নলিখিত লক্ষ্য অর্জনের জন্য একটি কাস্টম ওয়াইএএমএল ট্যাগ তৈরি করার সুযোগ দেয় (আপনি দেখতে পাবেন যে আমি এটি বিভিন্ন ওয়াইএএমএল ফাইলে সংজ্ঞায়িত টেস্ট স্যুট লোড করতে ব্যবহার করছি) এবং আমি এটিকে লক্ষ্য test:নোডের অন্তর্ভুক্তের তালিকা হিসাবে কাজ করেছি ):

# ... yaml prev stuff

tests: !include
  - '1.hello-test-suite.yaml'
  - '3.foo-test-suite.yaml'
  - '2.bar-test-suite.yaml'

# ... more yaml document

এখানে এক-শ্রেণীর জাভা যা !includeট্যাগ প্রক্রিয়াকরণের অনুমতি দেয় । ক্লাসপথ (ম্যাভেন রিসোর্স ডিরেক্টরি) থেকে ফাইলগুলি লোড করা হয়েছে:

/**
 * Custom YAML loader. It adds support to the custom !include tag which allows splitting a YAML file across several
 * files for a better organization of YAML tests.
 */
@Slf4j   // <-- This is a Lombok annotation to auto-generate logger
public class MyYamlLoader {

    private static final Constructor CUSTOM_CONSTRUCTOR = new MyYamlConstructor();

    private MyYamlLoader() {
    }

    /**
     * Parse the only YAML document in a stream and produce the Java Map. It provides support for the custom !include
     * YAML tag to split YAML contents across several files.
     */
    public static Map<String, Object> load(InputStream inputStream) {
        return new Yaml(CUSTOM_CONSTRUCTOR)
                .load(inputStream);
    }


    /**
     * Custom SnakeYAML constructor that registers custom tags.
     */
    private static class MyYamlConstructor extends Constructor {

        private static final String TAG_INCLUDE = "!include";

        MyYamlConstructor() {
            // Register custom tags
            yamlConstructors.put(new Tag(TAG_INCLUDE), new IncludeConstruct());
        }

        /**
         * The actual include tag construct.
         */
        private static class IncludeConstruct implements Construct {

            @Override
            public Object construct(Node node) {
                List<Node> inclusions = castToSequenceNode(node);
                return parseInclusions(inclusions);
            }

            @Override
            public void construct2ndStep(Node node, Object object) {
                // do nothing
            }

            private List<Node> castToSequenceNode(Node node) {
                try {
                    return ((SequenceNode) node).getValue();

                } catch (ClassCastException e) {
                    throw new IllegalArgumentException(String.format("The !import value must be a sequence node, but " +
                            "'%s' found.", node));
                }
            }

            private Object parseInclusions(List<Node> inclusions) {

                List<InputStream> inputStreams = inputStreams(inclusions);

                try (final SequenceInputStream sequencedInputStream =
                             new SequenceInputStream(Collections.enumeration(inputStreams))) {

                    return new Yaml(CUSTOM_CONSTRUCTOR)
                            .load(sequencedInputStream);

                } catch (IOException e) {
                    log.error("Error closing the stream.", e);
                    return null;
                }
            }

            private List<InputStream> inputStreams(List<Node> scalarNodes) {
                return scalarNodes.stream()
                        .map(this::inputStream)
                        .collect(toList());
            }

            private InputStream inputStream(Node scalarNode) {
                String filePath = castToScalarNode(scalarNode).getValue();
                final InputStream is = getClass().getClassLoader().getResourceAsStream(filePath);
                Assert.notNull(is, String.format("Resource file %s not found.", filePath));
                return is;
            }

            private ScalarNode castToScalarNode(Node scalarNode) {
                try {
                    return ((ScalarNode) scalarNode);

                } catch (ClassCastException e) {
                    throw new IllegalArgumentException(String.format("The value must be a scalar node, but '%s' found" +
                            ".", scalarNode));
                }
            }
        }

    }

}

0

ইগলু দিয়ে আপনি অন্যান্য ফাইলগুলি আমদানি করতে পারেন:

A.yaml

foo: !? $import('B.yaml')

B.yaml

bar: Hello
$ yglu A.yaml
foo:
  bar: Hello

হিসাবে $importএকটি ফাংশন, এছাড়াও আপনি আর্গুমেন্ট হিসাবে একটি অভিব্যক্তি প্রেরণ করতে পারেন:

  dep: !- b
  foo: !? $import($_.dep.toUpper() + '.yaml')

এটি উপরের মতো একই আউটপুট দেবে।

দাবি অস্বীকার: আমি ইগলু এর লেখক।


-1

সঙ্গে Symfony , yaml তার হ্যান্ডলিং পরোক্ষভাবে নীড় yaml ফাইলগুলিতে আপনি অনুমতি দেবে। কৌশলটি হ'ল parametersবিকল্পটি ব্যবহার করা । উদাহরণ:

common.yml

parameters:
    yaml_to_repeat:
        option: "value"
        foo:
            - "bar"
            - "baz"

config.yml

imports:
    - { resource: common.yml }
whatever:
    thing: "%yaml_to_repeat%"
    other_thing: "%yaml_to_repeat%"

ফলাফল যেমন হবে:

whatever:
    thing:
        option: "value"
        foo:
            - "bar"
            - "baz"
    other_thing:
        option: "value"
        foo:
            - "bar"
            - "baz"

-6

প্রশ্ন জিজ্ঞাসা করার সময় সম্ভবত এটি সমর্থন করা হয়নি তবে আপনি অন্য ওয়াইএএমএল ফাইলটিকে একটিতে আমদানি করতে পারেন:

imports: [/your_location_to_yaml_file/Util.area.yaml]

যদিও আমার কাছে কোনও অনলাইন রেফারেন্স নেই তবে এটি আমার জন্য কার্যকর।


4
এটি মোটেও কোনও কাজ করে না। এটি কী এর মান হিসাবে একক স্ট্রিং "/your_location_to_yaml_file/Util.area.yaml" সমন্বিত একটি সিকোয়েন্স সহ একটি ম্যাপিং তৈরি করে imports
অ্যান্থন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.