如何在java或php中解析一个非常大的xml文件并将其插入mysql数据库
我正试图将一个巨大的xml文件解析到我的MySQL数据库中。该文件为4.7gb。我知道,这太疯狂了 数据来自这里:(最新的相册xml压缩为700mb,解压为4.7gb) 我可以使用java或php来解析和更新数据库。我认为java是更聪明的想法 我需要找到一种在不填充4gb内存的情况下解析xml的方法,并将其加载到数据库中 最聪明的方法是什么?我听说过SAX解析器,我的想法正确吗 现在,我不关心从那些URL下载图像,我只想把数据放在我的数据库中。我还没有设计表,但我现在对xml方面更感兴趣 我使用php的fread()打开文件的前1000个比特,这样至少我可以看到它的样子,下面是文件中第一个相册的结构示例:如何在java或php中解析一个非常大的xml文件并将其插入mysql数据库,java,php,xml,sax,Java,Php,Xml,Sax,我正试图将一个巨大的xml文件解析到我的MySQL数据库中。该文件为4.7gb。我知道,这太疯狂了 数据来自这里:(最新的相册xml压缩为700mb,解压为4.7gb) 我可以使用java或php来解析和更新数据库。我认为java是更聪明的想法 我需要找到一种在不填充4gb内存的情况下解析xml的方法,并将其加载到数据库中 最聪明的方法是什么?我听说过SAX解析器,我的想法正确吗 现在,我不关心从那些URL下载图像,我只想把数据放在我的数据库中。我还没有设计表,但我现在对xml方面更感兴趣 我使
<releases>
<release id="1" status="Accepted">
<images>
<image height="600" type="primary" uri="http://s.dsimg.com/image/R-1-1193812031.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812031.jpeg" width="600" />
<image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812053.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812053.jpeg" width="600" />
<image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812072.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812072.jpeg" width="600" />
<image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812091.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812091.jpeg" width="600" />
</images>
<artists>
<artist>
<name>Persuader, The</name>
</artist>
</artists>
<title>Stockholm</title>
<labels>
<label catno="SK032" name="Svek" />
</labels>
<formats>
<format name="Vinyl" qty="2">
<descriptions>
<description>12"</description>
</descriptions>
</format>
</formats>
<genres>
<genre>Electronic</genre>
</genres>
<styles>
<style>Deep House</style>
</styles>
<country>Sweden</country>
<released>1999-03-00</released>
<notes>Recorded at the Globe studio in Stockholm. The titles are the names of Stockholm's districts.</notes>
<master_id>5427</master_id>
<tracklist>
<track>
<position>A</position>
<title>Östermalm</title>
<duration>4:45</duration>
</track>
<track>
<position>B1</position>
<title>Vasastaden</title>
<duration>6:11</duration>
</track>
<track>
<position>B2</position>
<title>Kungsholmen</title>
<duration>2:49</duration>
</track>
<track>
<position>C1</position>
<title>Södermalm</title>
<duration>5:38</duration>
</track>
<track>
<position>C2</position>
<title>Norrmalm</title>
<duration>4:52</duration>
</track>
<track>
<position>D</position>
<title>Gamla Stan</title>
<duration>5:16</duration>
</track>
</tracklist>
</release>
说服者
斯德哥尔摩
12"
电子的
深屋
瑞典
1999-03-00
在斯德哥尔摩的环球影城录制。标题是斯德哥尔摩地区的名称。
5427
A.
Östermalm
4:45
地下一层
瓦萨斯塔登
6:11
地下二层
国王岛
2:49
C1
Södermalm
5:38
C2
马尔姆
4:52
D
老城区
5:16
谢谢。如果我想用PHP解析它,我将分两步进行:
节点拆分一次文件,并使该小文件成为有效的XML如果速度不是关键,那么PHP实际上会更好,因为在PHP中解析文本/XML很容易。我不久前也遇到过类似的问题。下面是脚本的一部分,它导入了大约28MB的文件,而不是将整个数据读入内存。它可能会工作:)。它通过XML节点读取,在内存中只保留XM的一小部分L.脚本只需稍加修改即可满足您的需要
$reader = new XMLReader();
$reader->open(<path_to_large_xml_file>);
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName == "Table") {
$node = $reader->expand();
$dom = new DomDocument();
$n = $dom->importNode($node,true);
$dom->appendChild($n);
$sxe = simplexml_import_dom($n);
$Data = array();
$DataColumns = array();
foreach ($columns as $key => $column)
{
if (in_array($key,$DateColumns))
{
$DateArray = explode('/',substr(trim($sxe->$column),0,10));
$ValueColumn = date('Y-m-d H:i:s',mktime(0,0,0,$DateArray[1],$DateArray[0],$DateArray[2]));
$Data[] = '\''.$ValueColumn.'\'';
$DataColumns[] = $key;
if ($SplitDateInsert == 'enabled')
{
$Data[] = '\''.$DateArray[2].'\'';
$Data[] = '\''.$DateArray[1].'\'';
$Data[] = '\''.$DateArray[0].'\'';
$DataColumns[] = $key.'_year';
$DataColumns[] = $key.'_month';
$DataColumns[] = $key.'_day';
}
} else {
$ValueColumn = addslashes(trim($sxe->$column));
$Data[] = '\''.$ValueColumn.'\'';
$DataColumns[] = $key;
}
}
$SQL = "INSERT INTO {$tableName} (".implode(',',$DataColumns).") VALUES (".implode(',',$Data).")";
$db->query($SQL);
} // END IF table
}
}
$reader=newXMLReader();
$reader->open();
而($reader->read()){
开关($reader->nodeType){
大小写(XMLREADER::元素):
如果($reader->localName==“Table”){
$node=$reader->expand();
$dom=新的DomDocument();
$n=$dom->importNode($node,true);
$dom->appendChild($n);
$sxe=simplexml\u import\u dom($n);
$Data=array();
$DataColumns=array();
foreach($key=>$column的列)
{
if(在数组中($key,$DateColumns))
{
$DateArray=explode('/',substr(trim($sxe->$column),0,10));
$ValueColumn=date('Y-m-dh:i:s',mktime(0,0,0,$DateArray[1],$DateArray[0],$DateArray[2]);
$Data[]='\'.$ValueColumn'\'';
$DataColumns[]=$key;
如果($SplitDateInsert=='enabled')
{
$Data[]='\'.$DateArray[2].'\';
$Data[]='\''.$DATEARRY[1].\'';
$Data[]='\''.$DATEARRY[0].\'';
$DataColumns[]=$key.“U年”;
$DataColumns[]=$key.“u月”;
$DataColumns[]=$key.“U日”;
}
}否则{
$ValueColumn=addslashes(trim($sxe->$column));
$Data[]='\'.$ValueColumn'\'';
$DataColumns[]=$key;
}
}
$SQL=“插入到{$tableName}(“.introde(',',$DataColumns)。”)值(“.introde(',',$Data)。”)”;
$db->query($SQL);
}//结束IF表
}
}
显然,您需要的是流式API而不是DOM,因为DOM需要将整个文档保存在内存中。Java支持SAX和。我本人从未使用过Stax,但听说它比SAX更易于使用,同时仍然很高效
还要确保将工作拆分为多个事务:数据库无法在单个事务中支持多个insert语句。假设MySQL在这方面具有与Oracle类似的功能,为什么不让DB处理解析?在Oracle中,您可以注册XMLSchema,创建结构化的XMLType t可以(可能比clob更有用),然后插入文件
从来没有在这么大的地方使用过它,但我不明白为什么它不应该工作,它只需要几行代码就可以完成。你只需要有MySQL经验的人来告诉你细节是如何工作的。我建议在Java上使用Stax。或者更简单一点,这会增加访问的便利性
但是,您需要对XML做什么呢?要在DB中对其进行流式处理,有一些方法可以将blob作为流处理(尽管mySQL JDBC驱动程序因其怪癖而臭名昭著)所以,应该是可行的。 < 4.7 GB不是疯狂的,只是温和的。如果你有64位java,扩展应该是最有效和最容易使用的选项。 < p>你没有说过你想用XML处理什么。你可以考虑使用撒克逊的流模式XSLT(它需要的是撒克逊EE产品,它需要钱)-如果处理本质上是依次处理每个“release”元素的“突发模式流”练习,那么它应该不会太难。当然,您也可以使用低级SAX o