O XML Wrangler é uma biblioteca PHP simplista projetada para facilitar a leitura e a escrita do XML. O XML Wrangler foi construído com a experiência do desenvolvedor em mente - você pode ler qualquer tipo de arquivo XML, mesmo com namespaces complexos e até grandes arquivos XML. Ele também lançará exceções se o XML for inválido!
XML Wrangler é instalado via compositor.
composer require saloonphp/xml-wrangler
Requer Php 8.1+
A leitura do XML pode ser feita passando a sequência ou arquivo XML no leitor XML e usando um dos muitos métodos para pesquisar e encontrar um elemento ou valor específico. Você também pode converter todos os elementos em uma matriz facilmente percorrer, se preferir. Se você precisar acessar atributos em um elemento, poderá usar o Element DTO, que é uma classe simples para acessar o conteúdo e os atributos. O XML Wrangler fornece métodos para iterar através de vários elementos, mantendo apenas um elemento na memória por vez.
< 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', ...] Escrever XML é tão simples quanto definir uma matriz PHP e usar teclas e valores para definir elementos. Quando você precisa definir elementos com mais algumas características, como atributos ou namespaces, você pode usar o Element DTO para definir elementos mais avançados.
<?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 ' ]),
],
]);O código acima criará o seguinte 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 >Esta seção sobre a documentação é para usar o leitor XML.
O leitor XML pode aceitar uma variedade de tipos de entrada. Você pode usar uma sequência XML, arquivo ou fornecer um recurso. Você também pode ler o XML diretamente de uma resposta PSR (como do Guzzle) ou uma resposta de salão.
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 );Os avisos devido a limitações da classe PHP XMLReader subjacente, dos métodos
fromStream,fromPsrResponseefromSalooncriará um arquivo temporário em sua máquina/servidor para ler sobre o qual será removido automaticamente quando o leitor for destruído. Você precisará garantir que você tenha armazenamento suficiente em sua máquina para usar esse método.
Você pode usar os métodos de elements e values para converter todo o documento XML em uma matriz. Se você quiser uma matriz de valores, use o método values - mas se precisar acessar atributos nos elementos, o método elements retornará uma matriz de DTOs Element .
$ reader = XmlReader :: fromString (...);
$ elements = $ reader -> elements (); // Array of `Element::class` DTOs
$ values = $ reader -> values (); // Array of values.NOTA Se você estiver lendo um arquivo XML grande, use o
elementou os métodosvalue. Esses métodos podem iterar através de grandes arquivos XML sem ficar sem memória.
Você pode usar o método value para obter o valor de um elemento específico. Você pode usar a notação do Dot para procurar elementos filho. Você também pode usar números inteiros para encontrar posições específicas de vários elementos. Este método pesquisa através de todo o corpo XML de maneira eficiente em termos de memória.
Este método retornará uma classe LazyQuery que possui métodos diferentes para recuperar os dados.
$ 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' Você pode usar o método element para pesquisar um elemento específico. Este método fornecerá uma classe Element que contém o valor e os atributos. Você pode usar a notação do Dot para procurar elementos filho. Você também pode usar números inteiros para encontrar posições específicas de vários elementos. Este método pesquisa através de todo o corpo XML de maneira eficiente em memória.
Este método retornará uma classe LazyQuery que possui métodos diferentes para recuperar os dados.
$ 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') Às vezes, é mais fácil atravessar um documento XML quando você não precisa se preocupar com espaços para nome e prefixos para elementos. Se você deseja removê -los, pode usar o método removeNamespaces() no leitor.
$ reader = XmlReader :: fromString (...);
$ reader -> removeNamespaces (); Ao pesquisar um arquivo grande, você pode usar os métodos lazy ou collectLazy que retornarão um gerador de resultados apenas mantendo um item na memória por vez.
$ names = $ reader -> element ( ' name ' )-> lazy ();
foreach ( $ names as $ name ) {
//
} Se você estiver usando o Laravel, pode usar os métodos collect e collectLazy que converterão os elementos em uma coleção Laravel/Lazy Collection. Se você não estiver usando o Laravel, pode instalar o pacote illuminate/collections via Composer para adicionar essa funcionalidade.
$ names = $ reader -> value ( ' name ' )-> collect ();
$ names = $ reader -> value ( ' name ' )-> collectLazy (); Às vezes, você pode procurar um elemento ou valor específico em que o elemento contém um atributo específico. Você pode fazer isso fornecendo um segundo argumento para o método value ou element . Isso procurará o último elemento dos atributos e retornará se eles corresponderem.
$ 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 é uma maneira fantástica de pesquisar no XML. Com uma sequência, você pode procurar um elemento específico, com atributos ou índices específicos. Se você estiver interessado em aprender XPath, clique aqui para uma folha de truques útil.
Você pode usar o método xpathValue para encontrar o valor de um elemento específico com uma consulta XPath. Este método retornará uma classe Query que possui métodos diferentes para recuperar os dados.
<?php
$ reader = XmlReader :: fromString (...);
$ reader -> xpathValue ( ' //person/favourite-songs/song[3] ' )-> sole (); // 'London Symfony Orchestra - Starfield Suite' Você pode usar o método xpathElement para encontrar um elemento específico com uma consulta XPath. Este método retornará uma classe Query que possui métodos diferentes para recuperar os dados.
<?php
$ reader = XmlReader :: fromString (...);
$ reader -> xpathElement ( ' //person/favourite-songs/song[3] ' )-> sole (); // Element('London Symfony Orchestra - Starfield Suite')Aviso devido a limitações com XPath - Os métodos acima usados para consultar o XPath não são seguros na memória e podem não ser adequados para documentos XML grandes.
Você pode se encontrar com um documento XML que contém um atributo xmlns não prefixado - como este:
< container xmlns = " http://example.com/xml-wrangler/person " xmlns : xsi = " http://www.w3.org/2001/XMLSchema-instance " /> Quando isso acontece, o XML Wrangler removerá automaticamente esses namespaces não prefixados para melhorar a compatibilidade. Se você deseja manter esses namespaces, pode usar setXpathNamespaceMap para mapear cada espaço de nome XML não prefixado.
$ reader = XmlReader :: fromString (...);
$ reader -> setXpathNamespaceMap ([
' root ' => ' http://example.com/xml-wrangler/person ' ,
]);
$ reader -> xpathValue ( ' //root:person/root:favourite-songs/root:song[3] ' )-> sole ();Esta seção sobre a documentação é para usar o escritor XML.
O uso mais básico do leitor é usar teclas de string para os nomes e valores dos elementos para os valores do elemento. O escritor aceita matrizes infinitamente aninhadas para elementos aninhados.
use Saloon XmlWrangler XmlWriter ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [
' name ' => ' Sam ' ,
' twitter ' => ' @carre_sam ' ,
' facts ' => [
' favourite-song ' => ' Luke Combs - When It Rains It Pours '
],
]);O código acima será convertido no seguinte 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 > Ao escrever XML, muitas vezes você precisará definir atributos e namespaces em seus elementos. Você pode usar a classe Element na matriz de XML para adicionar um elemento com um atributo ou espaço para nome. Você pode misturar a classe Element com outras matrizes e valores de string.
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 ' ),
]);Isso resultará no seguinte 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 >Muitas vezes, você precisará definir uma variedade de elementos. Você pode fazer isso simplesmente fornecendo uma variedade de valores ou classes de elemento.
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 ' ),
],
],
]);Isso resultará no seguinte 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 > Às vezes, pode ser necessário alterar o nome do elemento raiz. Isso pode ser personalizado como o primeiro argumento do método write .
$ xml = XmlWriter :: make ()-> write ( ' custom-root ' , [...]) Se você deseja adicionar atributos e namespaces ao elemento raiz, também pode usar uma classe 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 , [...]) Se você precisar adicionar uma tag CDATA, poderá usar a classe 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! ' ),
]);Isso resultará no seguinte XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< root >
< name >Sam</ name >
< custom > <![CDATA[ Here is some CDATA content! ]]> </ custom >
</ root > Às vezes, você pode fazer uma parte do XML que reutiliza em várias solicitações XML em seu aplicativo. Com o XML Wrangler, você pode criar elementos "composíveis", onde pode definir seu conteúdo XML em uma classe que você pode reutilizar em seu aplicativo. Estenda a classe Element e use o método compose estática protegida.
<?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 ,
]);Isso resultará em XML como este:
<? 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 > A codificação XML padrão é utf-8 , a versão padrão do XML é 1.0 e o padrão padrão é null (os analisadores XML interpretam nenhum atributo independente do false ). Se você deseja personalizar isso, pode com os métodos setXmlEncoding , setXmlVersion e setXmlStandalone no escritor.
use Saloon XmlWrangler XmlWriter ;
$ writer = new XmlWriter ();
$ writer -> setXmlEncoding ( ' ISO-8859-1 ' );
$ writer -> setXmlVersion ( ' 2.0 ' );
$ writer -> setXmlStandalone ( true );
// $writer->write(...); O que resulta na declaração xml <?xml version="2.0" encoding="ISO-8859-1" standalone="yes"?> .
Você pode adicionar uma "instrução de processamento" personalizada ao XML usando o método addProcessingInstruction .
use Saloon XmlWrangler XmlWriter ;
$ writer = new XmlWriter ();
$ writer -> addProcessingInstruction ( ' xml-stylesheet ' , ' type="text/xsl" href="base.xsl" ' );
$ xml = $ writer -> write ( ' root ' , [ ' name ' => ' Sam ' ]);Isso resultará no seguinte XML
<? xml version = " 1.0 " encoding = " utf-8 " ?>
<? xml-stylesheet type = " text/xsl " href = " base.xsl " ?>
< root >
< name >Sam</ name >
</ root > Por padrão, o XML escrito não é minificado. Você pode fornecer o terceiro argumento ao método write para minificar o XML.
use Saloon XmlWrangler XmlWriter ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [...], minified: true );O XML Wrangler é um invólucro simples em torno de duas bibliotecas realmente poderosas que fazem muito trabalho braçal. Ambas as bibliotecas são fantásticas e merecem uma estrela!