noccylabs / sdl
简单声明性语言 (SDL)
Requires
- psr/cache: ~1.0
- symfony/expression-language: ~2.4 || ~3.0 || ~4.0 || ~5.0
This package is auto-updated.
Last update: 2024-09-29 03:32:28 UTC
README
php-sdl 2.0
这是Simple Declarative Language (SDL)序列化语言在PHP中的实现。它与Simple Directmedia Layer无关。想象一下,它就像XML,但需要输入更少。
greetings {
greeting "Aloha" where="Hawaii"
greeting "Hej" where="Sweden"
}
这是php-sdl的2.0重写版本,因此有些功能可能还没有完全工作。如果您正在寻找一个工作但不太可扩展的解析器,请使用composer安装v1.x分支,composer require noccylabs/sdl:1.*
。当前存在的问题包括:
- 并非所有
LiteralType
都得到了实现。然而,现在每个类型都在自己的文件夹中,这很容易实现。 - 解析器仍然有问题。
- 并非所有单元测试都已创建。
- 可以生成注释,但不一定总是能解析。
- 数字类型可能会丢失精度。
用法
您现在实际上不应该使用这个。以下是关于哪些功能正在工作以及哪些功能尚未工作的简要总结。欢迎贡献和改进。
组件
功能
性能
解析器在读取时目前稍微有点慢,但这可能可以通过某种方式优化。无论如何,它为现有的序列化格式(XML、JSON和YAML)提供了一个整洁的替代方案。重要的是要记住,XML、JSON和YAML的解析器是以原生代码运行的,而SDL解析器是用PHP编写的。
话虽如此,应该注意的是,php-sdl最好用于不是过于频繁请求的配置文件(例如博客文章、路由表等),而是用于例如工作配置或即时文件(例如将博客文章导出到SDL以方便编辑和导入)。
缓存实现方式与1.x版本解析器中一样,即解析的标签的缓存文件放置在要解析的SDL文件相同的目录中,文件名相同,但以点(.)开头,以.cache结尾。例如,“foo.sdl”将缓存为“.foo.sdl.cache”。这种行为可能会在未来发生变化。
一些可能的改进和优化包括:
- 改进预解析优化例程。
- 使用正则表达式重写解析器(可能更快,也可能更慢)
示例
生成标签树
生成很简单。使用createRoot()
获取一个新的根标签,并开始添加您的子标签。您可以像从Symfony2中熟悉的那样使用相同的流式编程,其中所有setX()
方法都返回当前标签,调用end()
返回父节点。createChild()
可用于创建标签,将其添加为当前节点的子标签,并返回新创建的子标签。
use Sdl\SdlTag;
$tag = SdlTag::createRoot()
->createChild("people")
->createChild("person")
->setValue("John Doe")
->setAttribute("sex","male")
->end()
->end();
echo $tag->encode();
值和属性可以从PHP值分配,也可以通过任何LiteralType
后裔直接分配。
use Sdl\SdlTag;
use Sdl\LiteralType\SdlBinary;
$tag = SdlTag::createRoot()
->createChild("image")
->setValue(new SdlBinary($file))
->setAttribute("type","image/jpeg")
->end();
请记住,使用新的根或非变量时的流式方法调用,确保您的end()
调用匹配,以确保在您使用流式方法调用时返回根元素。
use Sdl\SdlTag;
$tag = SdlTag::createRoot();
$tag->createChild("foo")->createChild("bar");
// $tag will still point to the root even though end() wasn't called.
$bad = SdlTag::createRoot()->createChild("foo")->createChild("bar");
// $bad will be pointing to "bar" here, not the root.
但是,如果您需要,您应该能够使用getParent()
回到根节点。
function root($tag) {
while(($parent = $tag->getParent())
$tag = $parent;
return $tag;
}
解析文件
要解析文件,请使用Sdl\Parser\SdlParser
类。它提供了一些不同的方法来解析内容,并返回Sdl\SdlTag
对象。
use Sdl\Parser\SdlParser;
// Parse a file
$tag = SdlParser::parseFile("basic.sdl");
// Parse a string
$tag = SdlParser::parseString($sdl_string);
将标签编码到SDL
标签使用 encode()
方法编码到 SDL 中。如果您需要将其写入文件,请使用 file_put_contents()
或其他适当的方法将 encode()
的输出写入文件。
use Sdl\SdlTag;
// Create a new root
$tag = SdlTag::createRoot();
// Add two children
$tag->addChild("foo")->setValuesFromArray([0, 1, 2 ]);
$tag->addChild("bar")->setValuesFromArray([2, 3, 4 ]);
// Output the final SDL
echo $tag->encode();
导航子节点
您可以使用 getAllChildren()
、getChildrenByTagName(..)
来导航树结构。
SdlSelector
将提供一种更方便的方法来使用逻辑表达式查询树。
use Sdl\Parser\SdlParser;
$tag = SdlTag::createRoot();
$tag->createChild("people")
->createChild("person")
->setValue("John Doe")
->setAttribute("sex","male");
$people = $tag->getChildrenByTagName("people")[0]->getAllChildren();
echo "Person name: ".$people[0]->getValue()."\n";
// Enumerate children
foreach($tag->getAllChildren() as $ctag) {
printf("Tag: %s\n", $ctag->getTagName());
}
查询
查询利用 Symfony 的 ExpressionLanguage 组件来允许执行复杂的查询。
use Sdl\Parser\SdlParser;
use Sdl\Selector\SdlSelector;
// Load the data
$tag = SdlParser::parseFile(__DIR__."/sdl/products.sdl");
// Create a new selector for the tag
$tag_sel = new SdlSelector($tag);
// Execute the query
$expr = "/productcatalog/product[tag.attr('itemno')=='101-NAIL']";
$item = $tag_sel->query($expr);
开发
您可以使用 phpunit 运行单元测试。
$ phpunit --bootstrap tests/bootstrap.php tests/src/
只需记住,首先使用 composer 创建自动加载器等。
$ composer dump-autoload
当贡献代码时,遵循其他地方的约定,并使用您的杰作发送一个 pull request。如果您太懒不想自己修复某个问题,或者更有可能正在世界其他地方忙于拯救世界,创建一个问题,让其他人来处理它。