Files
myep/src/BusProNet/XmlCrawlerFactory.php
T

58 lines
1.7 KiB
PHP

<?php
namespace App\BusProNet;
use Symfony\Component\DomCrawler\Crawler;
/**
* Builds a Crawler over BusPro's XML payloads.
*
* The Crawler constructor parses its content as HTML5, which flattens the
* nesting BusPro's exports and API responses rely on, so XML has to be added
* through addXmlContent() instead.
*/
final class XmlCrawlerFactory
{
public static function create(string $xml): Crawler
{
$crawler = new Crawler();
$crawler->addXmlContent($xml);
return $crawler;
}
/**
* Explains why create() returned an empty Crawler. addXmlContent() discards the
* libxml errors, so an empty, a malformed and a truncated payload are
* indistinguishable afterwards; this re-parses to recover the reason. Only worth
* calling on the failure path.
*/
public static function diagnose(string $xml): string
{
if ('' === trim($xml)) {
return sprintf('empty response (%d bytes)', strlen($xml));
}
$previousUseErrors = libxml_use_internal_errors(true);
libxml_clear_errors();
try {
simplexml_load_string($xml);
$messages = [];
foreach (libxml_get_errors() as $error) {
$messages[] = sprintf('%s (line %d, column %d)', trim($error->message), $error->line, $error->column);
}
if ([] === $messages) {
return sprintf('unknown XML error (%d bytes)', strlen($xml));
}
return sprintf('%s (%d bytes)', implode('; ', array_unique($messages)), strlen($xml));
} finally {
libxml_clear_errors();
libxml_use_internal_errors($previousUseErrors);
}
}
}