简单声明性语言 (SDL)

2.0.5 2020-07-29 23:51 UTC

This package is auto-updated.

Last update: 2024-09-29 03:32:28 UTC


README

Build Status

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。如果您太懒不想自己修复某个问题,或者更有可能正在世界其他地方忙于拯救世界,创建一个问题,让其他人来处理它。