Mam więc dwa pliki YAML, „A” i „B”, i chcę, aby zawartość A została wstawiona do B, albo połączona z istniejącą strukturą danych, jak tablica, lub jako element podrzędny elementu, jak wartość dla określonego klucza skrótu.
Czy to w ogóle jest możliwe? W jaki sposób? Jeśli nie, jakieś wskazówki do odniesienia normatywnego?
yaml
transclusion
kch
źródło
źródło
Odpowiedzi:
Nie, YAML nie zawiera żadnych instrukcji „import” lub „include”.
źródło
Twoje pytanie nie wymaga rozwiązania w języku Python, ale oto jedno z nich używa PyYAML .
PyYAML umożliwia dołączanie niestandardowych konstruktorów (np.
!include
) Do modułu ładującego YAML. Dołączyłem katalog główny, który można ustawić, aby to rozwiązanie obsługiwało względne i bezwzględne odwołania do plików.Rozwiązanie klasy
Oto rozwiązanie oparte na klasach, które pozwala uniknąć globalnej zmiennej root mojej oryginalnej odpowiedzi.
Zobacz tę istotę podobnego, bardziej niezawodnego rozwiązania Python 3, które używa metaklasy do rejestrowania niestandardowego konstruktora.
Przykład:
foo.yaml
bar.yaml
Teraz pliki można załadować za pomocą:
źródło
include
funkcji można uprościć: `def include (loader, node):" "" Dołącz inny plik YAML. "" "Nazwa_pliku = loader.construct_scalar (węzeł) dane = yaml.load (otwórz (nazwa pliku))`a: bla
bar.yaml: `! Include foo.yaml b: blubb` Aby wynik był następujący:` {{a a: bla, 'b': blubb}Jeśli używasz wersji YAML Symfony , jest to możliwe, jak poniżej:
źródło
Uwzględnienia nie są bezpośrednio obsługiwane w YAML, o ile mi wiadomo, będziesz musiał sam zapewnić mechanizm, jednak generalnie jest to łatwe.
Używałem YAML jako języka konfiguracji w moich aplikacjach w Pythonie iw tym przypadku często definiuję taką konwencję:
Następnie w moim (pythonowym) kodzie:
Jedynym minusem jest to, że zmienne w dołączeniach zawsze nadpisują zmienne w main, i nie ma sposobu, aby zmienić ten priorytet, zmieniając miejsce, w którym instrukcja „include: pojawia się w pliku main.yml.
W nieco innej kwestii, YAML nie obsługuje włączania, ponieważ nie jest tak zaprojektowany, jak wyłączny znacznik oparty na plikach. Co oznaczałoby włączenie, jeśli otrzymałeś je w odpowiedzi na żądanie AJAX?
źródło
W przypadku użytkowników Pythona możesz wypróbować pyyaml-include .
zainstalować
Stosowanie
Rozważmy, że mamy takie pliki YAML :
1.yaml
treść:2.yaml
treść:Dołącz pliki według nazwy
Na najwyższym poziomie:
Jeśli
0.yaml
był:Dostaniemy:
W mapowaniu:
Jeśli
0.yaml
był:Dostaniemy:
Kolejno:
Jeśli
0.yaml
był:Dostaniemy:
Dołącz pliki według symboli wieloznacznych
Nazwa pliku może zawierać symbole wieloznaczne w stylu powłoki. Dane ładowane z pliku (ów) znalezionych przez symbole wieloznaczne zostaną ustawione w sekwencji.
Jeśli
0.yaml
był:Dostaniemy:
Aby włączyć
recursive
argument, napiszemy!include
tag w trybieMapping
lubSequence
:Sequence
trybie:Mapping
trybie:źródło
Rozwijając odpowiedź @ Josh_Bode, oto moje własne rozwiązanie PyYAML, które ma tę zaletę, że jest samodzielną podklasą
yaml.Loader
. Nie zależy to od globalizacji na poziomieyaml
modułu ani od modyfikacji globalnego stanu modułu.źródło
yaml.load(f, IncludeLoader)
w_include
sobie, możesz uniknąć konieczności wymiany roota. Ponadto, chyba że to zrobisz, rozwiązanie nie będzie działało głębiej niż na jednym poziomie, ponieważ zawarte dane korzystają ze zwykłejyaml.Loader
klasy.root
zkwargs
po ustawieniuself.root
je zdobyć pracę z tekstem. Przeniosłem blok if-else nadsuper
rozmowę. Może ktoś inny może potwierdzić moje odkrycie lub pokazać, jak używać klasy z ciągami znaków iroot
parametrem.Podaję kilka przykładów w celach informacyjnych.
wynik
Aktualizacja 2
i możesz to połączyć w ten sposób
źródło
Niestety YAML nie zapewnia tego w swoim standardzie.
Ale jeśli używasz Ruby, istnieje klejnot zapewniający funkcjonalność, o którą prosisz, rozszerzając bibliotekę Ruby YAML: https://github.com/entwanderer/yaml_extend
źródło
Myślę, że rozwiązanie zastosowane przez @ maxy-B wygląda świetnie. Jednak nie udało mi się to dzięki zagnieżdżonym inkluzjom. Na przykład jeśli config_1.yaml zawiera config_2.yaml, który obejmuje config_3.yaml, to wystąpił problem z modułem ładującym. Jeśli jednak po prostu wskażesz nową klasę modułu ładującego na ładunek, zadziała! W szczególności, jeśli zastąpimy starą funkcję _include bardzo nieznacznie zmodyfikowaną wersją:
Po zastanowieniu zgadzam się z innymi komentarzami, że ładowanie zagnieżdżone nie jest ogólnie odpowiednie dla yaml, ponieważ strumień wejściowy może nie być plikiem, ale jest bardzo przydatny!
źródło
Standard YML nie określa sposobu wykonania tej czynności. Ten problem nie ogranicza się do YML. JSON ma te same ograniczenia.
Wiele aplikacji korzystających z konfiguracji opartych na YML lub JSON może w końcu napotkać ten problem. A kiedy to się dzieje, tworzą własną konwencję .
np. dla definicji API swagger:
np. dla konfiguracji tworzenia dokera:
Alternatywnie, jeśli chcesz podzielić zawartość pliku yml na wiele plików, takich jak drzewo zawartości, możesz zdefiniować własną konwencję dotyczącą struktury folderów i użyć (istniejącego) skryptu scalania.
źródło
Może to Cię zainspiruje, spróbuj dostosować się do konwencji jbb:
https://docs.openstack.org/infra/jenkins-job-builder/definition.html#inclusion-tags
- job: name: test-job-include-raw-1 builders: - shell: !include-raw: include-raw001-hello-world.sh
źródło
Standardowy YAML 1.2 nie obejmuje natywnie tej funkcji. Niemniej jednak wiele implementacji zapewnia pewne rozszerzenie w tym celu.
Przedstawiam sposób osiągnięcia tego za pomocą Java i
snakeyaml:1.24
(biblioteki Java do parsowania / emitowania plików YAML), który pozwala na utworzenie niestandardowego znacznika YAML w celu osiągnięcia następującego celu (zobaczysz, że używam go do ładowania pakietów testowych zdefiniowanych w kilku plikach YAML i sprawiłem, że działa jako lista dołączeń dlatest:
węzła docelowego ):Oto jedna klasa Java, która umożliwia przetwarzanie
!include
znacznika. Pliki są ładowane ze ścieżki klasy (katalog zasobów Maven):źródło
Za pomocą Yglu możesz importować inne pliki takie jak to:
A.yaml
B.yaml
Jako
$import
funkcja możesz również przekazać wyrażenie jako argument:To dałoby taką samą wydajność jak powyżej.
Oświadczenie: Jestem autorem Yglu.
źródło
Dzięki Symfony jego obsługa yaml pozwoli pośrednio na zagnieżdżanie plików yaml. Sztuką jest skorzystanie z tej
parameters
opcji. na przykład:common.yml
config.yml
Wynik będzie taki sam jak:
źródło
Prawdopodobnie nie było obsługiwane po zadaniu pytania, ale możesz zaimportować inny plik YAML do jednego:
Chociaż nie mam żadnych odnośników online, ale to działa dla mnie.
źródło
imports
.