nigelrel3 / xml-reader-reg
XMLReader高级接口
Requires (Dev)
- phpunit/phpunit: 8.5.2
- symplify/easy-coding-standard: ~7.2
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
匹配元素的正文内容。这可以被类型提示为string
、SimpleXMLElement
或DOMElement
。
在这个回调中,
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 文件。