XML Wrangler是一个简单的PHP库,旨在使阅读和写作XML变得容易。 XML Wrangler是考虑到开发人员经验的构建 - 即使使用复杂的名称空间,甚至大型XML文件,您也可以读取任何类型的XML文件。如果XML无效,它也会引发异常!
XML Wrangler是通过作曲家安装的。
composer require saloonphp/xml-wrangler
需要PHP 8.1+
可以通过将XML字符串或文件传递到XML读取器中,并使用众多方法之一来搜索和查找特定元素或值来完成读取XML。如果您愿意,您也可以将每个元素转换为易于穿越的数组。如果您需要在元素上访问属性,则可以使用Element
DTO,这是一个简单的类来访问内容和属性。 XML Wrangler提供了通过多个元素迭代的方法,而一次仅保留一个元素。
< breakfast_menu >
< food soldOut = " false " bestSeller = " true " >
< name >Belgian Waffles</ name >
< price >$5.95</ price >
< description >Two of our famous Belgian Waffles with plenty of real maple syrup</ description >
< calories >650</ calories >
</ food >
< food soldOut = " false " bestSeller = " false " >
< name >Strawberry Belgian Waffles</ name >
< price >$7.95</ price >
< description >Light Belgian waffles covered with strawberries and whipped cream</ description >
< calories >900</ calories >
</ food >
< food soldOut = " false " bestSeller = " true " >
< name >Berry-Berry Belgian Waffles</ name >
< price >$8.95</ price >
< description >Light Belgian waffles covered with an assortment of fresh berries and whipped cream</ description >
< calories >900</ calories >
</ food >
</ breakfast_menu >
<?php
use Saloon XmlWrangler XmlReader ;
$ reader = XmlReader :: fromString ( $ xml );
// Retrieve all values as one simple array
$ reader -> values (); // ['breakfast_menu' => [['name' => '...'], ['name' => '...'], ['name' => '...']]
// Use dot-notation to find a specific element
$ reader -> value ( ' food.0 ' )-> sole (); // ['name' => 'Belgian Waffles', 'price' => '$5.95', ...]
// Use the element method to get a simple Element DTO containing attributes and content
$ reader -> element ( ' food.0 ' )-> sole (); // Element::class
// Use XPath to query the XML
$ reader -> xpathValue ( ' //food[@bestSeller="true"]/name ' )-> get (); // ['Belgian Waffles', 'Berry-Berry Belgian Waffles']
// Use getAttributes() to get the attributes on the elements
$ reader -> element ( ' food.0 ' )-> sole ()-> getAttributes (); // ['soldOut' => false, 'bestSeller' => true]
// Use getContent() to get the contents of the elements
$ reader -> element ( ' food.0 ' )-> sole ()-> getContent (); // ['name' => 'Belgian Waffles', 'price' => '$5.95', ...]
编写XML就像定义PHP数组并使用键和值定义元素一样简单。当您需要定义具有更多特征(例如属性或名称空间)的元素时,您可以使用Element
DTO来定义更高级的元素。
<?php
use Saloon XmlWrangler Data Element ;
use Saloon XmlWrangler XmlWriter ;
$ writer = new XmlWriter ;
$ xml = $ writer -> write ( ' breakfast_menu ' , [
' food ' => [
[
' name ' => ' Belgian Waffles ' ,
' price ' => ' $5.95 ' ,
' description ' => ' Two of our famous Belgian Waffles with plenty of real maple syrup ' ,
' calories ' => ' 650 ' ,
],
[
' name ' => ' Strawberry Belgian Waffles ' ,
' price ' => ' $7.95 ' ,
' description ' => ' Light Belgian waffles covered with strawberries and whipped cream ' ,
' calories ' => ' 900 ' ,
],
// You can also use the Element class if you need to define elements with
// namespaces or with attributes.
Element :: make ([
' name ' => ' Berry-Berry Belgian Waffles ' ,
' price ' => ' $8.95 ' ,
' description ' => ' Light Belgian waffles covered with an assortment of fresh berries and whipped cream ' ,
' calories ' => ' 900 ' ,
])-> setAttributes ([ ' bestSeller ' => ' true ' ]),
],
]);
以上代码将创建以下XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< breakfast_menu >
< food >
< name >Belgian Waffles</ name >
< price >$5.95</ price >
< description >Two of our famous Belgian Waffles with plenty of real maple syrup</ description >
< calories >650</ calories >
</ food >
< food >
< name >Strawberry Belgian Waffles</ name >
< price >$7.95</ price >
< description >Light Belgian waffles covered with strawberries and whipped cream</ description >
< calories >900</ calories >
</ food >
< food bestSeller = " true " >
< name >Berry-Berry Belgian Waffles</ name >
< price >$8.95</ price >
< description >Light Belgian waffles covered with an assortment of fresh berries and whipped cream</ description >
< calories >900</ calories >
</ food >
</ breakfast_menu >
该文档的本节用于使用XML读取器。
XML读取器可以接受多种输入类型。您可以使用XML字符串,文件或提供资源。您还可以直接从PSR响应(例如来自Guzzle)或轿车响应中读取XML。
use Saloon XmlWrangler XmlReader ;
$ reader = XmlReader :: fromString ( ' <?xml version="1.0" encoding="utf-8"?><breakfast_menu>... ' );
$ reader = XmlReader :: fromFile ( ' path/to/file.xml ' );
$ reader = XmlReader :: fromStream ( fopen ( ' path/to/file.xml ' , ' rb ' );
$ reader = XmlReader :: fromPsrResponse ( $ response );
$ reader = XmlReader :: fromSaloonResponse ( $ response );
由于基础PHP XMLReader类的局限性引起的警告,
fromStream
,fromPsrResponse
和fromSaloon
方法将在您的计算机/服务器上创建一个临时文件,以便在破坏读取器时自动删除从中读取的文件。您将需要确保在计算机上具有足够的存储空间来使用此方法。
您可以使用elements
和values
方法将整个XML文档转换为数组。如果您需要一个值数组,请使用values
方法 - 但是,如果您需要在元素上访问属性,则elements
方法将返回Element
DTO的数组。
$ reader = XmlReader :: fromString (...);
$ elements = $ reader -> elements (); // Array of `Element::class` DTOs
$ values = $ reader -> values (); // Array of values.
请注意,如果您正在读取大型XML文件,则应改用
element
或value
方法。这些方法可以通过大型XML文件迭代,而不会用完存储器。
您可以使用value
方法来获取特定元素的值。您可以使用点通用来搜索子元素。您也可以使用整数来查找多个元素的特定位置。此方法以记忆有效的方式在整个XML主体上进行搜索。
此方法将返回一个LazyQuery
类,该类具有不同的方法来检索数据。
$ reader = XmlReader :: fromString ( '
<?xml version="1.0" encoding="utf-8"?>
<person>
<name>Sammyjo20</name>
<favourite-songs>
<song>Luke Combs - When It Rains It Pours</song>
<song>Sam Ryder - SPACE MAN</song>
<song>London Symfony Orchestra - Starfield Suite</song>
</favourite-songs>
</person>
' );
$ reader -> value ( ' person.name ' )-> sole () // ' Sammyjo20 '
$ reader -> value ( ' song ' )-> get (); // ['Luke Combs - When It Rains It Pours', 'Sam Ryder - SPACE MAN', ...]
$ reader -> value ( ' song.2 ' )-> sole (); // 'London Symfony Orchestra - Starfield Suite'
您可以使用element
方法搜索特定元素。此方法将提供包含值和属性的Element
类。您可以使用点通用来搜索子元素。您也可以使用整数来查找多个元素的特定位置。此方法以内存有效的方式搜索整个XML主体。
此方法将返回一个LazyQuery
类,该类具有不同的方法来检索数据。
$ reader = XmlReader :: fromString ( '
<?xml version="1.0" encoding="utf-8"?>
<person>
<name>Sammyjo20</name>
<favourite-songs>
<song>Luke Combs - When It Rains It Pours</song>
<song>Sam Ryder - SPACE MAN</song>
<song>London Symfony Orchestra - Starfield Suite</song>
</favourite-songs>
</person>
' );
$ reader -> element ( ' name ' )-> sole (); // Element('Sammyjo20')
$ reader -> element ( ' song ' )-> get (); // [Element('Luke Combs - When It Rains It Pours'), Element('Sam Ryder - SPACE MAN'), ...]
$ reader -> element ( ' song.2 ' )-> sole (); // Element('London Symfony Orchestra - Starfield Suite')
有时,当您不必担心命名空间和元素前缀时,遍历XML文档会更容易。如果您想删除它们,则可以在读取器上使用removeNamespaces()
方法。
$ reader = XmlReader :: fromString (...);
$ reader -> removeNamespaces ();
在搜索大文件时,您可以使用lazy
或collectLazy
方法,该方法将返回一个结果的生成器,一次仅保留一个项目。
$ names = $ reader -> element ( ' name ' )-> lazy ();
foreach ( $ names as $ name ) {
//
}
如果您使用的是Laravel,则可以使用collect
and collectLazy
方法,这些方法将将元素转换为Laravel Collection/Lazy Collection。如果您不使用Laravel,则可以通过作曲家安装illuminate/collections
软件包来添加此功能。
$ names = $ reader -> value ( ' name ' )-> collect ();
$ names = $ reader -> value ( ' name ' )-> collectLazy ();
有时,您可能需要搜索元素包含特定属性的特定元素或值。您可以通过为value
或element
方法提供第二个参数来做到这一点。这将搜索最后一个元素以获取属性,并在匹配的情况下返回。
$ reader = XmlReader :: fromString ( '
<?xml version="1.0" encoding="utf-8"?>
<person>
<name>Sammyjo20</name>
<favourite-songs>
<song>Luke Combs - When It Rains It Pours</song>
<song>Sam Ryder - SPACE MAN</song>
<song recent="true">London Symfony Orchestra - Starfield Suite</song>
</favourite-songs>
</person>
' );
$ reader -> element ( ' song ' , [ ' recent ' => ' true ' ])-> sole (); // Element('London Symfony Orchestra - Starfield Suite')
$ reader -> value ( ' song ' , [ ' recent ' => ' true ' ])-> sole (); // 'London Symfony Orchestra - Starfield Suite'
XPATH是搜索XML的绝佳方法。使用一个字符串,您可以搜索具有特定属性或索引的特定元素。如果您有兴趣学习XPATH,则可以单击此处以获取有用的作弊表。
您可以使用xpathValue
方法在XPath查询中找到特定元素的值。此方法将返回一个Query
类,该类别具有不同的方法来检索数据。
<?php
$ reader = XmlReader :: fromString (...);
$ reader -> xpathValue ( ' //person/favourite-songs/song[3] ' )-> sole (); // 'London Symfony Orchestra - Starfield Suite'
您可以使用xpathElement
方法找到具有XPath查询的特定元素。此方法将返回一个Query
类,该类别具有不同的方法来检索数据。
<?php
$ reader = XmlReader :: fromString (...);
$ reader -> xpathElement ( ' //person/favourite-songs/song[3] ' )-> sole (); // Element('London Symfony Orchestra - Starfield Suite')
由于XPATH的限制引起的警告- 上述与XPath查询的方法不安全,并且可能不适合大型XML文档。
您可能会发现自己的XML文档包含一个未固定的xmlns
属性 - 如下:
< container xmlns = " http://example.com/xml-wrangler/person " xmlns : xsi = " http://www.w3.org/2001/XMLSchema-instance " />
当这种情况发生时,XML Wrangler将自动删除这些未装置的名称空间以提高兼容性。如果您想保留这些命名空间,则可以使用setXpathNamespaceMap
映射每个未固定的XML名称空间。
$ reader = XmlReader :: fromString (...);
$ reader -> setXpathNamespaceMap ([
' root ' => ' http://example.com/xml-wrangler/person ' ,
]);
$ reader -> xpathValue ( ' //root:person/root:favourite-songs/root:song[3] ' )-> sole ();
该文档的本节用于使用XML作者。
读者最基本的用法是将字符串键用于元素值的元素名称和值。作者接受嵌套元素的无限嵌套数组。
use Saloon XmlWrangler XmlWriter ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [
' name ' => ' Sam ' ,
' twitter ' => ' @carre_sam ' ,
' facts ' => [
' favourite-song ' => ' Luke Combs - When It Rains It Pours '
],
]);
以上代码将转换为以下XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< root >
< name >Sam</ name >
< twitter >@carre_sam</ twitter >
< facts >
< favourite-song >Luke Combs - When It Rains It Pours</ favourite-song >
</ facts >
</ root >
编写XML时,您通常需要在元素上定义属性和名称空间。您可以使用XML数组中的Element
类添加具有属性或名称空间的元素。您可以将Element
类与其他数组和字符串值混合。
use Saloon XmlWrangler XmlWriter ;
use Saloon XmlWrangler Data Element ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [
' name ' => ' Sam ' ,
' twitter ' => Element :: make ( ' @carre_sam ' )-> addAttribute ( ' url ' , ' https://twitter.com/@carre_sam ' ),
' facts ' => [
' favourite-song ' => ' Luke Combs - When It Rains It Pours '
],
' soap:custom-namespace ' => Element :: make ()-> addNamespace ( ' soap ' , ' http://www.w3.org/2003/05/soap-envelope ' ),
]);
这将导致以下XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< root >
< name >Sam</ name >
< twitter url = " https://twitter.com/@carre_sam " >@carre_sam</ twitter >
< facts >
< favourite-song >Luke Combs - When It Rains It Pours</ favourite-song >
</ facts >
< soap : custom-namespace xmlns : soap = " http://www.w3.org/2003/05/soap-envelope " />
</ root >
您通常需要定义一系列元素。您可以通过简单地提供一个值或元素类来做到这一点。
use Saloon XmlWrangler XmlWriter ;
use Saloon XmlWrangler Data Element ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [
' name ' => ' Luke Combs ' ,
' songs ' => [
' song ' => [
' Fast Car ' ,
' The Kind Of Love We Make ' ,
' Beautiful Crazy ' ,
Element :: make ( ' She Got The Best Of Me ' )-> addAttribute ( ' hit ' , ' true ' ),
],
],
]);
这将导致以下XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< root >
< name >Luke Combs</ name >
< songs >
< song >Fast Car</ song >
< song >The Kind Of Love We Make</ song >
< song >Beautiful Crazy</ song >
< song hit = " true " >She Got The Best Of Me</ song >
</ songs >
</ root >
有时,您可能需要更改根元素的名称。这可以自定义为write
方法的第一个参数。
$ xml = XmlWriter :: make ()-> write ( ' custom-root ' , [...])
如果您想向根元素添加属性和名称空间,则可以在此处使用RootElement
类。
use Saloon XmlWrangler Data RootElement ;
$ rootElement = RootElement :: make ( ' root ' )-> addNamespace ( ' soap ' , ' http://www.w3.org/2003/05/soap-envelope ' );
$ xml = XmlWriter :: make ()-> write ( $ rootElement , [...])
如果需要添加CDATA标签,则可以使用CDATA
类。
use Saloon XmlWrangler Data CDATA ; use Saloon XmlWrangler XmlWriter ;
use Saloon XmlWrangler Data Element ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [
' name ' => ' Sam ' ,
' custom ' => CDATA :: make ( ' Here is some CDATA content! ' ),
]);
这将导致以下XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< root >
< name >Sam</ name >
< custom > <![CDATA[ Here is some CDATA content! ]]> </ custom >
</ root >
有时,您可能会有XML的一部分,您将在应用程序中的多个XML请求中重复使用。借助XML Wrangler,您可以创建“可组合”元素,在其中可以在类中定义XML内容,您可以在应用程序中重新使用该内容。扩展Element
类并使用受保护的静态compose
方法。
<?php
use Saloon XmlWrangler XmlWriter ;
use Saloon XmlWrangler Data Element ;
class BelgianWafflesElement extends Element
{
protected function compose (): void
{
$ this
-> setAttributes ([
' soldOut ' => ' false ' ,
' bestSeller ' => ' true ' ,
])
-> setContent ([
' name ' => ' Belgian Waffles ' ,
' price ' => ' $5.95 ' ,
' description ' => ' Two of our famous Belgian Waffles with plenty of real maple syrup ' ,
' calories ' => ' 650 ' ,
]);
}
}
$ writer = XmlWriter :: make ()-> write ( ' root ' , [
' food ' => new BelgianWafflesElement ,
]);
这将导致这样的XML:
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< breakfast_menu >
< food soldOut = " false " bestSeller = " true " >
< name >Belgian Waffles</ name >
< price >$5.95</ price >
< description >Two of our famous Belgian Waffles with plenty of real maple syrup</ description >
< calories >650</ calories >
</ food >
</ breakfast_menu >
默认的XML编码是utf-8
,XML的默认版本为1.0
,默认的独立版为null
(XML Parsers解释没有与false
相同的独立属性)。如果您想自定义此功能,则可以使用setXmlEncoding
, setXmlVersion
和setXmlStandalone
方法在作者上进行自定义。
use Saloon XmlWrangler XmlWriter ;
$ writer = new XmlWriter ();
$ writer -> setXmlEncoding ( ' ISO-8859-1 ' );
$ writer -> setXmlVersion ( ' 2.0 ' );
$ writer -> setXmlStandalone ( true );
// $writer->write(...);
哪些导致XML声明<?xml version="2.0" encoding="ISO-8859-1" standalone="yes"?>
。
您可以使用addProcessingInstruction
方法向XML添加自定义“处理指令”。
use Saloon XmlWrangler XmlWriter ;
$ writer = new XmlWriter ();
$ writer -> addProcessingInstruction ( ' xml-stylesheet ' , ' type="text/xsl" href="base.xsl" ' );
$ xml = $ writer -> write ( ' root ' , [ ' name ' => ' Sam ' ]);
这将导致以下XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
<? xml-stylesheet type = " text/xsl " href = " base.xsl " ?>
< root >
< name >Sam</ name >
</ root >
默认情况下,XML书面未缩小。您可以向write
方法提供第三个参数以缩小XML。
use Saloon XmlWrangler XmlWriter ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [...], minified: true );
XML Wrangler是一个简单的包装纸,围绕两个非常强大的图书馆,可以做很多腿部工作。两个图书馆都很棒,值得一颗星星!