youknowriad / meta-yaml
使用 [Yaml|Xml|json] 架构文件验证 [Yaml|Xml|json]
Requires
- php: >=5.3.3
- symfony/yaml: 2.*
Requires (Dev)
- atoum/atoum: dev-master#c6ec75d4cf132728e80ec8ed1470b83cb53fc1c9
This package is not auto-updated.
Last update: 2024-09-14 13:18:06 UTC
README
一个使用 [在此处插入文件类型]
文件作为输入的 [在此处插入另一种文件类型]
架构验证器。
目前,支持的文件类型可以是 Json、Yaml,或 XML。它可以生成关于架构的文档,或 XSD 文件(实验性)。
该名称来源于它最初是为了实现 Yaml 文件的伪架构而制作的。
安装
这是一个独立组件
要安装所有这些包,您可以使用 composer:只需执行 composer --update
基本用法
您需要创建一个 MetaYaml 对象,然后将架构和您的数据(作为多维 php 数组)传递给它
use RomaricDrigon\MetaYaml\MetaYaml; // create object, load schema from an array $schema = new MetaYaml($schema); /* you can optionally validate the schema it can take some time (up to a second for a few hundred lines) so do it only once, and maybe only in development! */ $schema->validate_schema(); // return true or throw an exception // you could also have done this at init $schema = new MetaYaml($schema, true); // will load AND validate the schema // finally, validate your data array according to the schema $schema->validate($data); // return true or throw an exception
您可以使用提供的任何加载器来获取这些数组(是的,您可以使用来自 Yaml 文件的架构来验证 XML!)
一些加载器示例
use RomaricDrigon\MetaYaml\MetaYaml; use RomaricDrigon\MetaYaml\Loader\YamlLoader; use RomaricDrigon\MetaYaml\Loader\XmlLoader; // JsonLoader is already available // create one loader object $loader = new JsonLoader(); // Json (will use php json_decode) $loader = new YamlLoader(); // Yaml using Symfony Yaml component $loader = new XmlLoader(); // Xml (using php SimpleXml) // the usage is the same then $array = $loader->load('SOME STRING...'); // or you can load from a file $array = $loader->loadFromFile('path/to/file');
如何编写架构
简介
架构文件将定义数组结构(哪些元素是允许的,在哪里),一些属性(必需的,可以是空的...)以及这些元素的可能的值(或其类型)。
以下是一个使用 Yaml 语法架构的简单示例
root: # root is always required (note no prefix here) _type: array # each element must always have a '_type' _children: # array nodes have a '_children' node, defining their children flowers: _type: array _required: true # optional, default false _children: rose: _required: true _type: text violet: _type: text # -> only rose and violet are allowed children of flowers
以及一个有效的 Yaml 文件
flowers: rose: "a rose" violet: "a violet flower"
我们将继续使用 Yaml 示例;如果您不熟悉其语法,您可能想查看其 Wikipedia 页面。当然,同样的结构也可以用 Json 或 XML 实现,因为核心是相同的。请查看 test/data/
目录中的示例。
架构结构
架构文件必须有一个 root
节点,它将描述第一级内容。您可以可选地定义一个 prefix
;默认值为 _
(_type
,_required
...)。
如果您想使用此功能,必须定义一个 partials
节点(下面将详细介绍)。
一个基本的架构文件
root: # here put the elements who will be in the file # note that root can have any type: an array, a number, a prototype... prefix: my_ # so it's gonna be 'my_type', 'my_required', 'my_children'... partials: block: # here I define a partial called block
架构节点
架构中的每个节点都必须有一个 _type
属性。这里我定义了一个名为 paragraph
的节点,其内容是一些文本
paragraph: _type: text
以下类型是可用的
text
:标量值number
:数字值boolean
:布尔值pattern
:检查值是否与在_pattern
中提供的正则表达式匹配,其中_pattern
是一个 PCRE 正则表达式enum
:枚举;在_values
节点中列出接受的值array
:数组;在 _children 节点中定义子元素;数组的子元素必须具有确定的命名键;任何额外的键都将导致错误prototype
:定义一个不重要的名称/索引的物品重复。您必须在_prototype
节点中给出子节点的类型。choice
:子节点可以是_choices
中提供的任何节点。在_choices
数组中的键不重要(只要它们是唯一的)。在每个选择中,最好将区分字段放在第一位。partial
:“快捷方式”到在partials
根节点中描述的块。在_partial
中提供部分名称。
您可以指定其他属性
- 通用属性
_required
:此节点必须始终被定义(默认为false)_not_empty
适用于文本、数字和数组节点:它们不能为空(默认为false)。相应的空值是''
、0
(作为一个字符串、一个整数或一个浮点数)、array()
。要测试null
值,请使用_required
。_strict
与文本、数字、布尔值和枚举一起使用将强制执行严格的类型检查(分别与字符串、整数或浮点数、布尔值、这些值的任意一个)。当与可能不具有类型感知的解析器(如XML解析器)一起使用时请小心(Yaml和json应该没问题)_description
:全文描述,参见图文档生成器- 仅适用于数组节点
_ignore_extra_keys
:节点可以包含不在_children
中列出的子键;它们将被忽略- 仅适用于原型节点
min_items
:原型节点应包含至少'min'个元素max_items
:相反,原型节点中的元素最大数量(默认为200)
这是一个综合示例
root: _type: array _children: SomeText: _type: text _not_empty: true # so !== '' SomeEnum: _type: enum _values: - windows - mac - linux SomeNumber: _type: number _strict: true SomeBool: _type: boolean SomePrototypeArray: _type: prototype _prototype: _type: array _children: SomeOtherText: _type: text _is_required: true # can't be null SomeParagraph: _type: partial _partial: aBlock # cf 'partials' below SomeChoice: _type: choice _choices: 1: _type: enum _values: - windows - linux 2: _type: number # so our node must be either #1 or #2 SomeRegex: _type: pattern _pattern: /e/ partials: aBlock: _type: array _children: Line1: _type: text
更多信息
更多示例,请查看test/data
文件夹。在每个文件夹中,都有一个.yml文件及其模式。还有一个XML示例。
如果您对高级用法感兴趣,可以查看data/MetaSchema.json
:使用此模式(是的,该模式可以成功验证自身!)验证模式文件。
文档生成器
每个节点都可以有一个_description
属性,其中包含一些可读文本。您可以通过以下方式检索有关节点(其类型、描述、其他属性)的文档
// it's recommended to validate the schema before reading documentation $schema = new MetaYaml($schema, true); // get documentation about root node $schema->getDocumentationForNode(); // get documentation about a child node 'test' in an array 'a_test' under root $schema->getDocumentationForNode(array('a_test', 'test')); // finally, if you want to unfold (follow) all partials, set second argument to true $schema->getDocumentationForNode(array('a_test', 'test'), true); // watch out there's no loop inside partials!
它返回一个格式如下所示的关联数组
array( 'name' => 'test', // name of current node, root for first node 'node' => array( '_type' => 'array', '_children' => ... // and so on ), 'prefix' => '_' )
如果目标节点在choice中,则结果会有所不同
array( 'name' => 'test', // name of current node, from the choice key in the schema 'node' => array( '_is_choice' => 'true', // important: so we know next keys are choices 0 => array( '_type' => 'array' // and so on, for first choice ), 1 => array( '_type' => 'text' // and so on, for second choice ), // ... ), 'prefix' => '_' )
此行为允许我们处理嵌套的选择,而不会丢失数据(您有一个数组级别的每个选择级别,并且您可以使用_is_choice
标志进行检查)
如果您传递一个无效的路径(例如,没有您给出的名称的节点),它将抛出异常。
关于 XML 支持的说明
在XML中,您可以在子元素或使用属性中存储节点的值。在数组中不可能做到这一点;唯一的方法是使用子节点。
因此,XML加载器强制执行以下约定
- 元素和属性都存储为子节点,使用元素名称和内容或属性名称和值作为相应的键和值
- 如果节点有一个属性和一个具有相同名称的子节点,则属性将被覆盖
- 如果节点既有属性又有文本内容,则文本内容将存储在键
_value
下 - 具有相同名称的多个子节点将被覆盖,只保留最后一个;除非它们具有
_key
属性,然后使用它 - 不支持命名空间
- 空节点被忽略
让我们举一个例子
<fleurs> <roses couleur="rose"> <opera>une rose</opera> <sauvage> <des_bois>une autre rose</des_bois> <des_sous_bois sauvage="oui">encore</des_sous_bois> </sauvage> </roses> <tulipe>je vais disparaitre !</tulipe> <tulipe>deuxieme tulipe</tulipe> <fleur couleur="violette" sauvage="false" _key="violette">une violette</fleur> </fleurs>
将给我们这个数组
array('fleurs' => 'roses' => array( 'couleur' => 'rose', 'sauvage' => array( 'des_bois' => 'une autre rose', 'des_sous_bois' => array( 'sauvage' => 'oui', '_value' => 'encore' ) ) ), 'tulipe' => 'deuxieme tulipe', 'violette' => array( 'couleur' => 'violette', 'sauvage' => 'false', '_value' => 'une violette' ) )
XSD 生成器
请注意,此功能仍然是实验性的!
MetaYaml可以从MetaYaml模式生成一个XML模式定义。您可能希望使用此文件来预验证XML输入,或在其他上下文中使用(客户端...)。将使用相同的约定(参上)。
使用示例
use RomaricDrigon\MetaYaml\MetaYaml\XsdGenerator; // create a XsdGenerator object (requires Php XMLWriter from libxml, enabled by default) $generator = new XsdGenerator(); // $schema is the source schema, php array // second parameter to soft-indent generated XML (default true) $my_xsd_string = $generator->build($schema, true);
有一些限制,其中一些与XML Schema相关
root
节点必须是一个array
- 一个元素的名字不能以数字开头
- 所有第一级节点将是必需的(但它们可能为空)
choice
节点不受支持pattern
由于实现差异,可能会有略微不同的行为prototype
子节点类型将不会进行验证strict
模式不存在ignore_extra_keys
属性将导致所有子节点都不进行验证
测试
该项目已使用atoum进行全面测试。要运行测试,请在壳中运行./bin/test --test-all
扩展
您可能想编写自己的加载器,使用任何其他方法。
查看Loader/文件夹
中的任何类,它很简单:您必须实现LoaderInterface,并可能想扩展Loader类(这样您就不必编写loadFromFile()
)。
感谢
感谢Riad Benguella和Julien Bianchi的帮助和建议。