src/FeedIo/Parser/XmlParser.php
<?php
declare(strict_types=1);
namespace FeedIo\Parser;
use DOMElement;
use FeedIo\FeedIoException;
use FeedIo\RuleSet;
use FeedIo\FeedInterface;
use FeedIo\Feed\NodeInterface;
use FeedIo\ParserAbstract;
use FeedIo\Reader\Document;
use FeedIo\Standard\XmlAbstract;
/**
* Parses a DOM document if its format matches the parser's standard
*
* Depends on :
* - FeedIo\StandardAbstract
* - Psr\Log\LoggerInterface
*
*/
class XmlParser extends ParserAbstract
{
public function isItem(string $tagName): bool
{
if ($this->standard instanceof XmlAbstract) {
return (strtolower($this->standard->getItemNodeName()) === strtolower($tagName));
}
return false;
}
public function parseContent(Document $document, FeedInterface $feed): FeedInterface
{
if ($this->standard instanceof XmlAbstract) {
$element = $this->standard->getMainElement($document->getDOMDocument());
$this->parseNode($feed, $element, $this->standard->getFeedRuleSet());
}
return $feed;
}
public function checkBodyStructure(Document $document, iterable $mandatoryFields): bool
{
$errors = array();
$element = $document->getDOMDocument()->documentElement;
foreach ($mandatoryFields as $field) {
$list = $element->getElementsByTagName($field);
if (0 === $list->length) {
$errors[] = $field;
}
}
if (!empty($errors)) {
$message = "missing mandatory field(s) : ".implode(',', $errors);
$this->logger->warning($message);
throw new MissingFieldsException($message);
}
return true;
}
public function parseNode(NodeInterface $item, DOMElement $element, RuleSet $ruleSet): NodeInterface
{
foreach ($element->childNodes as $node) {
if ($node instanceof DOMElement) {
$this->handleNode($item, $node, $ruleSet);
}
}
return $item;
}
protected function handleNode(NodeInterface $item, DOMElement $node, RuleSet $ruleSet): void
{
if ($this->isItem($node->tagName) && $item instanceof FeedInterface) {
$linkItem = $item->getLink();
$newItem = $this->parseNode($item->newItem()->setLink($linkItem), $node, $this->getItemRuleSet());
$this->addValidItem($item, $newItem);
} else {
$rule = $ruleSet->get($node->tagName);
$rule->setProperty($item, $node);
}
}
protected function getItemRuleSet(): RuleSet
{
if ($this->standard instanceof XmlAbstract) {
return $this->standard->getItemRuleSet();
}
throw new FeedIoException('Not an XML Standard');
}
}