nigelrel3/xml-reader-reg

XMLReader高级接口

0.3 2020-05-27 17:24 UTC

This package is auto-updated.

Last update: 2024-09-12 04:57:54 UTC


README

PHP的XMLReader扩展,包含简化的接口。

快速开始

可以使用以下方式安装XMLReaderReg:

composer require nigelrel3/xml-reader-reg

而不是必须使用样板代码来获取特定元素,XMLReaderReg允许您注册对某些元素的兴趣,同时附带一个回调。这有效地将其从拉解析器转换为推解析器。

require_once __DIR__ . '/../vendor/autoload.php';

$inputFile = __DIR__ ."/../tests/data/simpleTest1.xml";
$reader = new XMLReaderReg\XMLReaderReg();
$reader->open($inputFile);

$reader->process([
    // Find all person elements
    '(.*/person' => function (SimpleXMLElement $data, $path): void {
        echo "1) Value for ".$path." is ".PHP_EOL.
            $data->asXML().PHP_EOL;
    },
    // Find the /root/person2/firstname element in the document
    '/root/person2/firstname' => function (string $data): void {
        echo "3) Value for /root/person2/firstname is ". $data.PHP_EOL;
    }
    ]);

$reader->close();

主要新增的是process()方法,而不是循环遍历文档结构,process()将一个包含正则表达式和相关回调元素的数组传递给process()。当特定的XML元素与您感兴趣的图案匹配时,回调将被传递该元素的数据。

文档层次结构的编码方式

当文档加载时,代码将根据元素的嵌套构建一个简单的文档层次结构。所以...

<person>
    <firstname>John</firstname>
    <lastname>Doe</lastname>
</person>

将产生以下树...

/person
/person/firstname
/person/lastname

为了支持多个元素,这略有修改以跟踪元素的个数...

<root>
    <firstname>John</firstname>
    <firstname>Fred</firstname>
</root>

将产生以下树...

/root
/root/firstname
/root/firstname[1]

请注意,第一个实例没有后缀(因为它还不知道有更多相同名称的元素),当添加时它们从1开始。

数组元素在任何特定的嵌套级别上都会被记住,所以...

<root>
    <firstname>John</firstname>
    <lastname>Doe</lastname>
    <firstname>Fred</firstname>
</root>

将产生以下树...

/root
/root/firstname
/root/lastname
/root/firstname[1]

正则表达式匹配

匹配过程就像确定您想要的数据在文档中的位置一样简单。您可以使用正则表达式的能力来匹配上述层次结构中的内容,您可以根据需要尽可能地明确或模糊。

从快速开始示例代码...

/root/person2/firstname

直接匹配层次结构中的元素,而

.*/person(?:\[\d*\])?

将找到任何<person>元素,并允许在存在多个元素时使用可选后缀。

正则表达式中的捕获组也很有用,请注意,最后一个正则表达式实际上是(.*/person(?:\[\d*\])?)。捕获组将被传递给回调。

回调函数

基本的回调函数定义是

function (mixed $data[, mixed $path]): void {}

data

匹配元素的正文内容。这可以被类型提示为stringSimpleXMLElementDOMElement

在这个回调中,

function ( $data ) {}

由于没有对回调值进行类型提示,它将传递readInnerXml()的结果,它是一个包含XML元素内容的字符串。

有一些更具体的替代方案...

// same as above, just with a type hint
function ( string $data ) {}

// The element is passed as a SimpleXMLelement
function ( \SimpleXMLElement $data ) {}

// The element is passed as a DOMElement
function ( \DOMElement $data ) {}

最后两个允许您以更可访问的格式获取内容,如果您需要进行进一步处理。

对于DOMElement,相当于$reader->importNode($reader->expand(), true)

对于SimpleXMLElement,相当于simplexml_import_dom(importNode($reader->expand(), true))

path

正则表达式中的捕获组。

如果您没有使用捕获组,则可以省略$path参数。如果您使用了捕获组,则它将传递一个数组,该数组是preg_match()的返回值,该函数用于内部检查路径是否与正则表达式模式匹配。

选项

DOM文档所有者

public function setDocument ( DOMDocument $doc ): void;

当使用DOMDocument时,创建的节点所有者可能很重要。如果您想要控制这一点,请创建自己的DOMDocument实例并将其传递给此调用。任何随后生成的节点传递给回调都将属于该文档。

如果没有调用此函数,所有节点都将属于一个内部创建的文档。

命名空间使用 - 匹配

public function setUseNamespaces ( bool $useNamespaces ): void;

标志用于指示路径是否使用命名空间构建。默认情况下,此标志设置为 true,将使用文档中定义的命名空间。

<a:root xmlns:a="http://someurl.com">
    <a:person>
    ...

设置为 true 时,它将生成路径层次结构为

/a:root
/a:root/a:person

设置为 false 时,它将生成路径层次结构为

/root
/root/person

命名空间使用 - 输出

public function setOutputNamespaces ( bool $outputNamespace ) : void;

如果您不需要/想要输出中的命名空间,使用 false 调用此方法将删除输出中的所有命名空间。这包括节点定义和任何命名空间前缀。

由于这种处理将产生开销。

配置数组表示法

默认情况下,数组表示法是关闭的,这将使重复的元素呈现为

/root
/root/firstname
/root/firstname

这消除了在(例如)(.*/person(?:\[\d*\])?)中包含正则表达式以匹配可选数组索引的需要,只需使用 (.*/person) 来检索每个 <person> 元素。

在某些情况下,您可能不需要知道正在处理元素的具体实例,这允许您提取特定实例或简单地从路径中知道正在处理哪个实例。

public function setArrayNotation ( bool $arrayNotation ): void;

使用 false 调用此方法将在匹配完成后停止生成数组索引。因此,上面的路径将看起来像以下...

/root
/root/firstname
/root/firstname[1]

停止处理

public function flagToStop () : void;

在回调期间,您可能决定不需要处理更多内容,此方法将标志 process() 方法在下一个迭代时停止。

这可以这样做...

function (DOMElement $data, $path)
                    use ($reader): void {
    // process $data
    $reader->flagToStop();
}

示例

examples/XMLReaderBasic.php 包含关于如何使用 XMLReaderReg 的一组简要示例

测试

tests/XMLReaderRegTest.php 是 XMLReaderReg 的 PHPUnit 测试集。

请注意,testFetchLargeFullRead 读取一个 25MB 的 XML 文件,因此将花费一些时间来完成。

许可

请参阅 LICENSE 文件。