MySQL känner inte till din XML-struktur. Även om det kan importera enkla, välformade XML-strukturer direkt, måste du konvertera mer komplexa strukturer själv. Du kan generera CSV, SQL eller en (stödd) XML.
För stora filer som den är XMLReader det bästa API:et. Skapa först en instans och öppna filen:
$reader = new XMLReader();
$reader->open('php://stdin');
Du använder namnrymder, så jag föreslår att du definierar en mappningsmatris för dem:
$xmlns = [
'a' => 'http://www.abc-example.com'
];
Det är möjligt att använda samma prefix/alias som i XML-filen, men du kan också använda dina egna.
Gå sedan igenom XML-noderna tills du hittar den första postelementnoden:
while (
$reader->read() &&
($reader->localName !== 'ABCRecord' || $reader->namespaceURI !== $xmlns['a'])
) {
continue;
}
Du måste jämföra det lokala namnet (taggen utan namnområdesprefixet) och namnområdets URI. På så sätt beror du inte på de faktiska prefixen i XML-filen.
När du hittat den första noden kan du gå vidare till nästa syskon med samma lokala namn.
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');
}
Du kan använda XMLReader för att läsa postdata men det är lättare med DOM- och XPath-uttryck. XMLReader kan expandera den aktuella noden till en DOM-nod. Så förbered ett DOM-dokument, skapa ett XPath-objekt för det och registrera namnområdena. Om du expanderar en nod laddas noden och alla avkomlingar till minnet, men inte överordnade noder eller syskon.
$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()
låter dig använda Xpath-uttryck för att hämta skalära värden eller nodlistor från en DOM.
fputcsv()
kommer det att göra det riktigt enkelt att skriva in data i en CSV.
Sätt ihop:
// 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');
}
Utdata:
id,name
5967007LIEEXZX4LPK21,"REGISTERENHETEN I Bornheim"
5967007LIE45ZX4MHC90,"SUNNDAL HOSTBANK"