Streaming parser for Yandex Market Language (YML) feeds.
Uses XMLReader for the outer scan and SimpleXMLElement for per-offer parsing, so the whole catalog is never loaded in memory — offers arrive as a Generator.
- PHP >= 8.3
- Extensions:
ext-mbstring,ext-simplexml,ext-xmlreader,ext-libxml
composer require sirian/yandex-market-language-parseruse Sirian\YMLParser\Parser;
$parser = new Parser();
$result = $parser->parse('/path/to/catalog.xml');
$shop = $result->getShop();
echo $shop->getName();
foreach ($shop->getCategories() as $category) {
echo $category->getId(), ': ', $category->getName(), "\n";
}
foreach ($result->getOffers() as $offer) {
echo $offer->getId(), ' — ', $offer->getName(), "\n";
}Sirian\YMLParser\Factory\Factory::createOffer() returns:
type attribute |
class |
|---|---|
vendor.model |
Sirian\YMLParser\Model\Offer\VendorModelOffer |
book |
Sirian\YMLParser\Model\Offer\BookOffer |
| anything else | Sirian\YMLParser\Model\Offer\Offer |
| absent | Sirian\YMLParser\Model\Offer\VendorModelOffer (default) |
Provide a custom FactoryInterface to swap any model/storage implementation:
use Sirian\YMLParser\Factory\Factory;
use Sirian\YMLParser\Model\Offer\Offer;
use Sirian\YMLParser\Parser;
$factory = new class () extends Factory {
public function createOffer(string $type): Offer
{
// return your own subclass
return parent::createOffer($type);
}
};
$parser = new Parser($factory);Offer::applyField(string $field, string $value): bool maps XML child elements onto setters. Override it in your own offer subclass to handle YML fields beyond the built-in ones:
final class MyOffer extends VendorModelOffer
{
public function applyField(string $field, string $value): bool
{
if ('country_of_origin' === $field) {
$this->country = $value;
return true;
}
return parent::applyField($field, $value);
}
}Any field can also be accessed via the raw XML — $offer->getXml() / $shop->getXml().
composer install
vendor/bin/phpunit # tests + coverage
vendor/bin/phpstan analyse # static analysis (level 8)
vendor/bin/php-cs-fixer fix --dry-run --diff # code styleMIT