Skip to content

Creates objects from XML input streams while parsing them.

Notifications You must be signed in to change notification settings

xp-forge/address

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

246 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Address

Build status on GitHub XP Framework Module BSD Licence Requires PHP 7.4+ Supports PHP 8.0+ Latest Stable Version

Creates objects from XML input streams while parsing them. Yes, this still happens today 😉

Example

Given the following two value objects:

class Book {
  public $name, $author;

  public function __construct(string $name, Author $author) {
    $this->name= $name;
    $this->author= $author;
  }
}

class Author {
  public $name;

  public function __construct(string $name) {
    $this->name= $name;
  }
}

...and this XML:

<?xml version="1.0" encoding="utf-8"?>
<book>
  <name>A Short History of Nearly Everything</name>
  <author>
    <name>Bill Bryson</name>
  </author>
</book>

...the following will map the XML to an object instance while reading it from the socket.

use util\address\{XmlStreaming, ObjectOf};

$socket= /* ... */

$stream= new XmlStreaming($socket);
$book= $stream->next(new ObjectOf(Book::class, [
  'name'   => fn($self) => $self->name= yield,
  'author' => fn($self) => $self->author= yield new ObjectOf(Author::class, [
    'name'   => fn($self) => $self->name= yield ?: '(unknown author)'; }
  ])
]);

Creating values

Definitions are used to create structured data from the XML input. Here are all the implementations:

ValueOf

Simplemost version which is given a seed value, which it can modify through the given address functions.

use util\address\{XmlStreaming, ValueOf};

// Parse into string 'Tim Taylor'
$stream= new XmlStreaming('<name>Tim Taylor</name>');
$name= $stream->next(new ValueOf(null, [
  '.' => fn(&$self) => $self= yield,
]);

// Parse into array ['More', 'Power']
$stream= new XmlStreaming('<tools><tool>More</tool><tool>Power</tool></tools>');
$name= $stream->next(new ValueOf([], [
  'tool' => fn(&$self) => $self[]= yield,
]);

// Parse into map ['id' => 6100, 'name' => 'more power']
$stream= new XmlStreaming('<tool id="6100">more power</tool>');
$book= $stream->next(new ValueOf([], [
  '@id' => fn(&$self) => $self['id']= (int)yield,
  '.'   => fn(&$self) => $self['name']= yield,
]);

ObjectOf

Creates objects without invoking their constructors. Modifies the members directly, including non-public ones.

use util\address\{XmlStreaming, ObjectOf};

class Book {
  public $isbn, $name;
}

// Parse into Book(isbn: '978-0552151740', name: 'A Short History...')
$stream= new XmlStreaming('<book isbn="978-0552151740"><name>A Short History...</name></book>');
$book= $stream->next(new ObjectOf(Book::class, [
  '@isbn' => fn($self) => $self->isbn= yield,
  'name'  => fn($self) => $self->name= yield,
]);

RecordOf

Works with record classes, which are defined as being immutable and having an all-arg constructor. Modifies the named constructor arguments.

use util\address\{XmlStreaming, RecordOf};

class Book {
  public function __construct(private string $isbn, private string $name) { }

  public function isbn() { return $this->isbn; }
  public function name() { return $this->name; }
}

// Parse into Book(isbn: '978-0552151740', name: 'A Short History...')
$stream= new XmlStreaming('<book isbn="978-0552151740"><name>A Short History...</name></book>');
$book= $stream->next(new RecordOf(Book::class, [
  '@isbn' => fn(&$args) => $args['isbn']= yield,
  'name'  => fn(&$args) => $args['name']= yield,
]);

Iteration

Any Address instance can be iterated using the foreach statement. Using the data sequences library in combination with calling the value() method here's a way to parse an RSS feed's items:

use peer\http\HttpConnection;
use util\data\Sequence;
use util\Date;
use util\address\{XmlStream, ObjectOf};
use util\cmd\Console;

class Item {
  public $title, $description, $pubDate, $generator, $link, $guid;
}

$definition= new ObjectOf(Item::class, [
  'title'       => fn($self) => $self->title= yield,
  'description' => fn($self) => $self->description= yield,
  'pubDate'     => fn($self) => $self->pubDate= new Date(yield),
  'generator'   => fn($self) => $self->generator= yield,
  'link'        => fn($self) => $self->link= yield,
  'guid'        => fn($self) => $self->guid= yield,
]);

$conn= new HttpConnection('https://www.tagesschau.de/xml/rss2/');
$stream= new XmlStream($conn->get()->in());

Sequence::of($stream->pointers('//channel/item'))
  ->map(fn($pointer) => $pointer->value($definition))
  ->each(fn($item) => Console::writeLine('- ', $item->title, "\n  ", $item->link))
;

About

Creates objects from XML input streams while parsing them.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages