{"id":14985370,"url":"https://github.com/eliashaeussler/valinor-xml","last_synced_at":"2025-04-11T15:32:32.947Z","repository":{"id":244419613,"uuid":"814852300","full_name":"eliashaeussler/valinor-xml","owner":"eliashaeussler","description":"🔖 XML source for cuyz/valinor","archived":false,"fork":false,"pushed_at":"2025-04-10T23:15:44.000Z","size":401,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-11T00:48:28.984Z","etag":null,"topics":["composer","library","mapper","php","source","valinor","xml"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eliashaeussler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["eliashaeussler"],"custom":["https://paypal.me/eliashaeussler"]}},"created_at":"2024-06-13T21:01:58.000Z","updated_at":"2025-04-05T05:38:07.000Z","dependencies_parsed_at":"2024-09-14T17:01:41.524Z","dependency_job_id":"6f354f96-7213-4952-bc84-a27f2c2c22ec","html_url":"https://github.com/eliashaeussler/valinor-xml","commit_stats":{"total_commits":79,"total_committers":2,"mean_commits":39.5,"dds":0.06329113924050633,"last_synced_commit":"c7b93009757627f973167b8d2c5a63abe41d409a"},"previous_names":["eliashaeussler/valinor-xml"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eliashaeussler%2Fvalinor-xml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eliashaeussler%2Fvalinor-xml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eliashaeussler%2Fvalinor-xml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eliashaeussler%2Fvalinor-xml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eliashaeussler","download_url":"https://codeload.github.com/eliashaeussler/valinor-xml/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248431748,"owners_count":21102261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["composer","library","mapper","php","source","valinor","xml"],"created_at":"2024-09-24T14:10:49.046Z","updated_at":"2025-04-11T15:32:32.669Z","avatar_url":"https://github.com/eliashaeussler.png","language":"PHP","funding_links":["https://github.com/sponsors/eliashaeussler","https://paypal.me/eliashaeussler"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n[![Code example](docs/img/header.svg)](#-installation)\n\n# XML source for `cuyz/valinor`\n\n[![Coverage](https://img.shields.io/coverallsCoverage/github/eliashaeussler/valinor-xml?logo=coveralls)](https://coveralls.io/github/eliashaeussler/valinor-xml)\n[![Maintainability](https://img.shields.io/codeclimate/maintainability/eliashaeussler/valinor-xml?logo=codeclimate)](https://codeclimate.com/github/eliashaeussler/valinor-xml/maintainability)\n[![CGL](https://img.shields.io/github/actions/workflow/status/eliashaeussler/valinor-xml/cgl.yaml?label=cgl\u0026logo=github)](https://github.com/eliashaeussler/valinor-xml/actions/workflows/cgl.yaml)\n[![Tests](https://img.shields.io/github/actions/workflow/status/eliashaeussler/valinor-xml/tests.yaml?label=tests\u0026logo=github)](https://github.com/eliashaeussler/valinor-xml/actions/workflows/tests.yaml)\n[![Supported PHP Versions](https://img.shields.io/packagist/dependency-v/eliashaeussler/valinor-xml/php?logo=php)](https://packagist.org/packages/eliashaeussler/valinor-xml)\n\n\u003c/div\u003e\n\nA Composer library that provides an additional XML source for use with\nthe popular [`cuyz/valinor`](https://github.com/CuyZ/Valinor) library.\nThis allows to easily map XML files or contents to any signature supported\nby Valinor, e.g. objects or special array shapes. It leverages the\n[`mtownsend/xml-to-array`](https://github.com/mtownsend5512/xml-to-array)\nlibrary to convert raw XML to a reusable array structure.\n\n## 🔥 Installation\n\n[![Packagist](https://img.shields.io/packagist/v/eliashaeussler/valinor-xml?label=version\u0026logo=packagist)](https://packagist.org/packages/eliashaeussler/valinor-xml)\n[![Packagist Downloads](https://img.shields.io/packagist/dt/eliashaeussler/valinor-xml?color=brightgreen)](https://packagist.org/packages/eliashaeussler/valinor-xml)\n\n```bash\ncomposer require eliashaeussler/valinor-xml\n```\n\n## ⚡ Usage\n\nGiven the following XML:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cperson\u003e\n    \u003cname\u003eDr. Zane Stroman\u003c/name\u003e\n    \u003caddress\u003e\n        \u003cstreet\u003e439 Karley Loaf\u003c/street\u003e\n        \u003cpostcode\u003e17916\u003c/postcode\u003e\n        \u003ccity\u003eWest Judge\u003c/city\u003e\n        \u003ccountry\u003eFalkland Islands (Malvinas)\u003c/country\u003e\n    \u003c/address\u003e\n    \u003ccontact\u003e\n        \u003cphone\u003e827-986-5852\u003c/phone\u003e\n    \u003c/contact\u003e\n\u003c/person\u003e\n```\n\nThese are the resulting classes:\n\n```php\nfinal readonly class Address\n{\n    public function __construct(\n        public string $street,\n        public string $postcode,\n        public string $city,\n        public string $country,\n    ) {}\n}\n\nfinal readonly class Contact\n{\n    public function __construct(\n        public string $phone,\n    ) {}\n}\n\nfinal readonly class Person\n{\n    public function __construct(\n        public string $name,\n        public Address $address,\n        public Contact $contact,\n    ) {}\n}\n```\n\n### Mapping from XML string\n\nIn order to map the given XML to the `Person` class, you need\nto follow these three steps:\n\n1. Create a new mapper as written in [Valinor's documentation](https://valinor.cuyz.io/latest/getting-started/)\n2. Parse and prepare your XML using the shipped [`XmlSource`](src/Mapper/Source/XmlSource.php)\n3. Use the mapper to map your XML to the `Person` class\n\n```php\nuse CuyZ\\Valinor;\nuse EliasHaeussler\\ValinorXml;\n\n$mapper = (new Valinor\\MapperBuilder())-\u003emapper();\n$source = ValinorXml\\Mapper\\Source\\XmlSource::fromXmlString($xml);\n$person = $mapper-\u003emap(Person::class, $source); // instanceof Person\n```\n\nThe resulting object will look something like this:\n\n```\nobject(Person)#180 (3) {\n  [\"name\"]=\u003e\n  string(16) \"Dr. Zane Stroman\"\n  [\"address\"]=\u003e\n  object(Address)#135 (4) {\n    [\"street\"]=\u003e\n    string(15) \"439 Karley Loaf\"\n    [\"postcode\"]=\u003e\n    string(5) \"17916\"\n    [\"city\"]=\u003e\n    string(10) \"West Judge\"\n    [\"country\"]=\u003e\n    string(27) \"Falkland Islands (Malvinas)\"\n  }\n  [\"contact\"]=\u003e\n  object(Contact)#205 (1) {\n    [\"phone\"]=\u003e\n    string(12) \"827-986-5852\"\n  }\n}\n```\n\n### Mapping from XML file\n\nThe XML can also be read from an external file:\n\n```php\nuse CuyZ\\Valinor;\nuse EliasHaeussler\\ValinorXml;\n\n$mapper = (new Valinor\\MapperBuilder())-\u003emapper();\n$source = ValinorXml\\Mapper\\Source\\XmlSource::fromXmlFile($file);\n$person = $mapper-\u003emap(Person::class, $source); // instanceof Person\n```\n\n### Convert nodes to collections\n\nSometimes it might be necessary to always convert XML nodes to\ncollections. Given the following XML:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003ccommunity\u003e\n    \u003cmember\u003e\u003c!-- ... --\u003e\u003c/member\u003e \u003c!-- NOTE: There's only one member --\u003e\n\u003c/community\u003e\n```\n\nLet's assume you want to map this XML to the following class:\n\n```php\nfinal readonly class Community\n{\n    /**\n      * @param list\u003cPerson\u003e $member\n      */\n    public function __construct(\n        public array $member,\n    ) {}\n}\n```\n\nYou will recognize that this does not work as expected when using the\nabove mapping method:\n\n```php\nuse CuyZ\\Valinor;\nuse EliasHaeussler\\ValinorXml;\n\n$mapper = (new Valinor\\MapperBuilder())-\u003emapper();\n$source = ValinorXml\\Mapper\\Source\\XmlSource::fromXmlFile($file);\n$person = $mapper-\u003emap(Community::class, $source); // throws exception\n```\n\nIt will instead throw an exception like this:\n\n```\nCuyZ\\Valinor\\Mapper\\TypeTreeMapperError: Could not map type `Community` with value array{member: array{…}}.\n```\n\nThis is because the XML converter does not know whether `\u003cmember\u003e` should\nbe a collection or if it's just a \"normal\" node. That's why the `XmlSource`\nprovides an appropriate method to convert such nodes to collections:\n\n```php\nuse CuyZ\\Valinor;\nuse EliasHaeussler\\ValinorXml;\n\n$mapper = (new Valinor\\MapperBuilder())-\u003emapper();\n$source = ValinorXml\\Mapper\\Source\\XmlSource::fromXmlFile($file)\n    -\u003easCollection('member')\n;\n$person = $mapper-\u003emap(Community::class, $source); // instanceof Community\n```\n\nThe resulting object will look something like this:\n\n```\nobject(Community)#76 (1) {\n  [\"member\"]=\u003e\n  array(1) {\n    [0]=\u003e\n    object(Person)#126 (3) {\n      [\"name\"]=\u003e\n      string(16) \"Dr. Zane Stroman\"\n      [\"address\"]=\u003e\n      object(Address)#170 (4) {\n        [\"street\"]=\u003e\n        string(15) \"439 Karley Loaf\"\n        [\"postcode\"]=\u003e\n        string(5) \"17916\"\n        [\"city\"]=\u003e\n        string(10) \"West Judge\"\n        [\"country\"]=\u003e\n        string(27) \"Falkland Islands (Malvinas)\"\n      }\n      [\"contact\"]=\u003e\n      object(Contact)#252 (1) {\n        [\"phone\"]=\u003e\n        string(12) \"827-986-5852\"\n      }\n    }\n  }\n}\n```\n\nHowever, this is only relevant if only one node of the collection\nexists in your XML. If the XML contains more than one node, the XML\nconverter properly converts them to a collection:\n\n```php\nuse CuyZ\\Valinor;\nuse EliasHaeussler\\ValinorXml;\n\n$xml = \u003c\u003c\u003cXML\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003ccommunity\u003e\n    \u003cmember\u003e\u003c!-- ... --\u003e\u003c/member\u003e\n    \u003cmember\u003e\u003c!-- ... --\u003e\u003c/member\u003e\n    \u003cmember\u003e\u003c!-- ... --\u003e\u003c/member\u003e\n\u003c/community\u003e\nXML;\n\n$mapper = (new Valinor\\MapperBuilder())-\u003emapper();\n$source = ValinorXml\\Mapper\\Source\\XmlSource::fromXmlString($xml);\n$person = $mapper-\u003emap(Community::class, $source); // instanceof Community\n```\n\n## 🧑‍💻 Contributing\n\nPlease have a look at [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n## ⭐ License\n\nThis project is licensed under [GNU General Public License 3.0 (or later)](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feliashaeussler%2Fvalinor-xml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feliashaeussler%2Fvalinor-xml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feliashaeussler%2Fvalinor-xml/lists"}