skraeda / xmlary
XML操作工具集合
v1.4.0
2021-01-12 17:22 UTC
Requires
- php: >=7.2
Requires (Dev)
- mockery/mockery: ^1.3
- phpunit/phpunit: 8.5.11
- symfony/var-dumper: ^5.0
README
此包是PHP的XML工具集合。
写者示例
展示如何将数组转换为XML的例子。
使用 toString
获取XML主体字符串或使用 toDomDocument
获取PHP DOMDocument对象。
基本元素
use Skraeda\Xmlary\XmlWriter; $writer = new XmlWriter; $array = [ 'People' => [ // String value should become <Marie>Unknown</Marie> 'Marie' => 'Unknown', // Null value should become <Lao/> 'Lao' => null, // Boolean value should become <Peter>1</Peter> 'Peter' => true, // Nested value should become <John><Age>20</Age></John> 'John' => [ 'Age' => 20, ] ] ]; echo $writer->toString($array);
输出
<People> <Marie>Unknown</Marie> <Lao/> <Peter>1</Peter> <John> <Age>20</Age> </John> </People>
数组元素
$array = [ 'Root' => [ 'ArrayOfValues' => [ // Should create duplicate <Values> elements 'Values' => [ 'String1', 2, true, null ] ], 'ArrayOfNestedValues' => [ // Should create duplicate <Values> elements 'Values' => [ [ 'StringValue' => 'String1' ], [ 'BoolValue' => true ], [ 'NullValue' => null ], [ 'NumericValue' => 123 ], [ 'Nested' => [1, 2] ] ] ] ] ]; echo $writer->toString($array);
输出
<Root> <ArrayOfValues> <Values>String1</Values> <Values>2</Values> <Values>1</Values> <Values/> </ArrayOfValues> <ArrayOfNestedValues> <Values> <StringValue>String1</StringValue> </Values> <Values> <BoolValue>1</BoolValue> </Values> <Values> <NullValue/> </Values> <Values> <NumericValue>123</NumericValue> </Values> <Values> <Nested>1</Nested> <Nested>2</Nested> </Values> </ArrayOfNestedValues> </Root>
写者配置
本节描述了您可以自定义XmlWriter的一些方法。您可以通过接口配置XmlWriter,在生成前后配置内部的DOMDocument对象或添加关键词
以不同方式处理单个元素。
接口
您可以通过XmlWriter构造函数或setter方法设置自定义配置对象、验证器或值转换器。
示例
use Skraeda\Xmlary\Contracts\XmlValueConverterContract; /** * Custom value converter to change boolean values to true / false strings instead of 1 / 0 */ class CustomXmlValueConverter implements XmlValueConverterContract { public function convert($value) { if (is_bool($value)) { return $value ? 'true' : 'false'; } return $value; } } // Outputs <Root>false</Root> echo (new XmlWriter) ->setConverter(new CustomXmlValueConverter) ->toString(['Root' => false]);
中间件
您可以在创建DOMDocument之前或之后添加中间件。
示例
// Add namespaced attribute to root element. $writer->pushAfterMiddleware(function ($doc) { $namespace = $doc->createAttributeNS('http://example.com', 'example:attr'); $namespace->value = 'foo'; $doc->firstChild->appendChild($namespace); }); // Outputs <foo:Root xmlns:example="http://example.com" example:attr="foo">value</foo:Root> $writer->toString(['foo:Root' => 'value']);
关键词
通过关键词扩展XmlWriter,在元素级别添加一些自定义功能。
示例
use Skraeda\Xmlary\Contracts\XmlKeyword; class CDataKeyword implements XmlKeyword { public function handle(DOMDocument $doc, DOMNode $parent, $value): void { $parent->appendChild($doc->createCDATASection($value)); } } echo $writer->extend('cdata', new CDataKeyword)->toString([ 'Root' => [ 'Element' => [ '@cdata' => 'bar', ] ] ]);
输出
<Root><Element><![CDATA[bar]]></Element></Root>
引导
您可以使用写者的bootstrap方法使用默认关键词配置它。
关键词
attributes
: 设置元素属性value
: 设置元素值(如果使用同一节点中的其他关键词,则很有用)cdata
: 将值包裹在CDATA块中comment
: 将值包裹在注释块中handler
: 为节点块添加自定义函数处理器
示例
$writer = (new XmlWriter)->bootstrap(); $arr = [ 'Root' => [ '@attributes' => [ 'xmlns:example' => 'http://example.com', 'example:attr' => 'foo' ], 'Element' => [ '@attributes' => [ 'foo' => 'bar' ], '@value' => 'Value' ], 'CData' => [ '@cdata' => 'Wrapped', '@value' => 'NotWrapped' ], 'Comment' => [ '@value' => 'Value', '@comment' => 'Comment' ], 'Handler' => [ '@handler' => function (DOMDocument $doc, DOMNode $parent) { $parent->appendChild($doc->createElement('Name', 'Value')); } ] ] ]; echo $writer->toString($arr);
读取器示例
展示如何将XML转换为数组的例子。
示例1
$xml = <<<XML <Root> <Element id="1">Value</Element> </Root> XML; (new XmlReader)->parse($xml));
输出
[ 'Root' => [ 'Element' => [ '@attributes' => [ 'id' => '1' ], '@value' => Value ] ] ]
示例2
$xml = <<<XML <Order> <Items> <Item id="1"> <Price>2.00</Price> <Type>Drink</Type> <Supplier> <Organization> <OrganizationName /> </Organization> </Supplier> </Item> <Item id="3"> <Price><![CDATA[1.00]]></Price> <Type>Misc</Type> <Supplier /> </Item> </Items> </Order> XML;
输出
[ 'Order' => [ 'Items' => [ 'Item' => [ [ '@attributes' => [ 'id' => 1 ], 'Price' => [ '@value' => '2.00' ], 'Supplier' => [ 'Organization' => [ 'OrganizationName' => [ '@value' => null ] ] ] ], [ '@attributes' => [ 'id' => 3 ], 'Price' => [ '@value' => '1.00' ] 'Type' => [ '@value' => 'Misc' ], 'Supplier' => [ '@value' => null ] ] ] ] ] ]
示例3
您可以为节点提供配置映射,以进行一些基本更改到生成的数组。
use Skraeda\Xmlary\XmlReaderNodeConfiguration as Config; $xml = <<<XML <Root> <Element>1</Element> <Inner><Sheet><Data>2</Data></Sheet></Inner> </Root> XML; $reader = new XmlReader; $config = [ 'Root' => [ // Provide config to rename Root element '@config' => new Config('NewRoot'), 'Element' => [ // Provide config to ensure Element is always an array element and add custom value converter to cast to int and add +2 to the value. '@config' => new Config(null, true, function ($oldValue) { return ((int) $oldValue) + 2; }) ], 'Inner' => [ '@config' => new Config(null, false, function ($oldValue) use ($reader) { return $reader->parse(html_entity_decode($oldValue)); }, function (XmlReaderNode $node) { // Callback handler to execute when the ReaderNode is created.. }) ] ] ]; $reader->parse($xml, $config);
输出
[ 'NewRoot' => [ 'Element' => [ [ '@value' => 3 ] ], 'Inner' => [ '@value' => [ 'Sheet' => [ 'Data' => [ '@value' => '2' ] ] ] ] ] ]
如果您需要,可以创建自定义配置类以减少重复。
要么扩展读取器节点配置类,要么实现接口。
读取器配置
本节描述了您可以如何自定义XmlReader。
接口
您可以通过构造函数或setter方法设置自定义配置对象。
工具
XmlSerializable
您可以在模型上定义的接口,以便可以使用XmlWriter将其格式化为XML。
您需要在模型上定义xmlSerialize
,它应该返回一个类似于上述示例的数组。
XmlSerialize
您可以在模型上添加的特质,以使用反射提供默认的xmlSerialize
处理器。
XmlMessage
您可以扩展的抽象基类,以使用反射为对象提供默认的xmlSerialize
处理器。
示例
use Skraeda\Xmlary\XmlMessage; class MyMessage extends XmlMessage { public $Public = 'PublicValue'; protected $Protected = 'ProtectedValue'; private $Private = 'PrivateValue'; public $Array; public $Inner; public $Changer = 'WillBeChanged'; public $Attrs = null; public function __construct(?MyMessage $Inner = null) { $this->Array = ['Field' => 'Value']; $this->Inner = $Inner; } protected function ChangerMutator() { return 'ChangedValue'; } // Uses AttributeKeyword and ValueKeyword protected function AttrsAttributes() { return [ 'value' => 'AttributeValue' ]; } protected function AttrsTag() { return 'AttributeTag'; } protected function attributes() { return [ 'foo' => 'bar' ]; } } echo $writer->toString(new MyMessage(new MyMessage));
输出
<MyMessage foo="bar"> <Public>PublicValue</Public> <Protected>ProtectedValue</Protected> <Private>PrivateValue</Private> <Array> <Field>Value</Field> </Array> <Inner> <MyMessage foo="bar"> <Public>PublicValue</Public> <Protected>ProtectedValue</Protected> <Private>PrivateValue</Private> <Array> <Field>Value</Field> </Array> <Inner/> <Changer>ChangedValue</Changer> <AttributeTag name="AttributeValue"/> </MyMessage> </Inner> <Changer>ChangedValue</Changer> <AttributeTag name="AttributeValue"> </MyMessage>
开发
包含PHP7.2 CLI dockerfile,用于测试任何新功能。
开始
docker-compose up
测试
docker-compose exec app vendor/bin/phpunit