2011-07-05 61 views
2

我已经在我的系统中保存了一个HUUUGE HTML文件,其中包含来自产品目录的数据。数据的结构使得每个产品记录的名称位于两个标签(名称)和(/名称)之间。提取HTML文件中两个标签之间的数据

每个产品最多有3个属性:名称,产品ID和颜色,但并非所有产品都具有所有这些属性。

如何在不混淆产品属性的情况下为每个产品提取此数据?该文件也是50兆字节!

代码示例....

<name>'hat'</name> 
blah blah blah 
<prodId>'1829493'</prodId> 
blah blah blah 
<color>'cyan'</color> 

blah blah 
blah blah blah 
blah blah blah 

<name>'shirt'</name> 
blah blah blahblah blah blah 
<prodId>'193'</prodId> 

<name>'dress'</name> 
blah blah blah 
blah blah blah 
<prodId>'18'</prodId> 
<color>'dark purple'</color> 
+0

张贴一些代码。如果输入数据格式良好,也许有一个简单的答案。 –

+1

看起来像读取一个XML文档。您可以尝试稍微更改xmlread帮助页面中提供的函数(http://www.mathworks.com/help/techdoc/ref/xmlread.html)。 – Aabaz

+0

@ Kerrek SB 我已经添加了一个代码示例'nugget'。 –

回答

5

的大小为50 MB的文件是不是这么大,你不能只加载其内容直接进入MATLAB作为一个字符串,你可以用做功能FILEREAD

strContents = fileread('yourfile.html'); 

假设你有上面的文件格式,则可以再用REGEXP(使用named token capture)的功能解析内容

expr = '<(?<tag>name|prodId|color)>''([^<>]+)''</\k<tag>>'; 
tokens = regexp(strContents,expr,'tokens'); 
tokens = vertcat(tokens{:}); 

token使用示例文件内容,内容将是:

tokens = 

    'name'  'hat'   
    'prodId' '1829493'  
    'color'  'cyan'  
    'name'  'shirt'  
    'prodId' '193'   
    'name'  'dress'  
    'prodId' '18'   
    'color'  'dark purple' 

然后,您可能要分析所生成的n乘2单元阵列,并放置在一个structure array内容与领域'name''prodId''color'。难点在于不是每个条目都有三个字段。假设每个'name'会后跟一个'prodId',一个'color',或(顺序'prodId'然后'color'),然后将下面的代码应该为你工作:

s = struct('name',[],'prodId',[],'color',[]); %# Initialize structure 
nTokens = size(tokens,1);      %# Get number of tokens 
nameIndex = find(strcmp(tokens(:,1),'name')); %# Find indices of 'name' 
[s(1:numel(nameIndex)).name] = deal(tokens{nameIndex,2}); %# Fill 'name' field 

%# Find and fill 'prodId' that follows a 'name': 
index = strcmp(tokens(min(nameIndex+1,nTokens),1),'prodId'); 
[s(index).prodId] = deal(tokens{nameIndex(index)+1,2}); 

%# Find and fill 'color' that follows a 'name': 
index = strcmp(tokens(min(nameIndex+1,nTokens),1),'color'); 
[s(index).color] = deal(tokens{nameIndex(index)+1,2}); 

%# Find and fill 'color' that follows a 'prodId': 
index = strcmp(tokens(min(nameIndex+2,nTokens),1),'color'); 
[s(index).color] = deal(tokens{min(nameIndex(index)+2,nTokens),2}); 

s内容使用您的示例文件内容将是:

>> s(1) 

     name: 'hat' 
    prodId: '1829493' 
    color: 'cyan' 

>> s(2) 

     name: 'shirt' 
    prodId: '193' 
    color: [] 

>> s(3) 

     name: 'dress' 
    prodId: '18' 
    color: 'dark purple' 
+1

+1正确使用正则表达式,虽然它让我想起了这一点:http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html – Amro

+1

@Amro:我能说什么,我喜欢过着危险的生活。 ;) – gnovice

+0

这是一个梦幻般的解决方案 - 正是我所追求的。然而,我的“标签”的例子是真相的抽象。代码对标签对来说可能更灵活吗? 标签对可以是两个字符串吗?将这对标签存储在一个结构中?在上面的代码中,我们假设标签对中的第二个是前一个带有'/'的标签。 而不是,它可能是

0

有两种方法可以解决这类问题:字符串操作与正则表达式(如建议通过gnovice)或解析文件(或两者的混合)。如果你的文件结构非常好,解析通常是最好的;正则表达式赢得混乱的文件。

下面是解析解决方案。

首先下载xmliotools,然后在您的文件中调用xml_read。你的例子不是完全可重复的,所以这里有两个不同版本的数据。

保存这test1.xml

<?xml version="1.0" encoding="utf-8"?> 
<root> 
<name>'hat'</name> 
<prodId>'1829493'</prodId> 
<color>'cyan'</color> 
<name>'dress'</name> 
<prodId>'18'</prodId> 
<color>'dark purple'</color> 
</root> 

保存这test2.xml

<?xml version="1.0" encoding="utf-8"?> 
<root> 
<item> 
<name>'hat'</name> 
<prodId>'1829493'</prodId> 
<color>'cyan'</color> 
</item> 
<item> 
<name>'dress'</name> 
<prodId>'18'</prodId> 
<color>'dark purple'</color> 
</item> 
</root> 

现在比较

x1 = xml_read('test1.xml') 
x2 = xml_read('test2.xml') 
+0

感谢Richie,我会尝试这两种方法,并看看速度如何比较。 –

相关问题