Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

246 Commits

Repository files navigation

Address

Build status on GitHubXP Framework ModuleBSD LicenceRequires 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;
publicfunction__construct(string$name, Author$author) {
$this->name= $name;
$this->author= $author;
}
}
class Author {
public$name;
publicfunction__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.

useutil\address\{XmlStreaming, ObjectOf};
$socket= /* ... */$stream= newXmlStreaming($socket);
$book= $stream->next(newObjectOf(Book::class, [
'name' => fn($self) => $self->name= yield,
'author' => fn($self) => $self->author= yieldnewObjectOf(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.

useutil\address\{XmlStreaming, ValueOf};
// Parse into string 'Tim Taylor'$stream= newXmlStreaming('<name>Tim Taylor</name>');
$name= $stream->next(newValueOf(null, [
'.' => fn(&$self) => $self= yield,
]);
// Parse into array ['More', 'Power']$stream= newXmlStreaming('<tools><tool>More</tool><tool>Power</tool></tools>');
$name= $stream->next(newValueOf([], [
'tool' => fn(&$self) => $self[]= yield,
]);
// Parse into map ['id' => 6100, 'name' => 'more power']$stream= newXmlStreaming('<tool id="6100">more power</tool>');
$book= $stream->next(newValueOf([], [
'@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.

useutil\address\{XmlStreaming, ObjectOf};
class Book {
public$isbn, $name;
}
// Parse into Book(isbn: '978-0552151740', name: 'A Short History...')$stream= newXmlStreaming('<book isbn="978-0552151740"><name>A Short History...</name></book>');
$book= $stream->next(newObjectOf(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.

useutil\address\{XmlStreaming, RecordOf};
class Book {
publicfunction__construct(privatestring$isbn, privatestring$name) { }
publicfunctionisbn() { return$this->isbn; }
publicfunctionname() { return$this->name; }
}
// Parse into Book(isbn: '978-0552151740', name: 'A Short History...')$stream= newXmlStreaming('<book isbn="978-0552151740"><name>A Short History...</name></book>');
$book= $stream->next(newRecordOf(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:

usepeer\http\HttpConnection;
useutil\data\Sequence;
useutil\Date;
useutil\address\{XmlStream, ObjectOf};
useutil\cmd\Console;
class Item {
public$title, $description, $pubDate, $generator, $link, $guid;
}
$definition= newObjectOf(Item::class, [
'title' => fn($self) => $self->title= yield,
'description' => fn($self) => $self->description= yield,
'pubDate' => fn($self) => $self->pubDate= newDate(yield),
'generator' => fn($self) => $self->generator= yield,
'link' => fn($self) => $self->link= yield,
'guid' => fn($self) => $self->guid= yield,
]);
$conn= newHttpConnection('https://www.tagesschau.de/xml/rss2/');
$stream= newXmlStream($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

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages