MATLAB Answers

Question about accessing data in a nested struct

51 views (last 30 days)
Teshan Rezel
Teshan Rezel on 26 Jan 2021
Edited: per isakson on 27 Jan 2021
Hi all,
I am trying to get data from an xml file using xml2struct. Calling the struct using dot notation such as
Settings.CAFConfigurationSettings.numberOfTestPieces.Text
doesn't seem to work. Currently, I am calling on the data using the syntax
Settings.Children(20).Children.Data
where Dataset is my structure and x, y and z are integers referring to the index position within the nested structure. The problem is that sometimes the xml structure stores the same information in different positions meaning x, y and z will be different for these. For example, the "date" field might be the 3rd index (x=3) in one file, or the 2nd index (x=2) in another.
Is there a way to navigate around this please? I need to have a consistent way to gather this data because I loop through several xml files, so I need to get the same, consistent information from all the files with certainty.
I have tried to use "find" but to no avail. a sample of the files can be found here: https://www.dropbox.com/sh/ed5uv80s272mh4t/AAA1hROx8LvVeALHpqtTuSiGa?dl=0.
Thank you in advance
The code:
Accessing the data
close all
clear all
clc
%Asking the user to select the folder with the Images and Auto analysis in
startingFolder = pwd;
fprintf('Select the directory containing the Images and Auto analysis \n \n');
RawImages = uigetdir(startingFolder); %Creating the variable from the user selection
addpath(RawImages); %Ensuring matlab will follow the path
files = dir([RawImages '\AutoAnalysis\*.xml']);
numOfFiles = numel(files); %Counting number of files in the folder for looping purposes
Settings = xml2struct([RawImages '\settings.xml']); %Converting XML to structure then accessing the number of the samples from the Settings file
NumOfSamples = str2double(Settings.Children(20).Children.Data);
headings = {'Time','Temperature','Height','Area','Circumference', 'Shape Factor', 'Tip Radius', 'Base Width', 'Max Width', 'Height:Base Width Ratio', 'Height:Max Width Ratio', 'Bse Centre X', 'Base Centre Y', 'LHS Difference', 'RHS Difference'};
objectRangeEnd = strcat('O', num2str(numOfFiles));
objectRange = strcat('A2:', objectRangeEnd);
for j = 1:NumOfSamples %Getting the manually named test pieces from the settings
TestPieceName = Settings.Children(22).Children((2*j)).Children(4).Children.Data; %Creating a name variable to use when making file and folder names
Sample = ['Test Piece ' num2str(j) '-' TestPieceName];
TestPiece = zeros(numOfFiles,3); %Making an array to store the variables
for k = 1:numOfFiles %Grabbing the time and file data from the save file name
flds = {'date','bytes','isdir','datenum'}; %Reading time and temp from file
A = rmfield(files,flds); %Remove the file information that is unnecessary
codes = struct2cell(A); %Reduces the structure to only the fields required
codes = codes'; %Converts the labels in A to the format required
new = strsplit(char(codes(k)),'.'); % To remove the file type
new2 = strsplit(char(new(1)),'-'); % Splits the experimental conditions
time = str2double(new2(2));
alpha = new2(3);
alpha = char(alpha);
alpha(1) = [];
temp = str2double(alpha);
TestPiece(k,1) = time;
TestPiece(k,2) = temp;
file = [ RawImages '\AutoAnalysis\' files(k).name]; % Creating the k-th file name
DataSet = xml2struct(file); % Converting XML files to structures
datasetNum= numel(DataSet.Children);
testPieceLocation = datasetNum - NumOfSamples + j; %Indexing Height, Area, and Circumference etc.
TestPiece(k,3) = str2double(DataSet.Children(testPieceLocation).Children(end).Children('height').Children.Data); %Height
TestPiece(k,4) = str2double(DataSet.Children(testPieceLocation).Children(end).Children().Children.Data); %Area
TestPiece(k,5) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(find('circumference')).Children.Data); %Circumference
TestPiece(k,6) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(find('shapeFactor')).Children.Data); %Shape Factor
TestPiece(k,7) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(find('tipRadius')).Children.Data); %Tip Radius
TestPiece(k,8) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(5).Children.Data); %Base width
TestPiece(k,9) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(6).Children.Data); %Max Width
TestPiece(k,10) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(find('hBwRatio')).Children.Data); %hBw Ratio
TestPiece(k,11) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(find('hMwRatio')).Children.Data); %hMw Ratio
TestPiece(k,12) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(1).Children.Data); %Base Centre X
TestPiece(k,13) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(2).Children.Data); %Base Centre Y
TestPiece(k,14) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(3).Children.Data); %LHS Diff
TestPiece(k,15) = str2double(DataSet.Children(testPieceLocation).Children(end).Children(4).Children.Data); %RHS Diff
initialheight = TestPiece(1,3);
initialarea = TestPiece(1,4);
initialcirc = TestPiece(1,5);
initialSFactor = TestPiece(1,6);
initialTRad = TestPiece(1,7);
initialBW = TestPiece(1,8);
initialMWidth = TestPiece(1,9);
initialHBW = TestPiece(1,10);
initialHMW = TestPiece(1,11);
initialBaseCX = TestPiece(1,12);
initialBaseCY = TestPiece(1,13);
initialLHSDiff = TestPiece(1,14);
initialRHSDiff = TestPiece(1,15);
TestPiece(k,3) = TestPiece(k,3)/initialheight;
TestPiece(k,4) = TestPiece(k,4)/initialarea;
TestPiece(k,5) = TestPiece(k,5)/initialcirc;
TestPiece(k,6) = TestPiece(k,6)/initialSFactor;
TestPiece(k,7) = TestPiece(k,7)/initialTRad;
TestPiece(k,8) = TestPiece(k,8)/initialBW;
TestPiece(k,9) = TestPiece(k,9)/initialMWidth;
TestPiece(k,10) = TestPiece(k,10)/initialHBW;
TestPiece(k,11) = TestPiece(k,11)/initialHMW;
TestPiece(k,12) = TestPiece(k,12)/initialBaseCX;
TestPiece(k,13) = TestPiece(k,13)/initialBaseCY;
TestPiece(k,14) = TestPiece(k,14)/initialLHSDiff;
TestPiece(k,15) = TestPiece(k,15)/initialRHSDiff;
end
sampleDirectory = fullfile(RawImages); %file creation
filename = fullfile(sampleDirectory, ['Results.xls']); %Creating the filename to put the excel file in the appropriate folder
writecell(headings, filename, 'Sheet', Sample, 'Range', 'A1:O1');
writematrix(TestPiece, filename, 'Sheet', Sample, 'Range', objectRange);
end
  3 Comments
Teshan Rezel
Teshan Rezel on 27 Jan 2021
nevermind @per isakson, I was being stupid! thank you for your help, it's worked! can you type an answer please so I can accept yours?

Sign in to comment.

Accepted Answer

per isakson
per isakson on 27 Jan 2021
Edited: per isakson on 27 Jan 2021
It is impossible (for me) to help based on the little information that you provide. Here (R2018b) it works fine.
>> sas = xml_read( '..\settings.xml') % the xml-file is in the parent folder
sas =
struct with fields:
version: '1.3.6213.31983'
date: '2020-03-18T13:44:48.0887698+00:00'
testStandardIndex: 'CoalAsh'
startCaptureTemperature: 400
endCaptureTemperature: 1550
temperatureRamp: 7
temperatureInterval: 1
standbyTemperature: 30
backlightOffTemperature: 710
numberOfTestPieces: 6
testPiece: [1×1 struct]
cal: [1×1 struct]
gridDisplayEnable: 1
activeTestPiece: 1
ATTRIBUTE: [1×1 struct]
>> sas.activeTestPiece
ans =
1
where xml_read is part of xml_io_tools by Jaroslaw Tuszynski.
I propose that you use XML Notepad (free, Windows) to inspect the structure of the xml-files. Be sure not to reference non-existing fields.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!