{"id":13623935,"url":"https://github.com/romaricdrigon/MetaYaml","last_synced_at":"2025-04-15T20:32:46.716Z","repository":{"id":4459969,"uuid":"5598658","full_name":"romaricdrigon/MetaYaml","owner":"romaricdrigon","description":"A powerful schema validator!","archived":false,"fork":false,"pushed_at":"2019-03-16T01:38:37.000Z","size":300,"stargazers_count":103,"open_issues_count":8,"forks_count":21,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-19T05:04:30.727Z","etag":null,"topics":["json","schema","schema-validation","xml","yaml"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/romaricdrigon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-08-29T09:53:54.000Z","updated_at":"2025-02-16T04:30:38.000Z","dependencies_parsed_at":"2022-09-21T17:00:55.176Z","dependency_job_id":null,"html_url":"https://github.com/romaricdrigon/MetaYaml","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romaricdrigon%2FMetaYaml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romaricdrigon%2FMetaYaml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romaricdrigon%2FMetaYaml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romaricdrigon%2FMetaYaml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/romaricdrigon","download_url":"https://codeload.github.com/romaricdrigon/MetaYaml/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249148195,"owners_count":21220497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","schema","schema-validation","xml","yaml"],"created_at":"2024-08-01T21:01:37.105Z","updated_at":"2025-04-15T20:32:46.380Z","avatar_url":"https://github.com/romaricdrigon.png","language":"PHP","readme":"# MetaYaml\n\n[![Latest Stable Version](https://poser.pugx.org/romaricdrigon/metayaml/v/stable.svg)](https://packagist.org/packages/romaricdrigon/metayaml) \n[![Build Status](https://travis-ci.org/romaricdrigon/MetaYaml.png?branch=master)](https://travis-ci.org/romaricdrigon/MetaYaml)\n[![SensioLabsInsight](https://insight.sensiolabs.com/projects/b61e16d7-0756-42f1-8dff-32def155f608/mini.png)](https://insight.sensiolabs.com/projects/b61e16d7-0756-42f1-8dff-32def155f608)\n\nA `[put your file type here]` schema validator using `[put another file type here]` files.  \nAt the moment, file type can be Json, Yaml, or [XML](#notes-on-xml-support). It can generate a documentation about the schema, or a XSD file (experimental).\n\n_The name comes from the fact that it was initially made to implement a pseudo-schema for Yaml files._\n\n\u003e 1. [Installation](#installation)\n1. [Basic usage](#basic-usage)\n1. [How to write a schema](#how-to-write-a-schema)\n * [Introduction](#introduction)\n * [Schema structure](#schema-structure)\n * [Schema nodes](#schema-nodes)\n * [More information](#more-information)\n1. [Documentation generator](#documentation-generator)\n1. [Notes on XML support](#notes-on-xml-support)\n1. [XSD generator](#xsd-generator)\n1. [Test](#test)\n1. [Extending](#extending)\n1. [Thanks](#thanks)\n\n## Installation\n\nIt is a standalone component:\n\n* the core requires PHP \u003e= 5.3.3\n* to use the YamlLoader, you will need the Symfony component [Yaml](https://github.com/symfony/Yaml) (standalone component, does not require Symfony2)\n* to launch the tests, you'll need [atoum](https://github.com/mageekguy/atoum)\n\nTo install via [composer](http://getcomposer.org) just do `composer require romaricdrigon/metayaml`\n\n## Basic usage\n\nYou have to create a MetaYaml object, and then pass it both the schema and your data as multidimensional php arrays:\n```php\nuse RomaricDrigon\\MetaYaml\\MetaYaml;\n\n// create object, load schema from an array\n$schema = new MetaYaml($schema);\n\n/*\n    you can optionally validate the schema\n    it can take some time (up to a second for a few hundred lines)\n    so do it only once, and maybe only in development!\n*/\n$schema-\u003evalidateSchema(); // return true or throw an exception\n\n// you could also have done this at init\n$schema = new MetaYaml($schema, true); // will load AND validate the schema\n\n// finally, validate your data array according to the schema\n$schema-\u003evalidate($data); // return true or throw an exception\n```\n\nYou can use any of the provided loaders to obtain these arrays (yep, you can validate XML using a schema from an Yaml file!).\n\nSome loader examples:\n```php\nuse RomaricDrigon\\MetaYaml\\MetaYaml;\nuse RomaricDrigon\\MetaYaml\\Loader\\YamlLoader;\nuse RomaricDrigon\\MetaYaml\\Loader\\XmlLoader; // JsonLoader is already available\n\n// create one loader object\n$loader = new JsonLoader(); // Json (will use php json_decode)\n$loader = new YamlLoader(); // Yaml using Symfony Yaml component\n$loader = new XmlLoader(); // Xml (using php SimpleXml)\n\n// the usage is the same then\n$array = $loader-\u003eload('SOME STRING...');\n// or you can load from a file\n$array = $loader-\u003eloadFromFile('path/to/file');\n```\n\n## How to write a schema\n\n### Introduction\n\nA schema file will define the array structure (which elements are allowed, where), some attributes (required, can be empty...) and the possible values for these elements (or their type).\n\nHere's a simple example of a schema, using Yaml syntax:\n```yaml\nroot: # root is always required (note no prefix here)\n    _type: array # each element must always have a '_type'\n    _children: # array nodes have a '_children' node, defining their children\n        flowers:\n            _type: array\n            _required: true # optional, default false\n            _children:\n                rose:\n                    _required: true\n                    _type: text\n                violet:\n                    _type: text\n                # -\u003e only rose and violet are allowed children of flowers\n```\n\nAnd a valid Yaml file :\n```yaml\nflowers:\n    rose: \"a rose\"\n    violet: \"a violet flower\"\n```\n\nWe will continue with Yaml examples; if you're not familiar with the syntax, you may want to take a look at its [Wikipedia page](http://en.wikipedia.org/wiki/YAML).\nOf course the same structure is possible with Json or XML, because the core is the same. Take a look at examples in `test/data/` folder.\n\n### Schema structure\n\nA schema file must have a `root` node, which will describe the first-level content.\nYou can optionally define a `prefix`; by default it is `_` (`_type`, `_required`...).\n\nYou have to define a `partials` node if you want to use this feature (learn more about it below).\n\nA basic schema file:\n```yaml\nroot:\n    # here put the elements who will be in the file\n    # note that root can have any type: an array, a number, a prototype...\nprefix: my_ # so it's gonna be 'my_type', 'my_required', 'my_children'...\npartials:\n    block:\n        # here I define a partial called block\n```\n\n### Schema nodes\n\nEach node in the schema must have a `_type` attribute.\nHere I define a node called `paragraph` whose content is some text:\n```yaml\nparagraph:\n    _type: text\n```\n\nThose types are available:\n\n* `text`: scalar value\n* `number`: numeric value\n* `boolean`: boolean value\n* `pattern`: check if the value matches the regular expression provided in `_pattern`, which is a [PCRE regex](http://www.php.net/manual/en/reference.pcre.pattern.syntax.php)\n* `enum`: enumeration ; list accepted values in `_values` node\n* `array`: array; define children in a _children node; array's children must have determined named keys; any extra key will cause an error\n* `prototype`: define a repetition of items whose name/index is not important. You must give children's type in `_prototype` node.\n* `choice`: child node can be any of the nodes provided in `_choices`. Keys in `_choices` array are not important (as long as they are unique). In each choice, it's best to put the discriminating field in first.\n* `partial`: \"shortcut\" to a block described in `partials` root node. Provide partial name in `_partial`\n\nYou can specify additional attributes:\n\n* general attributes:\n * `_required`: this node must always be defined (by default false)\n * `_not_empty` for text, number and array nodes: they can't be empty (by default false). Respective empty values are `''`, `0` (as a string, an integer or a float), `array()`. To test for `null` values, use `_required` instead.\n * `_strict` with text, number, boolean and enum will enforce a strict type check (respectively, with a string, an integer or a float, a boolean, any of these values). Be careful when using these with a parser which may not be type-aware (such as the XML one; Yaml and json should be ok)\n * `_description`: full-text description, cf. [Documentation generator](#documentation-generator)\n* only for array nodes:\n * `_ignore_extra_keys`: the node can contain children whose keys are not listed in `_children`; they'll be ignored\n* only for prototype nodes:\n * `min_items`: the prototype node should contain at least 'min' elements\n * `max_items`: the opposite, the max number of elements in the prototype node (by default 200)\n\nHere's a comprehensive example:\n```yaml\nroot:\n    _type: array\n    _children:\n        SomeText:\n            _type: text\n            _not_empty: true # so !== ''\n        SomeEnum:\n            _type: enum\n            _values:\n                - windows\n                - mac\n                - linux\n        SomeNumber:\n            _type: number\n            _strict: true\n        SomeBool:\n            _type: boolean\n        SomePrototypeArray:\n            _type: prototype\n            _prototype:\n                _type: array\n                _children:\n                    SomeOtherText:\n                        _type: text\n                        _is_required: true # can't be null\n        SomeParagraph:\n            _type: partial\n            _partial: aBlock # cf 'partials' below\n        SomeChoice:\n            _type: choice\n            _choices:\n                1:\n                    _type: enum\n                    _values:\n                        - windows\n                        - linux\n                2:\n                    _type: number\n                # so our node must be either #1 or #2\n        SomeRegex:\n            _type: pattern\n            _pattern: /e/\npartials:\n    aBlock:\n        _type: array\n        _children:\n            Line1:\n                _type: text\n```\n\n### More information\n\nFor more examples, look inside `test/data` folder.\nIn each folder, you have an .yml file and its schema. There's also a XML example.\n\nIf you're curious about an advanced usage, you can check `data/MetaSchema.json`: schema files are validated using this schema (an yep, the schema validates successfully itself!)\n\n## Documentation generator ##\n\nEach node can have a `_description` attribute, containing some human-readable text.\nYou can retrieve the documentation about a node (its type, description, other attributes...) like this:\n```php\n// it's recommended to validate the schema before reading documentation\n$schema = new MetaYaml($schema, true);\n\n// get documentation about root node\n$schema-\u003egetDocumentationForNode();\n\n// get documentation about a child node 'test' in an array 'a_test' under root\n$schema-\u003egetDocumentationForNode(array('a_test', 'test'));\n\n// finally, if you want to unfold (follow) all partials, set second argument to true\n$schema-\u003egetDocumentationForNode(array('a_test', 'test'), true);\n// watch out there's no loop inside partials!\n```\n\nIt returns an associative array formatted like this:\n```php\narray(\n    'name' =\u003e 'test', // name of current node, root for first node\n    'node' =\u003e array(\n        '_type' =\u003e 'array',\n        '_children' =\u003e ... // and so on\n    ),\n    'prefix' =\u003e '_'\n)\n```\n\nIf the targeted node is inside a choice, the result will differ slightly:\n```php\narray(\n    'name' =\u003e 'test', // name of current node, from the choice key in the schema\n    'node' =\u003e array(\n        '_is_choice' =\u003e 'true', // important: so we know next keys are choices\n        0 =\u003e array(\n            '_type' =\u003e 'array' // and so on, for first choice\n        ),\n        1 =\u003e array(\n            '_type' =\u003e 'text' // and so on, for second choice\n        ),\n        // ...\n    ),\n    'prefix' =\u003e '_'\n)\n```\nThis behavior allow us to handle imbricated choices, without loosing data (you have an array level for each choice level, and you can check the flag `_is_choice`)\n\nIf you pass an invalid path (e.g. no node with the name you gave exist), it will throw an exception.\n\n## Notes on XML support\n\nIn XML, you can store a value in a node within a child element, or using an attribute.\nThis is not possible in an array; the only way is to use a child.\n\nThus, the following conventions are enforced by the XML loader:\n\n* elements AND attributes are stored as child, using element name and content, or attribute name and value, as respectively key and value\n* if a node has an attribute and a child node with the same name, the attribute will be overwritten\n* if a node has both attribute(s) and a text content, text content will be stored under key `_value`\n* multiple child node with the same name will be overwritten, only the last will be retained; except if they have a `_key` attribute, which will be used thus\n* namespaces are not supported\n* empty nodes are skipped\n\nLet's take an example:\n```xml\n\u003cfleurs\u003e\n    \u003croses couleur=\"rose\"\u003e\n        \u003copera\u003eune rose\u003c/opera\u003e\n        \u003csauvage\u003e\n            \u003cdes_bois\u003eune autre rose\u003c/des_bois\u003e\n            \u003cdes_sous_bois sauvage=\"oui\"\u003eencore\u003c/des_sous_bois\u003e\n        \u003c/sauvage\u003e\n    \u003c/roses\u003e\n    \u003ctulipe\u003eje vais disparaitre !\u003c/tulipe\u003e\n    \u003ctulipe\u003edeuxieme tulipe\u003c/tulipe\u003e\n    \u003cfleur couleur=\"violette\" sauvage=\"false\" _key=\"violette\"\u003eune violette\u003c/fleur\u003e\n\u003c/fleurs\u003e\n```\n\nwill give us this array:\n```php\narray('fleurs' =\u003e\n    'roses' =\u003e array(\n        'couleur' =\u003e 'rose',\n        'sauvage' =\u003e array(\n            'des_bois' =\u003e 'une autre rose',\n            'des_sous_bois' =\u003e array(\n                'sauvage' =\u003e 'oui',\n                '_value' =\u003e 'encore'\n            )\n        )\n    ),\n    'tulipe' =\u003e 'deuxieme tulipe',\n    'violette' =\u003e array(\n        'couleur' =\u003e 'violette',\n        'sauvage' =\u003e 'false',\n        '_value' =\u003e 'une violette'\n    )\n)\n```\n\n## XSD generator\n\n_**Please note this feature is still experimental!**_\n\nMetaYaml can try to generate a [XML Schema Definition](http://en.wikipedia.org/wiki/XML_Schema) from a MetaYaml schema.\nYou may want to use this file to pre-validate XML input, or to use in another context (client-side...).\nThe same conventions (cf. above) will be used.\n\nUsage example :\n```php\nuse RomaricDrigon\\MetaYaml\\MetaYaml\\XsdGenerator;\n\n// create a XsdGenerator object (requires Php XMLWriter from libxml, enabled by default)\n$generator = new XsdGenerator();\n\n// $schema is the source schema, php array\n// second parameter to soft-indent generated XML (default true)\n$my_xsd_string = $generator-\u003ebuild($schema, true);\n```\n\nA few limitations, some relative to XML Schema, apply:\n* `root` node must be an `array`\n* an element can't have a name beginning by a number\n* all first-level nodes will be mandatory (but they may be empty)\n* `choice` node are not supported\n* `pattern` may have a slightly different behavior due to implementations differences\n* `prototype` children nodes type will not be validated\n* `strict` mode does not exists\n* `ignore_extra_keys` attribute will cause all children nodes not to be validated\n\n## Test\n\nThe project is fully tested using [atoum](https://github.com/atoum/atoum).\nTo launch tests, just run in a shell `./bin/test -d test`\n\n## Extending\n\nYou may want to write your own loader, using anything else.  \nTake a look at any class in `Loader/ folder`, it's pretty easy: you have to implement the LoaderInterface, and may want to extend Loader class (so you don't have to write `loadFromFile()`).\n\n## Thanks\n\nThanks to [Riad Benguella](https://github.com/youknowriad) and [Julien Bianchi](https://github.com/jubianchi) for their help \u0026 advice.\n\n[Top](#metayaml)\n","funding_links":[],"categories":["过滤和验证","目录","Table of Contents","PHP","过滤和验证 Filtering and Validation","Filtering and Validation","过滤和验证( Filtering ang Validation )"],"sub_categories":["过滤和验证 Filtering and Validation","Filtering and Validation","Filtering, Sanitizing and Validation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromaricdrigon%2FMetaYaml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fromaricdrigon%2FMetaYaml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromaricdrigon%2FMetaYaml/lists"}