arc/xml

Ariadne 组件库:xml 编写器和解析器组件

3.0 2020-02-23 13:45 UTC

This package is auto-updated.

Last update: 2024-09-10 23:24:19 UTC


README

Scrutinizer Code Quality Code Coverage Latest Stable Version Total Downloads Latest Unstable Version License

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
    这会匹配任何具有 id idtag
  • #id
    这会匹配任何具有 id id 的元素。
  • 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>