Как получить ZIP-файл объемом 50 МБ с XML-файлом объемом 600 МБ (более 300 000 «<«abc: ABCRecord»> «) в mysql datatable? Сам файл xml имеет следующую структуру:
<?xml version='1.0' encoding='UTF-8'?>
<abc:ABCData xmlns:abc="http://www.abc-example.com" xmlns:xyz="http:/www.xyz-example.com">
<abc:ABCHeader>
<abc:ContentDate>2015-08-15T09:03:29.379055+00:00</abc:ContentDate>
<abc:FileContent>PUBLISHED</abc:FileContent>
<abc:RecordCount>310598</abc:RecordCount>
<abc:Extension>
<xyz:Sources>
<xyz:Source>
<xyz:ABC>5967007LIEEXZX4LPK21</xyz:ABC>
<xyz:Name>Bornheim Register Centre</xyz:Name>
<xyz:ROCSponsorCountry>NO</xyz:ROCSponsorCountry>
<xyz:RecordCount>398</xyz:RecordCount>
<xyz:ContentDate>2015-08-15T05:00:02.952+02:00</xyz:ContentDate>
<xyz:LastAttemptedDownloadDate>2015-08-15T09:00:01.885686+00:00</xyz:LastAttemptedDownloadDate>
<xyz:LastSuccessfulDownloadDate>2015-08-15T09:00:02.555222+00:00</xyz:LastSuccessfulDownloadDate>
<xyz:LastValidDownloadDate>2015-08-15T09:00:02.555222+00:00</xyz:LastValidDownloadDate>
</xyz:Source>
</xyz:Sources>
</abc:Extension>
</abc:ABCHeader>
<abc:ABCRecords>
<abc:ABCRecord>
<abc:ABC>5967007LIEEXZX4LPK21</abc:ABC>
<abc:Entity>
<abc:LegalName>REGISTERENHETEN I Bornheim</abc:LegalName>
<abc:LegalAddress>
<abc:Line1>Havnegata 48</abc:Line1>
<abc:City>Bornheim</abc:City>
<abc:Country>NO</abc:Country>
<abc:PostalCode>8900</abc:PostalCode>
</abc:LegalAddress>
<abc:HeadquartersAddress>
<abc:Line1>Havnegata 48</abc:Line1>
<abc:City>Bornheim</abc:City>
<abc:Country>NO</abc:Country>
<abc:PostalCode>8900</abc:PostalCode>
</abc:HeadquartersAddress>
<abc:BusinessRegisterEntityID register="Enhetsregisteret">974757873</abc:BusinessRegisterEntityID>
<abc:LegalForm>Organisasjonsledd</abc:LegalForm>
<abc:EntityStatus>Active</abc:EntityStatus>
</abc:Entity>
<abc:Registration>
<abc:InitialRegistrationDate>2014-06-15T12:03:33.000+02:00</abc:InitialRegistrationDate>
<abc:LastUpdateDate>2015-06-15T20:45:32.000+02:00</abc:LastUpdateDate>
<abc:RegistrationStatus>ISSUED</abc:RegistrationStatus>
<abc:NextRenewalDate>2016-06-15T12:03:33.000+02:00</abc:NextRenewalDate>
<abc:ManagingLOU>59670054IEEXZX44PK21</abc:ManagingLOU>
</abc:Registration>
</abc:ABCRecord>
<abc:ABCRecord>
<abc:ABC>5967007LIE45ZX4MHC90</abc:ABC>
<abc:Entity>
<abc:LegalName>SUNNDAL HOSTBANK</abc:LegalName>
<abc:LegalAddress>
<abc:Line1>Sunfsalsvegen 15</abc:Line1>
<abc:City>SUNNDALSPRA</abc:City>
<abc:Country>NO</abc:Country>
<abc:PostalCode>6600</abc:PostalCode>
</abc:LegalAddress>
<abc:HeadquartersAddress>
<abc:Line1>Sunndalsvegen 15</abc:Line1>
<abc:City>SUNNDALSPRA</abc:City>
<abc:Country>NO</abc:Country>
<abc:PostalCode>6600</abc:PostalCode>
</abc:HeadquartersAddress>
<abc:BusinessRegisterEntityID register="Foretaksregisteret">9373245963</abc:BusinessRegisterEntityID>
<abc:LegalForm>Hostbank</abc:LegalForm>
<abc:EntityStatus>Active</abc:EntityStatus>
</abc:Entity>
<abc:Registration>
<abc:InitialRegistrationDate>2014-06-26T15:01:02.000+02:00</abc:InitialRegistrationDate>
<abc:LastUpdateDate>2015-06-27T15:02:39.000+02:00</abc:LastUpdateDate>
<abc:RegistrationStatus>ISSUED</abc:RegistrationStatus>
<abc:NextRenewalDate>2016-06-26T15:01:02.000+02:00</abc:NextRenewalDate>
<abc:ManagingLOU>5967007LIEEXZX4LPK21</abc:ManagingLOU>
</abc:Registration>
</abc:ABCRecord>
</abc:ABCRecords>
</abc:ABCData>
Как должна выглядеть таблица mysql и как этого добиться? Цель состоит в том, чтобы в таблице было все содержимое, помеченное abc. Кроме того, каждый день будет предоставляться новый zip-файл по ссылке для скачивания, и он должен обновлять таблицу каждый день. Zip-файлы имеют следующую структуру: «20150815-XYZ-concatenated-file.zip». Пошаговая подсказка была бы отличной? Я попробовал это: Импорт XML-файла со специальными тегами & Пространства имен <а: хуг> в MySQL на данный момент, но работа еще не закончена!
Основываясь на объяснении Thw ниже, я сделал следующее:
<?php
// open input
$reader = new XMLReader();
$reader->open('./xmlreader.xml');
// open output
$output = fopen('./xmlreader.csv', 'w');
fputcsv($output, ['id', 'name']);
$xmlns = [
'a' => 'http://www.abc-example.com'
];
// prepare DOM
$dom = new DOMDocument;
$xpath = new DOMXpath($dom);
foreach ($xmlns as $prefix => $namespaceURI) {
$xpath->registerNamespace($prefix, $namespaceURI);
}
// look for the first record element
while (
$reader->read() &&
(
$reader->localName !== 'ABCRecord' ||
$reader->namespaceURI !== $xmlns['a']
)
) {
continue;
}
// while you have an record element
while ($reader->localName === 'ABCRecord') {
if ($reader->namespaceURI === 'http://www.abc-example.com') {
// expand record element node
$node = $reader->expand($dom);
// fetch data and write it to output
fputcsv(
$output,
[
$xpath->evaluate('string(a:ABC)', $node),
$xpath->evaluate('string(a:Entity/a:LegalName)', $node)
]
);
}
// move to the next record sibling
$reader->next('ABCRecord');
}
Это правильно?! И где я могу найти выход ?! И как я могу получить вывод в MySQL. Извините за мои вопросы новичка, я впервые делаю это …
$dbHost = "localhost";
$dbUser = "root";
$dbPass = "password";
$dbName = "new_xml_extract";
$dbConn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);
$delete = $dbConn->query("TRUNCATE TABLE `test_xml`");
....
$sql = "INSERT INTO `test_xml` (`.....`, `.....`)" . "VALUES ('". $dbConn->real_escape_string($.....) ."', '".$dbConn->real_escape_string($.....)."')";
$result = $dbConn->query($sql);
}
MySQL не знает вашу структуру XML. Хотя он может напрямую импортировать простые, хорошо структурированные XML-структуры, вам придется самостоятельно преобразовывать более сложные структуры. Вы можете генерировать CSV, SQL или (поддерживаемый) XML.
Для таких больших файлов XMLReader — лучший API. Сначала создайте экземпляр и откройте файл:
$reader = new XMLReader();
$reader->open('php://stdin');
Вы используете пространства имен, поэтому я предлагаю определить для них массив отображения:
$xmlns = [
'a' => 'http://www.abc-example.com'
];
Можно использовать те же префиксы / псевдонимы, что и в файле XML, но вы также можете использовать и свои собственные.
Далее пересекайте узлы XML, пока не найдете первый узел элемента записи:
while (
$reader->read() &&
($reader->localName !== 'ABCRecord' || $reader->namespaceURI !== $xmlns['a'])
) {
continue;
}
Вам нужно сравнить локальное имя (имя тега без префикса пространства имен) и URI пространства имен. Этот способ программирования не зависит от фактических префиксов в файле XML.
После того, как вы нашли первый узел, вы можете перейти к следующему брату с тем же локальным именем.
while ($reader->localName === 'ABCRecord') {
if ($reader->namespaceURI === 'http://www.abc-example.com') {
// read data for the record ...
}
// move to the next record sibling
$reader->next('ABCRecord');
}
Вы можете использовать XMLReader для чтения данных записи, но это проще с выражениями DOM и XPath. XMLReader может развернуть текущий узел в узел DOM. Поэтому подготовьте документ DOM, создайте для него объект XPath и зарегистрируйте пространства имен. Расширение узла загрузит узел и всех его потомков в память, но не родительские узлы или братьев и сестер.
$dom = new DOMDocument;
$xpath = new DOMXpath($dom);
foreach ($xmlns as $prefix => $namespaceURI) {
$xpath->registerNamespace($prefix, $namespaceURI);
}
while ($reader->localName === 'ABCRecord') {
if ($reader->namespaceURI === 'http://www.abc-example.com') {
$node = $reader->expand($dom);
var_dump(
$xpath->evaluate('string(a:ABC)', $node),
$xpath->evaluate('string(a:Entity/a:LegalName)', $node)
);
}
$reader->next('ABCRecord');
}
DOMXPath::evaluate()
позволяет использовать выражение Xpath для извлечения скалярных значений или списков узлов из DOM.
fputcsv()
Будет ли это действительно легко записать данные в CSV.
Собрать вместе:
// open input
$reader = new XMLReader();
$reader->open('php://stdin');
// open output
$output = fopen('php://stdout', 'w');
fputcsv($output, ['id', 'name']);
$xmlns = [
'a' => 'http://www.abc-example.com'
];
// prepare DOM
$dom = new DOMDocument;
$xpath = new DOMXpath($dom);
foreach ($xmlns as $prefix => $namespaceURI) {
$xpath->registerNamespace($prefix, $namespaceURI);
}
// look for the first record element
while (
$reader->read() &&
(
$reader->localName !== 'ABCRecord' ||
$reader->namespaceURI !== $xmlns['a']
)
) {
continue;
}
// while you have an record element
while ($reader->localName === 'ABCRecord') {
if ($reader->namespaceURI === 'http://www.abc-example.com') {
// expand record element node
$node = $reader->expand($dom);
// fetch data and write it to output
fputcsv(
$output,
[
$xpath->evaluate('string(a:ABC)', $node),
$xpath->evaluate('string(a:Entity/a:LegalName)', $node)
]
);
}
// move to the next record sibling
$reader->next('ABCRecord');
}
Выход:
id,name
5967007LIEEXZX4LPK21,"REGISTERENHETEN I Bornheim"5967007LIE45ZX4MHC90,"SUNNDAL HOSTBANK"
Других решений пока нет …