【问题标题】:How do I get a 50MB zip file with a 600MB xml file into a mysql datatable?如何将带有 600MB xml 文件的 50MB zip 文件放入 mysql 数据表中?
【发布时间】:2015-11-13 18:50:31
【问题描述】:

如何将 50MB 的 zip 文件和 600MB 的 xml 文件(超过 300,000 个“")放入 mysql 数据表中? xml文件本身的结构如下:

<?xml version='1.0' encoding='UTF-8'?>
<abc:ABCData xmlns:abc="http://www.abc-example.com" xmlns:xyz="http:/www.xyz-example.com">
<abc:ABCHeader>
<abc:ContentDate>2015-08-15T09:03:29.379055+00:00</abc:ContentDate>
<abc:FileContent>PUBLISHED</abc:FileContent>
<abc:RecordCount>310598</abc:RecordCount>
<abc:Extension>
  <xyz:Sources>
    <xyz:Source>
      <xyz:ABC>5967007LIEEXZX4LPK21</xyz:ABC>
      <xyz:Name>Bornheim Register Centre</xyz:Name>
      <xyz:ROCSponsorCountry>NO</xyz:ROCSponsorCountry>
      <xyz:RecordCount>398</xyz:RecordCount>
      <xyz:ContentDate>2015-08-15T05:00:02.952+02:00</xyz:ContentDate>
      <xyz:LastAttemptedDownloadDate>2015-08-15T09:00:01.885686+00:00</xyz:LastAttemptedDownloadDate>
      <xyz:LastSuccessfulDownloadDate>2015-08-15T09:00:02.555222+00:00</xyz:LastSuccessfulDownloadDate>
      <xyz:LastValidDownloadDate>2015-08-15T09:00:02.555222+00:00</xyz:LastValidDownloadDate>
     </xyz:Source>
    </xyz:Sources>
   </abc:Extension>
 </abc:ABCHeader>
<abc:ABCRecords>
 <abc:ABCRecord>
 <abc:ABC>5967007LIEEXZX4LPK21</abc:ABC>
  <abc:Entity>
    <abc:LegalName>REGISTERENHETEN I Bornheim</abc:LegalName>
    <abc:LegalAddress>
      <abc:Line1>Havnegata 48</abc:Line1>
      <abc:City>Bornheim</abc:City>
      <abc:Country>NO</abc:Country>
      <abc:PostalCode>8900</abc:PostalCode>
    </abc:LegalAddress>
    <abc:HeadquartersAddress>
      <abc:Line1>Havnegata 48</abc:Line1>
      <abc:City>Bornheim</abc:City>
      <abc:Country>NO</abc:Country>
      <abc:PostalCode>8900</abc:PostalCode>
    </abc:HeadquartersAddress>
    <abc:BusinessRegisterEntityID register="Enhetsregisteret">974757873</abc:BusinessRegisterEntityID>
    <abc:LegalForm>Organisasjonsledd</abc:LegalForm>
    <abc:EntityStatus>Active</abc:EntityStatus>
  </abc:Entity>
  <abc:Registration>
    <abc:InitialRegistrationDate>2014-06-15T12:03:33.000+02:00</abc:InitialRegistrationDate>
    <abc:LastUpdateDate>2015-06-15T20:45:32.000+02:00</abc:LastUpdateDate>
    <abc:RegistrationStatus>ISSUED</abc:RegistrationStatus>
    <abc:NextRenewalDate>2016-06-15T12:03:33.000+02:00</abc:NextRenewalDate>
    <abc:ManagingLOU>59670054IEEXZX44PK21</abc:ManagingLOU>
  </abc:Registration>
</abc:ABCRecord>
<abc:ABCRecord>
  <abc:ABC>5967007LIE45ZX4MHC90</abc:ABC>
  <abc:Entity>
    <abc:LegalName>SUNNDAL HOSTBANK</abc:LegalName>
    <abc:LegalAddress>
      <abc:Line1>Sunfsalsvegen 15</abc:Line1>
      <abc:City>SUNNDALSPRA</abc:City>
      <abc:Country>NO</abc:Country>
      <abc:PostalCode>6600</abc:PostalCode>
    </abc:LegalAddress>
    <abc:HeadquartersAddress>
      <abc:Line1>Sunndalsvegen 15</abc:Line1>
      <abc:City>SUNNDALSPRA</abc:City>
      <abc:Country>NO</abc:Country>
      <abc:PostalCode>6600</abc:PostalCode>
    </abc:HeadquartersAddress>
    <abc:BusinessRegisterEntityID register="Foretaksregisteret">9373245963</abc:BusinessRegisterEntityID>
    <abc:LegalForm>Hostbank</abc:LegalForm>
    <abc:EntityStatus>Active</abc:EntityStatus>
  </abc:Entity>
  <abc:Registration>
    <abc:InitialRegistrationDate>2014-06-26T15:01:02.000+02:00</abc:InitialRegistrationDate>
    <abc:LastUpdateDate>2015-06-27T15:02:39.000+02:00</abc:LastUpdateDate>
    <abc:RegistrationStatus>ISSUED</abc:RegistrationStatus>
    <abc:NextRenewalDate>2016-06-26T15:01:02.000+02:00</abc:NextRenewalDate>
    <abc:ManagingLOU>5967007LIEEXZX4LPK21</abc:ManagingLOU>
  </abc:Registration>
</abc:ABCRecord>
</abc:ABCRecords>
</abc:ABCData>

mysql 表的外观如何,我该如何完成?目标是在表中包含所有带有 abc 标记的内容。此外,每天都会通过下载链接提供一个新的 zip 文件,并且每天都会更新表格。 zip 文件以以下结构命名:“20150815-XYZ-concatenated-file.zip”。一步一步的提示会很棒吗?我试过这个:Importing XML file with special tags & namespaces <abc:xyz> in mysql 目前还没有完成工作!

根据下面的 ThW 解释,我现在做了以下工作:

<?php

// open input
$reader = new XMLReader();
$reader->open('./xmlreader.xml');

// open output
$output = fopen('./xmlreader.csv', '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');
} 

这对吗?!我在哪里可以找到输出?!以及如何在mysql中获取输出。对不起我的菜鸟问题,这是我第一次这样做......

$dbHost = "localhost";
$dbUser = "root";
$dbPass = "password";
$dbName = "new_xml_extract";

$dbConn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);

$delete = $dbConn->query("TRUNCATE TABLE `test_xml`");

....

$sql = "INSERT INTO `test_xml` (`.....`, `.....`)" . "VALUES ('". $dbConn->real_escape_string($.....) ."', '".$dbConn->real_escape_string($.....)."')";

$result = $dbConn->query($sql);
}

【问题讨论】:

  • 你试过什么?你试过用谷歌吗?键入类似...如何将 xml 导入 mysql 数据库
  • 我做到了!我尝试通过 mysql 中的导入函数简单地上传它...没有用..我通过dev.mysql.com/doc/refman/5.6/en/load-xml.html 尝试过..没有用..我尝试通过 PHP simplexml_load_file() 函数...一个小的示例 xml 文件,但其中没有名称空间。我正在尝试这种方法stackoverflow.com/questions/32058904/…,但是 foreach() 函数只允许我对两个标签执行此操作。如果我尝试使用 500MB 的文件,它会冻结。这是我第一次这样做
  • 在您的情况下,您必须使用可以接受大文件的软件或通过终端。没有网站会为你做这件事
  • 我也尝试先将其转换为 csv(通过 makro),它适用于少量记录,但不适用于整个文件。我确实有一个外壳和终端正在运行。我可以使用什么命令执行此操作,我需要如何准备 mysql 表?

标签: php mysql xml zip xml-namespaces


【解决方案1】:

MySQL 不知道您的 XML 结构。虽然它可以直接导入简单、格式良好的 XML 结构,但您需要自己转换更复杂的结构。您可以生成 CSV、SQL 或(支持的)XML。

对于像这样的大文件,XMLReader 是最好的 API。首先创建一个实例并打开文件:

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

你正在使用命名空间,所以我建议为它们定义一个映射数组:

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

可以使用与 XML 文件中相同的前缀/别名,但您也可以使用自己的。

接下来遍历 XML 节点,直到找到第一个记录元素节点:

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

您需要比较本地名称(不带命名空间前缀的标记名称)和命名空间 URI。这样您的编程方式不依赖于 XML 文件中的实际前缀。

找到第一个节点后,可以遍历到下一个同名的兄弟节点。

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

您可以使用 XMLReader 读取记录数据,但使用 DOM 和 XPath 表达式更容易。 XMLReader 可以将当前节点扩展为一个 DOM 节点。所以准备一个 DOM 文档,为其创建一个 XPath 对象并注册名称空间。扩展节点会将节点及其所有后代加载到内存中,但不会加载父节点或兄弟节点。

$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() 允许您使用 Xpath 表达式从 DOM 中获取标量值或节点列表。

fputcsv() 将数据写入 CSV 是否真的很容易。

放在一起:

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

输出:

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

【讨论】:

  • 感谢您的详细解释。不过我有点困惑。请看我上面的编辑!我在哪里可以找到输出?!在 DOM 文档中?!我该怎么做呢?这是一个简单的 html 文档吗?我创建了一个 xmlreader.html ... $output = fopen('./xmlreader.html', 'w'); ...虽然我没有看到任何输出!以及如何将输出从那里输入到 mysql 中?对不起我的菜鸟问题!
  • 我使用了php://stdinphp://stdout。这是标准输入和输出的两个“文件名”。这最适合eval.in 等在线服务。您将其更改为文件名,但目标应该是 CSV,更改为 HTML 文件。确保输出文件是可写的(权限)。如果将输出写入文件,则可以使用echo 输出状态信息。
  • 我创建了一个 csv 文件并确保其可写,但仍然没有反应! *cry ...我正在使用 Netbeans,希望这不是问题!
  • 我无法调试您的环境,我的示例有效 - 您可以在此处看到:eval.in/419784
  • 这看起来像是将 UTF-8 解释为 Latin-1。确保在插入时指定字符集/编码。
猜你喜欢
  • 2015-11-13
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 1970-01-01
相关资源
最近更新 更多