arc / xml
Ariadne 组件库:xml 编写器和解析器组件
Requires
- php: >=7.1
- arc/base: ~3.0
Requires (Dev)
- phpunit/phpunit: 9.*
README
PHP 的灵活组件库
Ariadne 组件库是 Ariadne 网络应用程序框架和内容管理系统的一个分支 [ http://www.ariadne-cms.org/ ]
arc/xml
此组件提供统一的 xml 解析器和编写器。编写器允许在代码中使用可读且始终正确的 xml,而无需使用模板。解析器是 DOMDocument 和 SimpleXML 的包装器。
解析器和编写器也可以处理 XML 的片段。解析器还确保输出与输入相同。当将节点转换为字符串时,\arc\xml 将返回包括标签在内的完整 xml 字符串。如果您不希望这样做,您始终可以访问 'nodeValue' 属性以获取原始 SimpleXMLElement。
最后,解析器还增加了使用基本 CSS 选择器在 XML 中查找元素的能力。
示例代码
use \arc\xml as x; $xmlString = x::preamble() .x::rss(['version'=>'2.0'], x::channel( x::title('Wikipedia'), x::link('http://www.wikipedia.org'), x::description('This feed notifies you of new articles on Wikipedia.') ) );
并解析它
$xml = \arc\xml::parse($xmlString); $title = $xml->channel->title->nodeValue; // SimpleXMLElement 'Wikipedia' $titleTag = $xml->channel->title; // <title>Wikipedia</title> echo $title;
安装
此库需要 PHP 7.1 或更高版本。它可以通过 Composer 以 arc/xml 的方式安装和自动加载。
composer require arc/xml
解析 XML
示例
以下示例我们将使用以下 XML
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel rdf:about="http://slashdot.org/"> <title>Slashdot</title> <link>http://slashdot.org/</link> <description>News for nerds, stuff that matters</description> <dc:language>en-us</dc:language> <dc:date>2016-01-30T20:38:08+00:00</dc:date> </channel> <item rdf:about="http://hardware.slashdot.org/story/1757209/"> <title>Drone Races To Be Broadcast To VR Headsets</title> <link>http://hardware.slashdot.org/story/1757209/</link> </item> <item rdf:about="http://it.slashdot.org/story/1720259/"> <title>FTDI Driver Breaks Hardware Again</title> <link>http://it.slashdot.org/story/1720259/</link> </item> </rdf:RDF>
获取标题
$xml = \arc\xml::parse( $xmlString ); $title = $xml->channel->title; echo $title;
结果
<title>Slashdot</title>
解析器默认返回完整的 XML 元素。如果您只想获取内容,则必须明确指出。
$title = $xml->channel->title->nodeValue; echo $title;
结果
Slashdot
与 SimpleXML 的默认设置不同,arc\xml 必须明确告诉使用 nodeValue
属性获取节点的值。
设置标题
$xml->channel->title = 'Update title';
如您所见,在此处不需要提及 nodeValue,名称 'title' 就足以选择正确的元素。在这里将标题转换为另一个标签整体是没有意义的。尽管如此,如果您愿意,仍然可以使用 nodeValue
。
获取属性
$about = $xml->channel['rdf:about'];
结果
http://slashdot.org/
正如预期的那样,即使其中包含命名空间也是如此。当您使用解析器之前未告知的命名空间时,它将简单地在该文档中查找并重用它。
由于属性不是 XML 节点,因此没有 nodeValue。属性始终作为字符串返回。
设置属性
$xml->channel['title-attribute'] = 'This is a title attribute';
如果之前不存在,则此操作添加 title-attribute
,如果存在则更新它。
删除属性
unset($xml->channel['title-attribute']);
搜索文档
$items = $xml->find('item'); echo implode($items);
结果
<item rdf:about="http://hardware.slashdot.org/story/1757209/"> <title>Drone Races To Be Broadcast To VR Headsets</title> <link>http://hardware.slashdot.org/story/1757209/</link> </item> <item rdf:about="http://it.slashdot.org/story/1720259/"> <title>FTDI Driver Breaks Hardware Again</title> <link>http://it.slashdot.org/story/1720259/</link> </item>
同样,您获得结果的完整 XML,它只是一个数组。(这里使用 implode
连接以清晰显示)。
find()
方法接受大多数 CSS2.0 选择器。目前您不能输入多个选择器,因此不能选择 'item, channel' 等。您可以使用 SimpleXML 的 xpath()
方法或运行多个查询。
使用命名空间搜索
$xml->registerNamespace('dublincore','http://purl.org/dc/elements/1.1/'); $date = current($xml->find('dublincore|date)); echo $date;
结果
<dc:date>2016-01-30T20:38:08+00:00</dc:date>
同样,默认情况下您获得完整的 XML。但除此之外,尽管您使用了文档中未知的命名空间别名(dublincore
),find()
也会为您返回 <dc:date>
元素。别名不同,但命名空间相同,这才是最重要的。
find()
方法始终返回一个数组,该数组可能为空。通过使用 current(),您可以得到找到的第一个元素,如果没有找到则返回 null。
支持的 CSS 选择器
以下 CSS 选择器受支持
tag1 tag2
这匹配tag2
,它是tag1
的后代。tag1 > tag2
这匹配tag2
,它是tag1
的直接子代。tag:first-child
这仅匹配tag
,如果它是第一个子代。tag1 + tag2
这仅匹配tag2
,如果它是紧跟在tag1
之后。tag1 ~ tag2
只有当存在前一个兄弟元素tag1
时,这才会匹配tag2
。tag[attr]
如果tag
具有属性attr
,则这会匹配tag
。tag[attr="foo"]
如果tag
的属性attr
的值在其值列表中为foo
,则这会匹配tag
。tag#id
这会匹配任何具有 idid
的tag
。#id
这会匹配任何具有 idid
的元素。ns|tag
这会匹配ns:tag
或更一般地,在由别名ns
指示的命名空间中的tag
。
SimpleXML
解析后的 XML 几乎与 SimpleXMLElement 完全相同,但存在上述异常。因此,您可以像 SimpleXMLElement 允许的那样访问属性。
$version = $xml['version']; $version = $xml->attributes('version');
您可以通过节点树进行遍历。
$title = $xml->channel->title;
SimpleXMLElement 中可用的任何方法或属性都包含在 \arc\xml 解析数据中。
DOMElement 方法
除了 SimpleXMLElement 方法外,您还可以调用 DOMElement 中可用的任何方法。
$version = $xml->getAttributes('version'); $title = $xml->getElementsByTagName('channel')[0] ->getElementsByTagName('title')[0];
解析片段
arc\xml 解析器接受部分 XML 内容。它不需要单个根元素。
$xmlString = <<< EOF <item> <title>An item</title> </item> <item> <title>Another item</title> </item> EOF; $xml = \arc\xml::parse($xmlString); echo $xml;
结果
<item> <title>An item</title> </item> <item> <title>Another item</title> </item>