sql >> Databasteknik >  >> RDS >> Mysql

Hur får jag en 50MB zip-fil med en 600MB xml-fil till en mysql-datatabell?

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"



  1. Django SearchVector med hjälp av icontains

  2. Literal matchar inte formatsträngen för Oracle SQL to_date i en strängkolumn

  3. Postgres fulltextsökning med synonymer

  4. Skapa dynamisk fråga i lagrad procedur MySQL