1

我想知道-解析以下内容的最有效方法是什么:

{{HEADER}}

Hello my name is {{NAME}}

{{#CONTENT}}
    This is the content ...

    {{#PERSONS}}

        <p>My name is {{NAME}}.</p>

    {{/PERSONS}}

{{/CONTENT}}

{{FOOTER}}

当然,这最终是为了成为一个模板系统,所以我的计划是创建一个哈希图来“覆盖”模板,就像这样

$hash = array(
    'HEADER' => 'This is a header',
    'NAME' => 'David',
    'CONTENT' => array('PERSONS' => array(array('NAME' => 'Heino'), array('NAME' => 'Sebastian')),
    'FOOTER' => 'This is the footer'
    );

值得注意的是,“部分”(以#开头的标签)可以重复多次,我认为这就是让我绊倒的原因......

此外,任何部分都可以包含任意数量的其他部分,以及常规标签......

所以..你是怎么做到的?

4

6 回答 6

1

是这样的预期输出:

这是一个标题

你好,我的名字是大卫

This is the content ...

My name is Heino.

My name is Sebastian.

这是页脚


您如何管理哈希映射中的嵌套数组与模板中可重复部分的关系?模板的实际行为应该是什么?如果为非节元素提供了一个数组,它会做什么?如果为一个部分元素提供了一个值,它是否会被视为只有一个元素的数组(我假设是这样)?

无论如何,关于模板的解析器(不管你最终对数据的映射做了什么)......我要做的是为每种类型的令牌创建一个类,包括一个用于非令牌内容的通用类. 这些将从具有可重写 Parse、Render 和 Map 方法的公共令牌基类继承。

绘制您的状态图并找出每个状态的入口和出口点,然后将其编码到令牌之间的调用结构中。最后,您希望生成描述模板的可枚举标记集合。

一旦您以抽象形式获得它,您可以遍历集合调用 Map 上的标记以将数据从 hashmap 分配给标记,然后调用 Render 将模板呈现为最终形式。

希望有帮助。

于 2008-10-17T18:42:27.560 回答
1

最有效的方法是将模板编译为 php 代码。并且只包括编译后的版本。

Smarty 模板引擎做了类似的事情。您还可以查看 smarty 源代码并检查它们如何解析标签。

于 2008-10-17T22:43:31.097 回答
0

您最好使用 XML 或 JSON 之类的现有解析器,这样您就不必编写自己的解析器,这样其他人就可以轻松地为您的解析器编写文档,而无需专门的工具。但是,如果您想编写自己的解析器,您可能需要考虑使用LexYacc

于 2008-10-17T18:22:47.567 回答
0

我会使用第三方解析器,因为我喜欢更聪明而不是更努力地工作,但如果你这样做是为了练习,或者你真的想构建自己的模板引擎(我假设在 PHP 中是因为标签),我将从审查设计模式开始,特别是复合设计模式

复合模式在 Java 框架中被大量使用,包括 XML 解析。

于 2008-10-17T18:42:04.970 回答
0

我会在 .php 单独的文件中使用这样的东西:

<?php echo $HEADER ?>

Hello my name is <?php echo $NAME?>

<div id="CONTENT">
    This is the content ...

    <?php foreach ($PERSONS as $PERSON) : ?>

        <p>My name is <?php echo $PERSON['NAME']?>.</p>

    <?php endforeach ?>

</div>

<?php echo $FOOTER ?>

只需将上述文件包含在填充引用变量的文件中即可。

信不信由你,PHP 已经提供了模板系统声称要实现的所有功能。无需在 PHP 之上添加另一层抽象(和复杂性)。

于 2008-10-17T19:43:44.847 回答
0

我为此使用PHP 的 DOM。我的模板语言只是带有 ID 和类属性的 HTML。但是,如果你想坚持你的计划,我会使用preg_replace_callback与一个匹配你的语法的模式和一个在你的哈希中找到适当替换的回调函数,在容器元素上递归地调用自己。

于 2008-10-17T20:08:11.333 回答