Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment puis-je obtenir un fichier zip de 50 Mo avec un fichier xml de 600 Mo dans une table de données mysql ?

MySQL ne connaît pas votre structure XML. Bien qu'il puisse importer directement des structures XML simples et bien formées, vous devrez convertir vous-même des structures plus complexes. Vous pouvez générer CSV, SQL ou un XML (pris en charge).

Pour les fichiers volumineux comme celui-ci, XMLReader est la meilleure API. Créez d'abord une instance et ouvrez le fichier :

$reader = new XMLReader();
$reader->open('php://stdin');

Vous utilisez des espaces de noms, je vous suggère donc de définir un tableau de mappage pour eux :

$xmlns = [
  'a' => 'http://www.abc-example.com'
];

Il est possible d'utiliser les mêmes préfixes/alias que dans le fichier XML, mais vous pouvez également utiliser les vôtres.

Parcourez ensuite les nœuds XML jusqu'à ce que vous trouviez le premier nœud d'élément d'enregistrement :

while (
  $reader->read() && 
  ($reader->localName !== 'ABCRecord' ||  $reader->namespaceURI !== $xmlns['a'])
) {
  continue;
}

Vous devez comparer le nom local (le nom de la balise sans le préfixe de l'espace de noms) et l'URI de l'espace de noms. De cette façon, votre programme ne dépend pas des préfixes réels dans le fichier XML.

Après avoir trouvé le premier nœud, vous pouvez passer au frère suivant avec le même nom 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');
}

Vous pouvez utiliser XMLReader pour lire les données d'enregistrement, mais c'est plus facile avec les expressions DOM et XPath. XMLReader peut développer le nœud actuel en un nœud DOM. Préparez donc un document DOM, créez un objet XPath pour celui-ci et enregistrez les espaces de noms. L'expansion d'un nœud chargera le nœud et tous ses descendants en mémoire, mais pas les nœuds parents ou frères.

$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() vous permet d'utiliser l'expression Xpath pour récupérer des valeurs scalaires ou des listes de nœuds à partir d'un DOM.

fputcsv() sera-t-il vraiment facile d'écrire les données dans un CSV.

Réunissez :

// 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');
} 

Sortie :

id,name
5967007LIEEXZX4LPK21,"REGISTERENHETEN I Bornheim"
5967007LIE45ZX4MHC90,"SUNNDAL HOSTBANK"