2011-07-05 103 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,我會嘗試這兩種方法,並看看速度如何比較。 –

相關問題