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是一個簡單的包裝紙,圍繞兩個非常強大的圖書館,可以做很多腿部工作。兩個圖書館都很棒,值得一顆星星!