XML Wrangler est une bibliothèque PHP simpliste conçue pour faciliter la lecture et l'écriture XML. XML Wrangler a été construit avec l'expérience du développeur à l'esprit - vous pouvez lire n'importe quel type de fichier XML, même avec des espaces de noms complexes et même de grands fichiers XML. Il lancera également des exceptions si le XML n'est pas valide!
XML Wrangler est installé via le compositeur.
composer require saloonphp/xml-wrangler
Nécessite PHP 8.1+
La lecture de XML peut être effectuée en passant la chaîne XML ou le fichier dans le lecteur XML et en utilisant l'une des nombreuses méthodes pour rechercher et trouver un élément ou une valeur spécifique. Vous pouvez également convertir chaque élément en un tableau facilement traversable si vous préférez. Si vous devez accéder aux attributs sur un élément, vous pouvez utiliser l' Element
DTO qui est une classe simple pour accéder au contenu et aux attributs. XML Wrangler fournit des méthodes pour itérer à travers plusieurs éléments tout en gardant un seul élément en mémoire à la fois.
< 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', ...]
L'écriture XML est aussi simple que de définir un tableau PHP et d'utiliser des clés et des valeurs pour définir des éléments. Lorsque vous devez définir des éléments avec quelques caractéristiques supplémentaires comme des attributs ou des espaces de noms, vous pouvez utiliser l' Element
DTO pour définir des éléments plus avancés.
<?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 ' ]),
],
]);
Le code ci-dessus créera le XML suivant
<? 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 >
Cette section sur la documentation consiste à utiliser le lecteur XML.
Le lecteur XML peut accepter une variété de types d'entrée. Vous pouvez utiliser une chaîne XML, un fichier ou fournir une ressource. Vous pouvez également lire le XML directement à partir d'une réponse PSR (comme de Guzzle) ou d'une réponse de salon.
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 );
Avertissement en raison des limites de la classe PHP XMLReader sous-jacente, des méthodes
fromStream
,fromPsrResponse
etfromSaloon
créeront un fichier temporaire sur votre machine / serveur à lire à partir de laquelle sera automatiquement supprimé lorsque le lecteur sera détruit. Vous devrez vous assurer d'avoir suffisamment de stockage sur votre machine pour utiliser cette méthode.
Vous pouvez utiliser les méthodes elements
et values
pour convertir l'ensemble du document XML en un tableau. Si vous souhaitez un tableau de valeurs, utilisez la méthode values
- mais si vous avez besoin d'accéder aux attributs sur les éléments, la méthode elements
renverra un tableau d' Element
DTOS.
$ reader = XmlReader :: fromString (...);
$ elements = $ reader -> elements (); // Array of `Element::class` DTOs
$ values = $ reader -> values (); // Array of values.
Remarque Si vous lisez un grand fichier XML, vous devez utiliser les méthodes
element
ouvalue
. Ces méthodes peuvent parcourir les grands fichiers XML sans manquer de mémoire.
Vous pouvez utiliser la méthode value
pour obtenir la valeur d'un élément spécifique. Vous pouvez utiliser la note de point pour rechercher des éléments enfants. Vous pouvez également utiliser des nombres entiers pour trouver des positions spécifiques de plusieurs éléments. Cette méthode recherche dans l'ensemble du corps XML de manière économe en mémoire.
Cette méthode renverra une classe LazyQuery
qui a différentes méthodes pour récupérer les données.
$ 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'
Vous pouvez utiliser la méthode element
pour rechercher un élément spécifique. Cette méthode fournira une classe Element
qui contient la valeur et les attributs. Vous pouvez utiliser la note de point pour rechercher des éléments enfants. Vous pouvez également utiliser des nombres entiers pour trouver des positions spécifiques de plusieurs éléments. Cette méthode recherche dans l'ensemble du corps XML de manière efficace par la mémoire.
Cette méthode renverra une classe LazyQuery
qui a différentes méthodes pour récupérer les données.
$ 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')
Parfois, il est plus facile de parcourir un document XML lorsque vous n'avez pas à vous soucier des espaces de noms et des préfixes aux éléments. Si vous souhaitez les supprimer, vous pouvez utiliser la méthode removeNamespaces()
sur le lecteur.
$ reader = XmlReader :: fromString (...);
$ reader -> removeNamespaces ();
Lorsque vous recherchez un grand fichier, vous pouvez utiliser les méthodes lazy
ou collectLazy
qui renvoient un générateur de résultats en gardant un élément en mémoire à la fois.
$ names = $ reader -> element ( ' name ' )-> lazy ();
foreach ( $ names as $ name ) {
//
}
Si vous utilisez Laravel, vous pouvez utiliser les méthodes collect
et collectLazy
qui convertiront les éléments en une collection Laravel / collection paresseuse. Si vous n'utilisez pas Laravel, vous pouvez installer le package illuminate/collections
via Composer pour ajouter cette fonctionnalité.
$ names = $ reader -> value ( ' name ' )-> collect ();
$ names = $ reader -> value ( ' name ' )-> collectLazy ();
Parfois, vous voudrez peut-être rechercher un élément ou une valeur spécifique où l'élément contient un attribut spécifique. Vous pouvez le faire en fournissant un deuxième argument à la méthode value
ou element
. Cela recherchera le dernier élément pour les attributs et reviendra s'ils correspondent.
$ 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 est un moyen fantastique de rechercher dans XML. Avec une chaîne, vous pouvez rechercher un élément spécifique, avec des attributs ou des index spécifiques. Si vous êtes intéressé à apprendre XPATH, vous pouvez cliquer ici pour une fiche utile.
Vous pouvez utiliser la méthode xpathValue
pour trouver la valeur d'un élément spécifique avec une requête XPath. Cette méthode renverra une classe Query
qui a différentes méthodes pour récupérer les données.
<?php
$ reader = XmlReader :: fromString (...);
$ reader -> xpathValue ( ' //person/favourite-songs/song[3] ' )-> sole (); // 'London Symfony Orchestra - Starfield Suite'
Vous pouvez utiliser la méthode xpathElement
pour trouver un élément spécifique avec une requête XPath. Cette méthode renverra une classe Query
qui a différentes méthodes pour récupérer les données.
<?php
$ reader = XmlReader :: fromString (...);
$ reader -> xpathElement ( ' //person/favourite-songs/song[3] ' )-> sole (); // Element('London Symfony Orchestra - Starfield Suite')
AVERTISSEMENT en raison des limites avec XPATH - Les méthodes ci-dessus utilisées pour interroger avec XPATH ne sont pas sûres de la mémoire et peuvent ne pas convenir aux grands documents XML.
Vous pourriez vous retrouver avec un document XML qui contient un attribut xmlns
non préfixé - comme ceci:
< container xmlns = " http://example.com/xml-wrangler/person " xmlns : xsi = " http://www.w3.org/2001/XMLSchema-instance " />
Lorsque cela se produit, XML Wrangler supprime automatiquement ces espaces de noms non préfixés pour améliorer la compatibilité. Si vous souhaitez conserver ces espaces de noms, vous pouvez utiliser setXpathNamespaceMap
pour cartographier chaque espace de noms XML non préfixé.
$ reader = XmlReader :: fromString (...);
$ reader -> setXpathNamespaceMap ([
' root ' => ' http://example.com/xml-wrangler/person ' ,
]);
$ reader -> xpathValue ( ' //root:person/root:favourite-songs/root:song[3] ' )-> sole ();
Cette section sur la documentation consiste à utiliser l'écrivain XML.
L'utilisation la plus élémentaire du lecteur consiste à utiliser des touches de chaîne pour les noms d'élément et les valeurs pour les valeurs de l'élément. L'écrivain accepte des tableaux infiniment imbriqués pour les éléments imbriqués.
use Saloon XmlWrangler XmlWriter ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [
' name ' => ' Sam ' ,
' twitter ' => ' @carre_sam ' ,
' facts ' => [
' favourite-song ' => ' Luke Combs - When It Rains It Pours '
],
]);
Le code ci-dessus sera converti en XML suivant
<? 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 >
Lorsque vous écrivez XML, vous devrez souvent définir des attributs et des espaces de noms sur vos éléments. Vous pouvez utiliser la classe Element
dans le tableau de XML pour ajouter un élément avec un attribut ou un espace de noms. Vous pouvez mélanger la classe Element
avec d'autres tableaux et valeurs de chaîne.
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 ' ),
]);
Cela entraînera le XML suivant
<? 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 >
Vous devrez souvent définir un éventail d'éléments. Vous pouvez le faire en fournissant simplement un tableau de valeurs ou de classes d'éléments.
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 ' ),
],
],
]);
Cela entraînera le XML suivant
<? 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 >
Parfois, vous devrez peut-être changer le nom de l'élément racine. Cela peut être personnalisé comme le premier argument de la méthode write
.
$ xml = XmlWriter :: make ()-> write ( ' custom-root ' , [...])
Si vous souhaitez ajouter des attributs et des espaces de noms à l'élément racine, vous pouvez également utiliser une 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 , [...])
Si vous devez ajouter une balise CDATA, vous pouvez utiliser la 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! ' ),
]);
Cela entraînera le XML suivant
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< root >
< name >Sam</ name >
< custom > <![CDATA[ Here is some CDATA content! ]]> </ custom >
</ root >
Parfois, vous pourriez avoir une partie de XML que vous réutiliserez sur plusieurs demandes XML dans votre application. Avec XML Wrangler, vous pouvez créer des éléments "composables" où vous pouvez définir votre contenu XML dans une classe que vous pouvez réutiliser sur votre application. Étendez la classe Element
et utilisez la méthode compose
statique protégée.
<?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 ,
]);
Cela se traduira par XML comme ceci:
<? 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 >
Le codage XML par défaut est utf-8
, la version par défaut de XML est 1.0
, et le standalone par défaut est null
(les analyseurs XML n'interprétent aucun attribut autonome que false
). Si vous souhaitez personnaliser cela, vous pouvez avec les méthodes setXmlEncoding
, setXmlVersion
et setXmlStandalone
sur l'écrivain.
use Saloon XmlWrangler XmlWriter ;
$ writer = new XmlWriter ();
$ writer -> setXmlEncoding ( ' ISO-8859-1 ' );
$ writer -> setXmlVersion ( ' 2.0 ' );
$ writer -> setXmlStandalone ( true );
// $writer->write(...);
Ce qui se traduit par la déclaration XML <?xml version="2.0" encoding="ISO-8859-1" standalone="yes"?>
.
Vous pouvez ajouter une "instruction de traitement" personnalisée au XML en utilisant la méthode addProcessingInstruction
.
use Saloon XmlWrangler XmlWriter ;
$ writer = new XmlWriter ();
$ writer -> addProcessingInstruction ( ' xml-stylesheet ' , ' type="text/xsl" href="base.xsl" ' );
$ xml = $ writer -> write ( ' root ' , [ ' name ' => ' Sam ' ]);
Cela entraînera le XML suivant
<? xml version = " 1.0 " encoding = " utf-8 " ?>
<? xml-stylesheet type = " text/xsl " href = " base.xsl " ?>
< root >
< name >Sam</ name >
</ root >
Par défaut, le XML écrit n'est pas minifié. Vous pouvez fournir le troisième argument à la méthode write
pour minimer le XML.
use Saloon XmlWrangler XmlWriter ;
$ xml = XmlWriter :: make ()-> write ( ' root ' , [...], minified: true );
XML Wrangler est un simple emballage autour de deux bibliothèques vraiment puissantes qui font beaucoup de jambes. Les deux bibliothèques sont fantastiques et méritent une étoile!