O MySQL não conhece sua estrutura XML. Embora possa importar diretamente estruturas XML simples e bem formadas, você mesmo precisará converter estruturas mais complexas. Você pode gerar CSV, SQL ou um XML (suportado).
Para arquivos grandes como esse XMLReader é a melhor API. Primeiro crie uma instância e abra o arquivo:
$reader = new XMLReader();
$reader->open('php://stdin');
Você está usando namespaces, então sugiro definir uma matriz de mapeamento para eles:
$xmlns = [
'a' => 'http://www.abc-example.com'
];
É possível usar os mesmos prefixos/aliases do arquivo XML, mas você também pode usar os seus próprios.
Em seguida, percorra os nós XML até encontrar o primeiro nó do elemento de registro:
while (
$reader->read() &&
($reader->localName !== 'ABCRecord' || $reader->namespaceURI !== $xmlns['a'])
) {
continue;
}
Você precisa comparar o nome local (o nome da tag sem o prefixo do namespace) e o URI do namespace. Desta forma a sua programação não depende dos prefixos reais no arquivo XML.
Depois de encontrar o primeiro nó, você pode passar para o próximo irmão com o mesmo nome local.
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');
}
Você pode usar XMLReader para ler os dados do registro, mas é mais fácil com expressões DOM e XPath. XMLReader pode expandir o nó atual em um nó DOM. Portanto, prepare um documento DOM, crie um objeto XPath para ele e registre os namespaces. A expansão de um nó carregará o nó e todos os descendentes na memória, mas não os nós pais ou irmãos.
$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()
permite que você use a expressão Xpath para buscar valores escalares ou listas de nós de um DOM. fputcsv()
será muito fácil escrever os dados em um CSV. Coloque junto:
// 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');
}
Resultado:
id,name
5967007LIEEXZX4LPK21,"REGISTERENHETEN I Bornheim"
5967007LIE45ZX4MHC90,"SUNNDAL HOSTBANK"