sql >> Database teknologi >  >> RDS >> Mysql

Hvordan får jeg en 50MB zip-fil med en 600MB xml-fil ind i en mysql-datatabel?

MySQL kender ikke din XML-struktur. Selvom det kan importere simple, velformede XML-strukturer direkte, skal du selv konvertere mere komplekse strukturer. Du kan generere CSV, SQL eller en (understøttet) XML.

Til store filer som den er XMLReader den bedste API. Opret først en instans og åbn filen:

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

Du bruger navnerum, så jeg foreslår, at du definerer et mapping-array for dem:

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

Det er muligt at bruge de samme præfikser/aliaser som i XML-filen, men du kan også bruge dine egne.

Gå derefter gennem XML-knuderne, indtil du finder den første postelementknude:

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

Du skal sammenligne det lokale navn (tagnavnet uden navnerumspræfikset) og navneområdets URI. På denne måde afhænger du ikke af de faktiske præfikser i XML-filen.

Når du har fundet den første node, kan du gå til den næste søskende med det samme lokale navn.

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 bruge XMLReader til at læse postdataene, men det er nemmere med DOM- og XPath-udtryk. XMLReader kan udvide den aktuelle node til en DOM-node. Så forbered et DOM-dokument, opret et XPath-objekt til det og registrer navneområderne. Udvidelse af en node vil indlæse noden og alle efterkommere i hukommelsen, men ikke overordnede noder eller søskende.

$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() giver dig mulighed for at bruge Xpath-udtryk til at hente skalarværdier eller nodelister fra en DOM.

fputcsv() vil det gøre det rigtig nemt at skrive dataene ind i en CSV.

Sæt sammen:

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

Output:

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



  1. Hvad returnerer en vellykket MySQL DELETE? Hvordan kontrollerer man, om SLETNING lykkedes?

  2. Sådan finder du sorteringen i SQL Server (T-SQL)

  3. Codeigniter-databasefejl:1064 Brug af MySQL og måske en sessionskonfigurationsfejl

  4. Python/Flask:Hvordan kan man se, hvor lang tid en bruger bruger på en side? (Dataindtastning/tidslog-app)