我正在尝试解析xml文件以将数据存储到数据库中。我用PHP编写了一个代码(如下所示),我可以成功运行代码。
但问题是,它需要大约8分钟来读取一个完整的文件(大约30 MB),而且每小时我必须解析大约100个文件。
所以,显然我现在的代码对我没用。有人可以建议更好的解决方案吗?或者我应该切换到其他编码语言?
我从网上获得的是,我可以使用Perl / Python或者称为XSLT的东西(坦白说我不太确定)。
$xml = new XMLReader();
$xml->open($file);
while ($xml->name === 'node1'){
$node = new SimpleXMLElement($xml->readOuterXML());
foreach($node->node2 as $node2){
//READ
}
$xml->next('node1');
}
$xml->close();
答案 0 :(得分:1)
以下是我用于解析WURFL XML数据库found here的脚本示例。
我使用了ElementTree模块用于Python并编写了一个JavaScript数组 - 虽然您可以轻松修改我的脚本以编写相同的CSV(只需更改最后3行)。
import xml.etree.ElementTree as ET
tree = ET.parse('C:/Users/Me/Documents/wurfl.xml')
root = tree.getroot()
dicto = {} #to store the data
for device in root.iter("device"): #parse out the device objects
dicto[device.get("id")] = [0, 0, 0, 0] #set up a list to store the needed variables
for child in device: #iterate through each device
if child.get("id") == "product_info": #find the product_info id
for grand in child:
if grand.get("name") == "model_name": #and the model_name id
dicto[device.get("id")][0] = grand.get("value")
dicto[device.get("id")][3] +=1
elif child.get("id") == "display": #and the display id
for grand in child:
if grand.get("name") == "physical_screen_height":
dicto[device.get("id")][1] = grand.get("value")
dicto[device.get("id")][3] +=1
elif grand.get("name") == "physical_screen_width":
dicto[device.get("id")][2] = grand.get("value")
dicto[device.get("id")][3] +=1
if not dicto[device.get("id")][3] == 3: #make sure I had enough
#otherwise it's an incomplete dataset
del dicto[device.get("id")]
arrays = []
for key in dicto.keys(): #sort this all into another list
arrays.append(key)
arrays.sort() #and sort it alphabetically
with open('C:/Users/Me/Documents/wurfl1.js', 'w') as new: #now to write it out
for item in arrays:
new.write('{\n id:"'+item+'",\n Product_Info:"'+dicto[item][0]+'",\n Height:"'+dicto[item][1]+'",\n Width:"'+dicto[item][2]+'"\n},\n')
当我再次跑步时算上这个 - 花了大约3秒钟。
答案 1 :(得分:1)
在Perl中,您可以使用XML::Twig,它旨在处理大型XML文件(大于内存中的文件)
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $file= shift @ARGV;
XML::Twig->new( twig_handlers => { 'node1/node2' => \&read_node })
->parsefile( $file);
sub read_node
{ my( $twig, $node2)= @_;
# your code, the whole node2 string is $node2->sprint
$twig->purge; # if you want to reduce memory footprint
}
您可以在xmltwig.org
找到有关XML :: Twig的更多信息答案 2 :(得分:0)
如果是Python,我建议使用lxml
。
由于遇到性能问题,我建议逐步遍历XML并逐个处理,这样可以节省大量内存并且可能更快。
我在3秒钟内阅读旧服务器10 MB XML,您的情况可能会有所不同。
关于使用lxml进行迭代:http://lxml.de/tutorial.html#tree-iteration
答案 3 :(得分:0)
查看以下代码:
$node = new SimpleXMLElement($xml->readOuterXML());
readOuterXML
的文档有一条评论,有时候它正试图寻找名称空间等等。无论如何,在这里我会怀疑性能问题。
如果可以,请考虑使用readInnerXML()
。