Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

xml - Extracting data between two tags in HTML file

I've got a HUUUGE HTML file here saved on my system, which contains data from a product catalogue. The data is structured such that for each product record the name is between two tags (name) and (/name) .

Each product has up to 3 attributes: name, productID, and color, but not all products will have all these attributes.

How would I go about extracting this data for each product without mixing up the product attributes? The file is also 50 megabyte!

Code example ....

<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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A file of size 50 MB isn't so big that you can't just load its contents directly into MATLAB as a string, which you can do with the function FILEREAD:

strContents = fileread('yourfile.html');

Assuming the file format you have above, you can then parse the contents with the function REGEXP (using named token capture):

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

And the contents of token using your sample file contents will be:

tokens = 

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

You may then want to parse the resulting N-by-2 cell array and place the contents in a structure array with fields 'name', 'prodId', and 'color'. The difficulty is that not every entry will have all three fields. Assuming each 'name' will be followed by either a 'prodId', a 'color', or both (in the order 'prodId' then 'color'), then the following code should work for you:

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

And the contents of s using your sample file contents will be:

>> s(1)

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

>> s(2)

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

>> s(3)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...