MySQL nie zna Twojej struktury XML. Chociaż może bezpośrednio importować proste, dobrze sformułowane struktury XML, będziesz musiał samodzielnie przekonwertować bardziej złożone struktury. Możesz wygenerować CSV, SQL lub (obsługiwany) XML.
Dla takich dużych plików XMLReader jest najlepszym API. Najpierw utwórz instancję i otwórz plik:
$reader = new XMLReader();
$reader->open('php://stdin');
Używasz przestrzeni nazw, więc sugeruję zdefiniowanie dla nich tablicy mapowania:
$xmlns = [
'a' => 'http://www.abc-example.com'
];
Możliwe jest użycie tych samych przedrostków/aliasów, co w pliku XML, ale możesz też użyć własnego.
Następnie przejdź przez węzły XML, aż znajdziesz pierwszy węzeł elementu rekordu:
while (
$reader->read() &&
($reader->localName !== 'ABCRecord' || $reader->namespaceURI !== $xmlns['a'])
) {
continue;
}
Musisz porównać nazwę lokalną (nazwę znacznika bez prefiksu przestrzeni nazw) i identyfikator URI przestrzeni nazw. W ten sposób program nie zależy od rzeczywistych przedrostków w pliku XML.
Po znalezieniu pierwszego węzła możesz przejść do następnego rodzeństwa o tej samej nazwie lokalnej.
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');
}
Możesz użyć XMLReader do odczytania danych rekordów, ale jest to łatwiejsze dzięki wyrażeniom DOM i XPath. XMLReader może rozwinąć bieżący węzeł w węzeł DOM. Przygotuj więc dokument DOM, utwórz dla niego obiekt XPath i zarejestruj przestrzenie nazw. Rozszerzenie węzła spowoduje załadowanie węzła i wszystkich potomków do pamięci, ale nie węzłów nadrzędnych ani rodzeństwa.
$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()
umożliwia użycie wyrażenia XPath do pobrania wartości skalarnych lub list węzłów z DOM.
fputcsv()
czy zapisanie danych w pliku CSV będzie naprawdę łatwe.
Razem:
// 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');
}
Wyjście:
id,name
5967007LIEEXZX4LPK21,"REGISTERENHETEN I Bornheim"
5967007LIE45ZX4MHC90,"SUNNDAL HOSTBANK"