用PHP解析YAML前端问题

时间:2011-08-13 18:56:00

标签: php yaml

我想用PHP解析YAML Front Matter

---
title = A nice title goes here
tags = tag1 tag2 tag3
---
This is the content of this entry...
Line2
Line3

我知道它是关于某种类型的Ruby gem,但我想在PHP中使用它来创建一个用户友好的flatfile博客引擎。

我还有一个名为Phrozn的项目片段。也许为了帮助我尽可能地帮助解决问题,你们可以方便地看到它。

private function parse()
{
    if (isset($this->template, $this->frontMatter)) {
        return $this;
    }

    $source = $this->readSourceFile();

    $parts = preg_split('/[\n]*[-]{3}[\n]/', $source, 2);
    if (count($parts) === 2) {
        $this->frontMatter = Yaml::load($parts[0]);
        $this->template = trim($parts[1]);
    } else {
        $this->frontMatter = null;
        $this->template = trim($source);
    }

    return $this;
}

3 个答案:

答案 0 :(得分:5)

我认为你的问题是你试图将三个部分分成两个部分。如果将第三个参数放到preg_split,您将得到一个包含三个元素的数组。第一部分(由---分隔):

---
title = A nice title goes here
tags = tag1 tag2 tag3
---
This is the content of this entry...
Line2
Line3

是空的,第二个是YAML,第三个是内容。试试这个:

$parts = preg_split('/[\n]*[-]{3}[\n]/', $source, 3);

现场测试案例:http://ideone.com/LYLxZ

如果你想匹配Phrozn似乎在做什么,那么你的输入将是这样的:

title = A nice title goes here
tags = tag1 tag2 tag3
---
This is the content of this entry...
Line2
Line3

你的PHP就是这样:

$parts = preg_split('/[\n]*[-]{3}[\n]/', $source, 2);

此版本的实时测试用例:http://ideone.com/a9a6C

答案 1 :(得分:1)

我遇到了同样的问题,并对未经测试的正则表达式以及可用的罕见软件包感到非常不满。

我写了一个库(Composer,TDD,PSR-4)来处理它。该库还处理解析YAML Markdown: FrontYAML

可以覆盖YAML和Markdown解析器。默认情况下,使用Symfony YAML和Parsedown。

答案 2 :(得分:0)

我这样做了:

// $string contains the full file.

$split = preg_split("/[\n]*[-]{3}[\n]/", $string, 3, PREG_SPLIT_NO_EMPTY);
try {
  // Strip extra, non-indentation, whitespace from beginning of lines
  $i = 0; $yfm = "";
  while ($split[0][$i] == " ") {$i++;}
  foreach(preg_split("/((\r?\n)|(\r\n?))/", $split[0]) as $line){
    $yfm .= substr($line, $i) . "\n";
  }
  // Using symfony's YAML parser
  $data = sfYaml::load($yfm);
} catch(InvalidArgumentException $e) {
  // This is not YAML
}

它删除了可能会使解析器跳转的无关缩进,并将所有换行符(无论是Win(CRLF),Nix(LF)还是Mac(CR))转换为"\n"