This function converts a MATLAB structure into a XML file.
Wouter Falkena (2019). struct2xml (https://www.mathworks.com/matlabcentral/fileexchange/28639-struct2xml), MATLAB Central File Exchange. Retrieved .
1.7.0.0 | The function now replaces element and attribute names containing _dash_ by -, _dot_ by . and _colon_ by : |
|
1.6.0.0 | Bugfix in val2str subfunction |
|
1.5.0.0 | Removed the for-loop in the val2str subfunction, thereby increasing the speed drastically. |
|
1.4.0.0 | Increased the speed of the str2val subfunction by removing the for-loop and making use of the suggestion of T. Lohuis. |
|
1.3.0.0 | Improved processing speed for multiline strings (or arrays) by 160%. |
|
1.2.0.0 | Added the on-screen output functionality suggested by Philipp Orth |
|
1.1.0.0 | Added a warning for ill-formatted Attributes |
Inspired: struct2xml with bug fix, struct2xml( s, varargin ), Microscopy Image Browser (MIB), Microscopy Image Browser 2 (MIB2)
Create scripts with code, output, and formatted text in a single executable document.
svanimisetti (view profile)
Anne Valvezan (view profile)
grajcjan (view profile)
Hi,
the example (in the script) is a bit confusing. Matlab uses two commas to define a string and not a char (line 172) and usage of commas for numbers is unnecessary, if the code uses function val2str respectively num2str (line 175).
tom li (view profile)
Martin Weisenhorn (view profile)
Rakesh Jasti (view profile)
Laio Marinheiro (view profile)
Worked perfectly! Thanks a lot!
Jacob Lynch August (view profile)
i added two methods to improve usability at line 57.
s = structArray2cell( s );
s = removeEmptyTextFields( s );
function s = removeEmptyTextFields( s )
% prevents the following error when Text field is empty, like after
% xml_struct = xml2struct( xml_file );
% struct2xml( xml_struct, xml_file );
% % Error using xmlwrite (line 82)
% % Java exception occurred:
% % java.lang.NullPointerException
% %
% % at com.mathworks.xml.XMLUtils.serializeXML(XMLUtils.java:192)
% %
% % at com.mathworks.xml.XMLUtils.serializeXML(XMLUtils.java:49)
% %
% %
% % Error in struct2xml (line 77)
% % xmlwrite(file,docNode);
switch class( s )
case 'cell'
s = cellfun( ...
@removeEmptyTextFields, s, ...
'UniformOutput', false );
case 'struct'
if isfield( s, 'Text' )
if isempty( s.Text )
s = rmfield( s, 'Text' );
end%if%isempty
end%if%isfield
if isempty( s ) || ...
isequal( s, struct() )
return;
end%if%isempty
s = structfun( ...
@removeEmptyTextFields, s, ...
'UniformOutput', false );
otherwise
% do nothing
end%switch%case%class(s)
end%function%removeEmptyTextFields
function s = structArray2cell( s )
% to avoid num2cell(s) in exterior function
switch class( s )
case 'cell'
s = cellfun( ...
@structArray2cell, s, ...
'UniformOutput', false );
case 'struct'
if isempty( s ) || ...
isequal( s, struct() )
return;
elseif isscalar( s )
s = structfun( ...
@structArray2cell, s, ...
'UniformOutput', false );
else%if ~isscalar( s )
s = structArray2cell( num2cell( s ) );
end%ifs
otherwise
% do nothing
end%switch%case%class(s)
end%function%structArray2cell
Herve Demezil (view profile)
it must bu a cell of structures:
m code :
<elem name="name" desc="description">
<subelem name="name3" desc="description3" number="3"/>
<subelem name="name5" desc="description5" number="5"/>
</elem>
xml :
elem.Attributes.name = 'name';
elem.Attributes.desc = 'description';
elem.subelem{1}.Attributes.name = 'name3';
elem.subelem{1}.Attributes.desc = 'description3';
elem.subelem{1}.Attributes.number = '3';
elem.subelem{2}.Attributes.name = 'name5';
elem.subelem{2}.Attributes.desc = 'description5';
elem.subelem{2}.Attributes.number = '3';
Thomas Marullo (view profile)
What format does the struct have to be? Seems that it breaks if there are nested structures.
Herve Demezil (view profile)
To fix the bug with matlab r2016a replace line 166 in function "val2str()":
str = [];
by
str = '';
I've tried and it seems to fix it
Herve Demezil (view profile)
Did you fix the bug?
Override (view profile)
xmlwrite.m crashes at Line 82 in R2016a
The reason could be the "new" Java version in combination with JAXP (which is used by MATLAB):
http://stackoverflow.com/questions/21393323/jaxb-marshaller-throwing-nullpointerexception-when-upgrading-from-java-6-to-java
Amos (view profile)
struct2xml bombs with a Java exception in R2016a, if the structure has empty entries. The problem did not occur in earlier MATLAB versions.
Can someone please fix that?
superaga (view profile)
Ilya Belevich (view profile)
Markus Fischer (view profile)
Raúl (view profile)
Great script. I don't know why my struct 'S' is not written in a xml file. I'm using the following statement
file = struct2xml(S);
Where 'file' is the xml file where I want to save the struct and S my struct. However, non xml file is created. Can you help me? What am I missing?
Thanks
Romaine Carter (view profile)
Really nice
Fredrik (view profile)
Rody Oldenhuis (view profile)
Graham (view profile)
Thanks! To get it to support logical fields, I broadened the condition of line 172 (val2str):
elseif (isnumeric(val) || islogical(val))
val = num2str(val);
Timo Dörsam (view profile)
Emmanuel Farhi (view profile)
Many thanks. It does work fine for me.
Hugo (view profile)
I have one .mat file and I need to convert it to a .xml file. Can anyone help me how to use the function. I always got an error about the input parameters.
Wouter Falkena (view profile)
Hi Harald,
The reason why the function requires a single field in the main structure is that a properly formatted XML document has a single root element (http://www.w3schools.com/xml/xml_dtd.asp). The only exception to that rule is a more elaborate XML preamble, which is currently not supported by the function.
For the second point, XML files usually have multiple elements with the same name. In order to convert this into a MATLAB structure, an array may be used. This means that isstruct(s.(curfield)) indeed may not work, but in that case
if iscell(s.(curfield))
min(cellfun(@(a) isstruct(a),s.curfield))
end
will tell you if all cells in the array are structures.
I hope this clarifies how to use the function a bit. If you have any more questions feel free to contact me.
Regards,
Wouter
Harald Berndt (view profile)
I had high hopes after reading the reviews, but... "There should be a single field in the main structure" - why? But worse: for an array of struct the call "isstruct(s.(curfield)" crashes because the return value ia an array!
Wouter Falkena (view profile)
Hi Emil,
The function indeed replaces the characters -:. with _ (also see the function help). It should be possible to rewrite the function to replace : with something unique like _colon_ and let struct2xml replace this with :. Let me know if you still need this functionality. The structure names do get longer in that way...
Regards,
Wouter
Emil (view profile)
Great Script... Just one question. I noticed when I loaded an XML with XML2struct it
<?xml version="1.0" encoding="utf-8"?>
<ADE:Recipe xmlns:ADEL
Then export with Struct2XML I get
<?xml version="1.0" encoding="utf-8"?>
<ADE_Recipe xmlns_ADE
The : were replaced with _
It seems to pop up because the Root and Attributes are structs while in MatLab and Matlab won't allow : character for struct.
I'm ok If this doesn't effect the validity of the file. If it does, I'm gong to have to make some modifications :(
Wouter Falkena (view profile)
Thank you Herbert for finding and successfully eradicating this bug. I have uploaded the fixed file to the MATLAB Central.
Herbert Gsenger (view profile)
Great tool. Helped a lot. But I found a little bug. Trying to convert something like:
a.b.Text = '';
b = struct2xml(a) throws an exception because of a bug in val2str(...).
The simple solution is to replace
...
if (isempty(val))
%do nothing
...
by
if (isempty(val))
return;
in function val2str(...)
Wouter Falkena (view profile)
You are correct. However, isspace does not operate on cells. In the latest update I removed the for-loop all together and use isspace on the multi-line string. This is the fastest approach yet. Again, thank you for your support.
T Lohuis (view profile)
Thank you Wouter for keeping the function updated!
Correct me if i'm wrong, but in my test the whitespace approach with isspace is about 40 times faster than regexprep. (i use an very long array, [148701x1 double], values )
Replaced:
str_cell = regexprep(tmp_cell,'[ ]*', ' ');
With:
whitespace=isspace(tmp_cell(:));
nonspace=(whitespace+ [0 whitespace(1:end-1)])~=2;
str_cell = tmp_cell(nonspace);
Wouter Falkena (view profile)
Thank you thijs for bringing this to my attention. The problem lies not in the regexprep, but in the for loop, however. I have changed the for loop to build a cell array of the multiline sting and execute the regexprep only once. From the MATLAB profiler I obtained that your method is already 38% faster. The regexprep using the cell should be 160% faster than before. I will upload the new function today and hopefully it will be available from Mathworks tomorrow. Thanks again for the suggestion!
T Lohuis (view profile)
T Lohuis (view profile)
For longer arrays of values it takes very long processing!, Use this
--
whitespace=isspace(tmp(i,:));
nonspace=(whitespace+ [0 whitespace(1:end-1)])~=2; % Only double whitespaces are removed)
str = [str tmp(i,nonspace) sprintf('\n')]
--
instead off:
--
str = [str regexprep(tmp(i,:),'[ ]*', ' ') sprintf('\n')];
--
Mais (view profile)
very easy to use. thank you very much
Philipp Orth (view profile)
Fast and works like expected for everything I tried up to now (which is not the case for the other Struct<->XML conversions I found at Matlab Central in the last years). Thanks a lot.