eliashaeussler/valinor-xml

cuyz/valinor 的 XML 源

1.0.0 2024-06-14 15:38 UTC

This package is auto-updated.

Last update: 2024-09-22 04:24:32 UTC


README

Code example

cuyz/valinor 的 XML 源

Coverage Maintainability CGL Tests Supported PHP Versions

这是一个 Composer 库,为流行的 cuyz/valinor 库提供额外的 XML 源。这使得将 XML 文件或内容轻松映射到 Valinor 支持的任何签名变得容易,例如对象或特殊数组形状。它利用 mtownsend/xml-to-array 库将原始 XML 转换为可重用的数组结构。

🔥 安装

Packagist Packagist Downloads

composer require eliashaeussler/valinor-xml

⚡ 使用方法

给定以下 XML

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <name>Dr. Zane Stroman</name>
    <address>
        <street>439 Karley Loaf</street>
        <postcode>17916</postcode>
        <city>West Judge</city>
        <country>Falkland Islands (Malvinas)</country>
    </address>
    <contact>
        <phone>827-986-5852</phone>
    </contact>
</person>

这些是生成的类

final readonly class Address
{
    public function __construct(
        public string $street,
        public string $postcode,
        public string $city,
        public string $country,
    ) {}
}

final readonly class Contact
{
    public function __construct(
        public string $phone,
    ) {}
}

final readonly class Person
{
    public function __construct(
        public string $name,
        public Address $address,
        public Contact $contact,
    ) {}
}

从 XML 字符串映射

要将给定的 XML 映射到 Person 类,您需要遵循以下三个步骤

  1. Valinor 文档 中所述创建一个新的映射器
  2. 使用提供的 XmlSource 解析和准备您的 XML
  3. 使用映射器将您的 XML 映射到 Person
use CuyZ\Valinor;
use EliasHaeussler\ValinorXml;

$mapper = (new Valinor\MapperBuilder())->mapper();
$source = ValinorXml\Mapper\Source\XmlSource::fromXmlString($xml);
$person = $mapper->map(Person::class, $source); // instanceof Person

生成的对象将类似于以下内容

object(Person)#180 (3) {
  ["name"]=>
  string(16) "Dr. Zane Stroman"
  ["address"]=>
  object(Address)#135 (4) {
    ["street"]=>
    string(15) "439 Karley Loaf"
    ["postcode"]=>
    string(5) "17916"
    ["city"]=>
    string(10) "West Judge"
    ["country"]=>
    string(27) "Falkland Islands (Malvinas)"
  }
  ["contact"]=>
  object(Contact)#205 (1) {
    ["phone"]=>
    string(12) "827-986-5852"
  }
}

从 XML 文件映射

XML 也可以从外部文件读取

use CuyZ\Valinor;
use EliasHaeussler\ValinorXml;

$mapper = (new Valinor\MapperBuilder())->mapper();
$source = ValinorXml\Mapper\Source\XmlSource::fromXmlFile($file);
$person = $mapper->map(Person::class, $source); // instanceof Person

将节点转换为集合

有时可能需要始终将 XML 节点转换为集合。给定以下 XML

<?xml version="1.0" encoding="UTF-8"?>
<community>
    <member><!-- ... --></member> <!-- NOTE: There's only one member -->
</community>

假设您想将此 XML 映射到以下类

final readonly class Community
{
    /**
      * @param list<Person> $member
      */
    public function __construct(
        public array $member,
    ) {}
}

您会发现使用上述映射方法时,这并不像预期的那样工作

use CuyZ\Valinor;
use EliasHaeussler\ValinorXml;

$mapper = (new Valinor\MapperBuilder())->mapper();
$source = ValinorXml\Mapper\Source\XmlSource::fromXmlFile($file);
$person = $mapper->map(Community::class, $source); // throws exception

它将抛出如下异常

CuyZ\Valinor\Mapper\TypeTreeMapperError: Could not map type `Community` with value array{member: array{…}}.

这是因为 XML 转换器不知道 <member> 是否应该是一个集合,或者它只是一个“正常”节点。这就是为什么 XmlSource 提供了适当的方法将此类节点转换为集合

use CuyZ\Valinor;
use EliasHaeussler\ValinorXml;

$mapper = (new Valinor\MapperBuilder())->mapper();
$source = ValinorXml\Mapper\Source\XmlSource::fromXmlFile($file)
    ->asCollection('member')
;
$person = $mapper->map(Community::class, $source); // instanceof Community

生成的对象将类似于以下内容

object(Community)#76 (1) {
  ["member"]=>
  array(1) {
    [0]=>
    object(Person)#126 (3) {
      ["name"]=>
      string(16) "Dr. Zane Stroman"
      ["address"]=>
      object(Address)#170 (4) {
        ["street"]=>
        string(15) "439 Karley Loaf"
        ["postcode"]=>
        string(5) "17916"
        ["city"]=>
        string(10) "West Judge"
        ["country"]=>
        string(27) "Falkland Islands (Malvinas)"
      }
      ["contact"]=>
      object(Contact)#252 (1) {
        ["phone"]=>
        string(12) "827-986-5852"
      }
    }
  }
}

然而,这仅在 XML 中只有一个集合节点时才相关。如果 XML 包含多个节点,XML 转换器会正确地将它们转换为集合

use CuyZ\Valinor;
use EliasHaeussler\ValinorXml;

$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<community>
    <member><!-- ... --></member>
    <member><!-- ... --></member>
    <member><!-- ... --></member>
</community>
XML;

$mapper = (new Valinor\MapperBuilder())->mapper();
$source = ValinorXml\Mapper\Source\XmlSource::fromXmlString($xml);
$person = $mapper->map(Community::class, $source); // instanceof Community

🧑‍💻 贡献

请参阅 CONTRIBUTING.md

⭐ 许可证

本项目采用 GNU 通用公共许可证 3.0(或更新版本) 许可。