PHP 中读取和写入 OPML 的库。

0.5.1 2023-03-10 16:00 UTC

This package is not auto-updated.

Last update: 2024-09-20 23:18:48 UTC


README

lib_opml 是一个用于在 PHP 中读取和写入 OPML 的库。

OPML 是一个旨在存储和交换大纲(即按层次关系排列的树结构)的标准。它主要用于在聚合器之间交换订阅列表。规范可在 opml.org 获取。

lib_opml 已在 PHP 7.2+ 上进行测试。它需要 DOMDocument 来运行。

它支持 OPML 的 1.0 和 2.0 版本,因为这些是唯一发布的版本。根据规范,版本 1.1 被视为版本 1.0。

它采用 MIT 许可证

安装

lib_opml 可在 Packagist 上找到,并建议使用 Composer 进行安装

$ composer require marienfressinaud/lib_opml

如果您不使用 Composer,您可以下载 ZIP 归档 并将 src/ 文件夹的内容复制到您的项目中。然后,手动加载文件

<?php
require 'path/to/lib_opml/LibOpml/Exception.php';
require 'path/to/lib_opml/LibOpml/LibOpml.php';
require 'path/to/lib_opml/functions.php';

用法

解析 OPML

假设您有一个名为 my_opml_file.xml 的 OPML 文件

<?xml version="1.0" encoding="UTF-8" ?>
<opml version="2.0">
    <head>
        <title>My OPML</title>
    </head>
    <body>
        <outline text="Newspapers">
            <outline text="El País" />
            <outline text="Le Monde" />
            <outline text="The Guardian" />
            <outline text="The New York Times" />
        </outline>
    </body>
</opml>

您可以使用以下方式加载它:

$opml_array = libopml_parse_file('my_opml_file.xml');

lib_opml 解析文件并返回一个数组

[
    'version' => '2.0',
    'namespaces' => [],
    'head' => [
        'title' => 'My OPML'
    ],
    'body' => [ // each entry of the body is an outline
        [
            'text' => 'Newspapers',
            '@outlines' => [ // sub-outlines are accessible with the @outlines key
                ['text' => 'El País'],
                ['text' => 'Le Monde'],
                ['text' => 'The Guardian'],
                ['text' => 'The New York Times']
            ]
        ]
    ]
]

由于它只是一个数组,因此它非常容易操作

foreach ($opml_array['body'] as $outline) {
    echo $outline['text'];
}

您还可以直接加载一个 OPML 字符串

$opml_string = '<opml>...</opml>';
$opml_array = libopml_parse_string($opml_string);

渲染 OPML

lib_opml 能够将数组渲染为 OPML 字符串。它检查数据是否有效且符合规范。

$opml_array = [
    'head' => [
        'title' => 'My OPML',
    ],
    'body' => [
        [
            'text' => 'Newspapers',
            '@outlines' => [
                ['text' => 'El País'],
                ['text' => 'Le Monde'],
                ['text' => 'The Guardian'],
                ['text' => 'The New York Times']
            ]
        ]
    ]
];

$opml_string = libopml_render($opml_array);

file_put_contents('my_opml_file.xml', $opml_string);

处理错误

如果由于任何原因(例如空 body,缺少 text 属性,错误的元素类型)渲染(或解析)失败,则会引发一个 \marienfressinaud\LibOpml\Exception

try {
    $opml_array = libopml_render([
        'body' => []
    ]);
} catch (\marienfressinaud\LibOpml\Exception $e) {
    echo $e->getMessage();
}

类样式

lib_opml 还可以使用类样式使用

use marienfressinaud\LibOpml;

$libopml = new LibOpml\LibOpml();

$opml_array = $libopml->parseFile($filename);
$opml_array = $libopml->parseString($opml_string);
$opml_string = $libopml->render($opml_array);

特殊元素和属性

根据规范,某些元素具有特殊含义,这意味着 lib_opml 可以将其解析为特定类型。在另一个方面,在渲染 OPML 字符串时,您必须使用正确的类型传递这些元素。

头部元素

  • dateCreated 被解析为 \DateTime
  • dateModified 被解析为 \DateTime
  • expansionState 被解析为一个整数数组;
  • vertScrollState 被解析为一个整数;
  • windowTop 被解析为一个整数;
  • windowLeft 被解析为一个整数;
  • windowBottom 被解析为一个整数;
  • windowRight 被解析为一个整数。

大纲属性

  • created 被解析为 \DateTime
  • category 被解析为一个字符串数组;
  • isComment 被解析为一个布尔值;
  • isBreakpoint 被解析为一个布尔值。

如果这些元素中的任何一个不是正确的类型,则会引发异常。

最后,还有一些基于大纲类型属性的额外检查

  • 如果 type="rss",则要求 xmlUrl 属性;
  • 如果 type="link",则要求 url 属性;
  • 如果 type="include",则要求 url 属性。

请注意,type 属性不区分大小写,始终被转换为小写。

命名空间

OPML 可以通过命名空间进行扩展

OPML 文件可能包含本页未描述的元素和属性,仅当这些元素在 W3C 规范中定义的命名空间中时才允许这样做。

在渲染 OPML 时,您可以包含一个 namespaces 键来指定命名空间

$opml_array = [
    'namespaces' => [
        'test' => 'https://example.com/test',
    ],
    'body' => [
        ['text' => 'My outline', 'test:path' => '/some/example/path'],
    ],
];

$opml_string = libopml_render($opml_array);
echo $opml_string;

这将输出

<?xml version="1.0" encoding="UTF-8"?>
<opml xmlns:test="https://example.com/test" version="2.0">
  <head/>
  <body>
    <outline text="My outline" test:path="/some/example/path"/>
  </body>
</opml>

严格性

您可以通过传递可选的 $strict 属性到函数中来告诉 lib_opml 在解析或渲染 OPML 时是更严格还是更宽松。当 strict 为 false 时,大多数规范要求被简单地忽略,lib_opml 将尽力解析(或生成)OPML。

默认情况下,解析不是严格的,因此您将能够读取大多数文件。如果要将解析设置为严格(例如验证文件),请将 true 传递给 libopml_parse_file()libopml_parse_string()

$opml_array = libopml_parse_file($filename, true);
$opml_array = libopml_parse_string($opml_string, true);

另一方面,默认情况下读取是严格的,因此您被鼓励生成有效的 OPML。如果您需要放宽严格性,请将 false 传递给 libopml_render()

$opml_string = libopml_render($opml_array, false);

请注意,当使用类形式时,在对象实例化期间传递 strict

use marienfressinaud\LibOpml;

// lib_opml will be strict for both parsing and rendering!
$libopml = new LibOpml\LibOpml(true);

$opml_array = $libopml->parseString($opml_string);
$opml_string = $libopml->render($opml_array);

示例和文档化源代码

请参阅 examples/ 文件夹以获取具体示例。

我们鼓励您阅读源代码以了解关于 lib_opml 的更多信息。因此,完整文档作为代码中的注释提供。

变更日志

请参阅 CHANGELOG.md

支持和稳定性

今天,lib_opml 覆盖了 OPML 规范的所有方面。由于规范在 15 年以上没有改变,预计库在未来的变化不会很大。因此,我计划在不久的将来发布 v1.0。我现在只等待对其最新版本进行更多测试(特别是在 FreshRSS 中,见 FreshRSS/FreshRSS#4403)。我还将等待对规范的解释(见 scripting/opml.org#3),但这不是硬性要求。

1.0 版本发布后,lib_opml 将被认为是“完成”的。这意味着我将不会添加新功能,也不会破坏现有代码。然而,我承诺继续支持库以修复安全问题、错误,或添加对新 PHP 版本的支持。

因此,您可以预期 lib_opml 是稳定的。

测试和linters

本部分是为 lib_opml 的开发者准备的。

要运行测试,您首先必须安装 Composer(见 官方文档)。然后,安装依赖项

$ make install

现在您应该有一个包含开发依赖项的 vendor/ 文件夹。

使用以下命令运行测试

$ make test

使用以下命令运行 linter

$ make lint
$ make lint-fix

贡献

请将错误报告和合并请求提交到 Framagit 仓库

没有太多的事情要做,但文档和示例可能可以改进。

合并请求需要您填写简短的清单,以节省我在审查您的更改时的时间。您还必须确保测试套件成功。