PHP XMLReader - чтение неправильно отформатированных файлов XML

Этот вопрос связан с другим сообщением, которое я разместил здесь (для ссылка)

Я загружаю файлы журналов по FTP из проекта открытых данных в Великобритании, и файлы журналов имеют размер около 3 МБ каждый и представлены следующим образом:

<?xml version="1.0" encoding="UTF-8"?><Pport xmlns="http://www.thalesgroup.com/rtti/PushPort/v12" ts="2018-02-05T21:33:59.8558288Z" version="12.0"><uR updateOrigin="Darwin"><deactivated rid="201802058015464"/></uR></Pport>
<?xml version="1.0" encoding="UTF-8"?><Pport xmlns="http://www.thalesgroup.com/rtti/PushPort/v12" xmlns:ns3="http://www.thalesgroup.com/rtti/PushPort/Forecasts/v2" ts="2018-02-05T21:33:59.8558288Z" version="12.0"><uR updateOrigin="Darwin"><TS rid="201802058709918" ssd="2018-02-05" uid="W09918"><ns3:Location tpl="DARTFD" wta="07:36"><ns3:arr delayed="true" et="21:34" src="Darwin"/><ns3:plat cisPlatsup="true" platsup="true">2</ns3:plat></ns3:Location></TS></uR></Pport>
<?xml version="1.0" encoding="UTF-8"?><Pport xmlns="http://www.thalesgroup.com/rtti/PushPort/v12" xmlns:ns3="http://www.thalesgroup.com/rtti/PushPort/Forecasts/v2" ts="2018-02-05T21:33:59.8558288Z" version="12.0"><uR updateOrigin="Darwin"><TS rid="201802058771469" ssd="2018-02-05" uid="W71469"><ns3:Location tpl="WLWYCSD" wtd="13:16"><ns3:dep delayed="true" et="21:34" src="Darwin"/></ns3:Location><ns3:Location tpl="WLWYNGC" wtp="13:18"><ns3:pass delayed="true" et="21:36" src="Darwin"/><ns3:plat cisPlatsup="true" platsup="true">3</ns3:plat></ns3:Location><ns3:Location tpl="HATFILD" wtp="13:21:30"><ns3:pass delayed="true" et="21:39" src="Darwin"/><ns3:plat cisPlatsup="true" platsrc="A" platsup="true">1</ns3:plat></ns3:Location><ns3:Location tpl="POTRSBR" wtp="13:26"><ns3:pass delayed="true" et="21:44" src="Darwin"/><ns3:plat cisPlatsup="true" platsup="true">1</ns3:plat></ns3:Location><ns3:Location tpl="ALEXNDP" wtp="13:36:30"><ns3:pass delayed="true" et="21:51" src="Darwin"/><ns3:plat cisPlatsup="true" platsup="true">2</ns3:plat></ns3:Location><ns3:Location tpl="HRGYURV" wta="13:43" wtd="13:48"><ns3:arr delayed="true" et="21:57" src="Darwin"/><ns3:dep delayed="true" et="21:58" src="Darwin"/></ns3:Location><ns3:Location tpl="HRNSYMD" wta="13:50"><ns3:arr delayed="true" et="22:00" src="Darwin"/></ns3:Location></TS></uR></Pport>

Чтобы добавить, иногда последняя запись является неработающей записью, например:

<?xml version="1.0" encoding="UTF-8"?><Pport xmlns="http://www.thalesgroup.com/rtti/PushPort/v12" xmlns:ns3="http://www.thalesgroup.com/rtti/PushPort/Forecasts/v2" ts="2018-02-05T21:34:52.2569006Z" version="12.0"><uR updateOrigin="Trust"><TS rid="201802056757064" ssd="2018-02-05" uid="C57064"><ns3:Location pta="21:34" ptd="21:34" tpl="DEVNPRT" wta="21:34" wtd="21:34:30"><ns3:arr at

Я воспользовался приведенным здесь советом и попытался реализовать решение PHP с помощью XMLReader, однако при настройке файла журнала XML XMLReader выдает ошибки.

Это базовый код, который я использую:

$xmlReader->open($filename);

// While there is something to read continue reading
    while ($xmlReader->read()) { 

    // check to ensure nodeType is an Element not attribute or #Text  
        if ($xmlReader->nodeType == XMLReader::ELEMENT) {

            if ($xmlReader->hasAttributes) {
//Do something here
                }
            }
        }
    }

Я подумал об одном решении, поскольку каждая запись в файле журнала представляет собой отдельные строки, я думал, что могу открыть файл, прочитать и загрузить в XMLReader, но у меня не было возможности сделать это, например:

if ($filename = fopen("./pPortData.log", "r")) {
       while (!feof($filename)) {
            $xmlstr = fgets($filename);
            # do same stuff with the $line
            $address = new SimpleXMLElement($xmlstr) or die("Error: Cannot create object");
            echo $address->getName(), PHP_EOL;
            foreach($address as $name => $part) {
                echo "$name: $part" . "/n/r", PHP_EOL;
            }
        }    
        fclose($xmlstr);
    }

Но без радости. Так ...

1) Знаете ли вы, как достичь этого, пожалуйста?

2) Или вы знаете, как построчно загружать из файла в XMLReader?

3) Как исправить XML файл?

Спасибо

Лючио


person Lucio    schedule 07.02.2018    source источник


Ответы (1)


Вы были близки к своим последним усилиям, загрузка каждой строки за раз, а затем их обработка с помощью SimpleXML должна быть в порядке.

Я внес несколько изменений, я добавил ловушку ошибок, которая выбирает последнюю запись, которая может быть неполной, и просто отображает сообщение. Другая часть касается того, как вы обрабатываете данные XML, поэтому на данный момент я просто выводю данные из загруженного XML.

if ($file = fopen("./pPortData.log", "r")) {
    while (!feof($file)) {
        $xmlstr = fgets($file);
        libxml_use_internal_errors(true);
        try {
            $xml = new SimpleXMLElement($xmlstr);
            echo $xml->getName(), PHP_EOL;
            foreach($xml->children() as $part) {
                echo $part->asXML() . PHP_EOL;
            }
        }
        catch ( Exception $e )  {
            echo "Last part unreadable.".PHP_EOL;
        }
    }
    fclose($file);
}
person Nigel Ren    schedule 07.02.2018
comment
Большое спасибо, это здорово - Clap Clap :) - person Lucio; 09.02.2018
comment
Если это помогло, отметьте его как принятый ответ - meta.stackexchange.com/questions/5234/ - person Nigel Ren; 09.02.2018