ArrayToXmlのインストール方法
composer require spatie/array-to-xml
サンプルのXML
簡単な例として以下のXMLを組み立てて行きます。
<?xml version="1.0" encoding="UTF-8"?>
<foods>
<vegetable>tomato</vegetable>
<fruits>apple</fruits>
<meat>beef</meat>
</foods>
サンプルコード
ArrayToXmlではconvert()メソッドに配列を渡すことでXMLを文字列で返します。
また、連想配列で各要素を定義していく為、全体像を把握しやすくなります。
convert()メソッドには引数が多い為、PHP8.0から追加された名前付き引数で記述していますが省略して大丈夫です。
use Spatie\ArrayToXml\ArrayToXml;
$elements = [
'vegetable' => 'tomato',
'fruits' => 'apple',
'meat' => 'beef'
];
ArrayToXml::convert(
array: $elements,
rootElement: 'foods',
replaceSpacesByUnderScoresInKeyNames: true,
xmlEncoding: 'UTF-8',
xmlVersion: '1.0',
domProperties: ['formatOutput' => true]
);
"""
<?xml version="1.0" encoding="UTF-8"?>\n
<foods>\n
<vegetable>tomato</vegetable>\n
<fruits>apple</fruits>\n
<meat>beef</meat>\n
</foods>\n
"""
ArrayToXml::convert()の引数
| データ型 | 仮引数名 | 内容 | |
|---|---|---|---|
| 第1引数 | array | $array | root以下の構成要素の配列 |
| 第2引数 | mixed | $rootElement | root要素に関する配列、またはroot要素名の文字列 |
| 第3引数 | bool | $replaceSpacesByUnderScoresInKeyNames | タグ名に空白がある場合、_に変更するかをtrue, falseで指定(省略可) |
| 第4引数 | string | $xmlEncoding | 生成されるXMLのエンコーディングを指定(省略可) |
| 第5引数 | string | $xmlVersion | 生成されるXMLのバージョンを指定(省略可) |
| 第6引数 | array | $domProperties | 内包されているDOMDocumentオブジェクトのプロパティを設定(省略可) |
| 第7引数 | bool | $xmlStandalone | 生成されるXMLのstandalone属性をture,falseで指定(省略可) |
| 第8引数 | bool | $addXmlDeclaration | XML宣言文を含めるかをture,falseで指定(省略可) |
| 第9引数 | array | $options | XML生成時の細かい挙動の設定(省略可) |
各仮引数の使用例
第1引数 $arrayについて
XMLのルート要素(サンプルでいうところの<foods></foods>)以下に入る要素を記述します。
シンプルな構造の場合と、複雑な構造の場合では記述方法が変わります。
シンプルな構造とは初めのサンプルコードで出した例です。
1. 各要素に属性がついている場合
<?xml version="1.0" encoding="UTF-8"?>
<foods>
<vegetable id="1">tomato</vegetable>
<fruits id="2">apple</fruits>
<meat id="3">beef</meat>
</foods>
この場合は、その要素に関する配列を作成して対応します。
_attributesに各属性名と値の連想配列を追加します。値は_valueで指定します。
$elements = [
'vegetable' => [
'_attributes' => ['id' => '1'],
'_value' => 'tomato'
],
'fruits' => [
'_attributes' => ['id' => '1'],
'_value' => 'apple'
],
'meat' => [
'_attributes' => ['id' => '1'],
'_value' => 'beef'
],
];
ArrayToXml::convert($elements, 'foods');
2. 同じタグ名が複数ある場合
<?xml version="1.0" encoding="UTF-8"?>
<foods>
<vegetable>tomato</vegetable>
<vegetable>carrot</vegetable>
<vegetable>onion</vegetable>
</foods>
配列にvegetable要素を3回定義すればいけそうに見えますが、PHPでは連想配列に同じキーを指定できません。
最終的には出力されるのは最後に定義しているonionだけになります。
vegetableキーに配列を渡すことで同じタグ名の要素を複数作成することが可能です。
$elements = [
'vegetable' => [
'tomato',
'carrot',
'onion'
]
];
ArrayToXml::convert($elements, 'foods');
または以下のようにキー名を__custom:タグ名:任意の文字列と定義することで対応可能です。
任意の文字列は重複しないように指定してください。文字列、数値で揃える必要や連番で揃える必要はありません。
$elements = [
'__custom:vegetable:1' => 'tomato',
'__custom:vegetable:2' => 'carrot',
'__custom:vegetable:3' => 'onion'
];
ArrayToXml::convert($elements, 'foods');
注意点として__custom:を使用する際、タグ名に:(コロン)を入れたい場合は:(コロン)の前に\\バックスラッシュを2個記述することでエスケープできます。
3. 入れ子構造の場合
例で出してきたサンプルでは全ての要素がルート要素直下でしたが、XMLが入れ子構造になっている場合もあります。
<?xml version="1.0" encoding="UTF-8"?>
<foods>
<vegetable>
<name>tomato</name>
<price>150</price>
</vegetable>
<fruits>
<name>apple</name>
<price>100</price>
</fruits>
<meat>
<name>beef</name>
<price>200</price>
</meat>
</foods>
このような場合は連想配列も入れ子構造にすることで対応可能です。
$elements = [
'vegetable' => [
'name' => 'tomato',
'price' => 150,
],
'fruits' => [
'name' => 'apple',
'price' => 100,
],
'meat' => [
'name' => 'beef',
'price' => 200
]
];
ArrayToXml::convert($elements, 'foods');
第2引数 $rootElementについて
第2引数ではroot要素に関する情報を渡します。
サンプルのXMLのようにroot要素がただ単に名前のみの場合は文字列で渡します。
サイトマップのようにroot要素に属性を持たせる場合などは配列を渡します。
<?xml version="1.0" encoding="UTF-8"?>
<foods country="US">
<vegetable>tomato</vegetable>
<fruits>apple</fruits>
<meat>beef</meat>
</foods>
root要素の名前は配列内のrootElementNameで指定し、属性は_attributesで指定します。
$elements = [
'vegetable' => 'tomato',
'fruits' => 'apple',
'meat' => 'beef'
];
$rootElement = [
'rootElementName' => 'foods',
'_attributes' => [
'country' => 'US',
],
];
ArrayToXml::convert($elements, $rootElement);
第3引数 $replaceSpacesByUnderScoresInKeyNamesについて
第3引数ではtrueにした場合、タグ名の空白を_に変換するかを指定します。
省略した場合はtrueになります。
ただし、タグ名に空白があり、falseを選択した場合、例外が発生します。
内包されているDOMDocumentのDOMExceptionがスローされます。
$elements = [
'red color fruits' => 'apple'
];
ArrayToXml::convert($elements, 'foods', false);
DOMException
Invalid Character Error
その為、trueを指定する以外選択肢はなく、明示的にtrueを指定するためだけの引数のような感じだと思います。
第4引数 $xmlEncodingについて
第4引数ですが、ここではエンコードを指定します。
省略可能ですが、省略した場合はエンコードの情報がないXMLを生成します。
UTF-8かShift_JISを使用することが多い印象です。
第5引数 $xmlVersionについて
第5引数ではXML宣言文内のバージョンの指定を指定します。
<!-- ↓ここの部分↓ -->
<?xml version="1.0" encoding="UTF-8"?>
省略可能で、省略した場合のバージョンは1.0になります。
存在しないXMLのバージョンを指定した場合でもエラーなどは特に起きません。
第6引数 $domPropertiesについて
第6引数では内包されているDOMDocumentの設定を配列で渡します。
基本的にはformatOutputで十分です。
formatOutputでは整形して出力するかをtrue,falseで指定します。
$domPropertiesを省略、またはformatOutputがfalseの場合
$elements = [
'fruits' => 'apple'
];
ArrayToXml::convert(
array: $elements,
rootElement: 'foods',
domProperties: [
'formatOutput' => false,
]
);
"""
<?xml version="1.0"?>
<foods><fruits>apple</fruits></foods>
"""
formatOutputがtrueの場合
インデント、改行などを加えて整形してくれます。
$elements = [
'fruits' => 'apple'
];
ArrayToXml::convert(
array: $elements,
rootElement: 'foods',
domProperties: [
'formatOutput' => true,
]
);
"""
<?xml version="1.0"?>
<foods>
<fruits>apple</fruits>
</foods>
"""
第7引数 $xmlStandaloneについて
第7引数ではXML宣言文にstandalone属性を追加できます。
trueの場合はstandalone="yes"になり
falseの場合はstandalone="no"になります。
<!-- ↓ここの部分↓ -->
<?xml version="1.0" standalone="yes"?>
第8引数 $addXmlDeclarationについて
第8引数ではXML宣言文を含めるかを指定します。
省略可能で、省略時はtrueになります。
falseを指定することでroot要素以下のみが出力されます。
第9引数 $optionsについて
第9引数はXML生成時の詳細な制御ができます。省略可能で省略時はconvertNullToXsiNilがfalseになります。
| キー | 内容 |
|---|---|
| convertNullToXsiNil | 値がnullの場合、 xsi:nil="true"にするかどうかを指定。また、root要素にxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"が追加されます。 |
| convertBoolToString | 値がboolの場合、PHPではtrueが1にfalseが0になるが、それをtrue,falseとして扱うかを指定。 |
どちらともtrueを指定した場合のサンプルです。
$elements = [
'profile' => null,
'is_active' => true,
];
ArrayToXml::convert(
array: $elements,
rootElement: 'user',
domProperties: ['formatOutput' => true],
options: [
'convertNullToXsiNil' => true,
'convertBoolToString' => true,
]
);
"""
<?xml version="1.0"?>
<user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<profile xsi:nil="true"></profile>
<is_active>true</is_active>
</user>
"""
所感
PHPでXMLを組み立てる方法を調べても、DOMDocumentやSimpleXMLElementはよく見るもののArrayToXmlについて言及している記事を見つけられなかったので書いてみました。
XMLを組み立てる際の参考になると幸いです。