sustaining_gazes/matlab_version/AU_training/data extraction/xml_io_tools_2010_11_05/html/xml_tutorial_script.html

2538 lines
128 KiB
HTML

<!DOCTYPE html
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--
This HTML is auto-generated from an M-file.
To make changes, update the M-file and republish this document.
--><title>Tutorial for xml_io_tools Package</title><meta name="generator" content="MATLAB 7.10"><meta name="date" content="2010-11-05"><meta name="m-file" content="xml_tutorial_script"><style type="text/css">
body {
background-color: white;
margin:10px;
}
h1 {
color: #990000;
font-size: x-large;
}
h2 {
color: #990000;
font-size: medium;
}
/* Make the text shrink to fit narrow windows, but not stretch too far in
wide windows. */
p,h1,h2,div.content div {
max-width: 600px;
/* Hack for IE6 */
width: auto !important; width: 600px;
}
pre.codeinput {
background: #EEEEEE;
padding: 10px;
}
@media print {
pre.codeinput {word-wrap:break-word; width:100%;}
}
span.keyword {color: #0000FF}
span.comment {color: #228B22}
span.string {color: #A020F0}
span.untermstring {color: #B20000}
span.syscmd {color: #B28C00}
pre.codeoutput {
color: #666666;
padding: 10px;
}
pre.error {
color: red;
}
p.footer {
text-align: right;
font-size: xx-small;
font-weight: lighter;
font-style: italic;
color: gray;
}
</style></head><body><div class="content"><h1>Tutorial for xml_io_tools Package</h1><!--introduction--><p><b>By Jarek Tuszynski</b></p><p>Package xml_io_tools can read XML files into MATLAB struct and writes MATLAB data types to XML files with help of simple interface to MATLAB's xmlwrite and xmlread functions.</p><p>Two function to simplify reading and writing XML files from MATLAB:</p><div><ul><li>Function xml_read first calls MATLAB's xmlread function and than converts its output ('Document Object Model' tree of Java objects) to tree of MATLAB struct's. The output is in the format of nested structs and cells. In the output data structure field names are based on XML tags.</li></ul></div><div><ul><li>Function xml_write first convert input tree of MATLAB structs and cells and other types to tree of 'Document Object Model' nodes, and then writes resulting object to XML file using MATLAB's xmlwrite function. .</li></ul></div><!--/introduction--><h2>Contents</h2><div><ul><li><a href="#1">This package can:</a></li><li><a href="#2">This package does not:</a></li><li><a href="#3">Change History</a></li><li><a href="#4">Licence</a></li><li><a href="#5">Write XML file based on a Struct using "xml_write"</a></li><li><a href="#6">Read XML file producing a Struct using "xml_read"</a></li><li><a href="#7">"Pref.XmlEngine" flag in "xml_write"</a></li><li><a href="#8">Writing Struct with different type MATLAB arrays</a></li><li><a href="#9">Read Struct with MATLAB arrays</a></li><li><a href="#10">"Pref.StructItem" flag in "xml_write" (controls 1D arrays of structs)</a></li><li><a href="#16">"Pref.CellItem" flag in "xml_write" (controls 1D arrays of cells)</a></li><li><a href="#20">"Pref.NoCells" flag in "xml_read"</a></li><li><a href="#24">"Pref.ItemName" flag in "xml_write" (customize 1D arrays of structs and cells)</a></li><li><a href="#26">"Pref.ItemName" flag in "xml_read"</a></li><li><a href="#28">"Pref.CellItem" flag in "xml_read"</a></li><li><a href="#33">"Pref.CellTable" flag in "xml_write" (controls 2D arrays of cells)</a></li><li><a href="#38">Write 2D cell array in HTML format</a></li><li><a href="#40">"Pref.StructTable" flag in "xml_write" (controls 2D arrays of structs)</a></li><li><a href="#43">"Pref.TableName" flag in "xml_write" (controls encoding tags used for 2D arrays)</a></li><li><a href="#45">"Pref.TableName" flag in "xml_read"</a></li><li><a href="#47">"Pref.Str2Num" flag in xml_read (control conversion to numbers while reading)</a></li><li><a href="#54">"Pref.PreserveSpace" flag in xml_write (control handling of strings with leading/trailing spaces)</a></li><li><a href="#57">"Pref.PreserveSpace" flag in xml_read</a></li><li><a href="#59">Write XML files with ATTRIBUTEs</a></li><li><a href="#61">"Pref.Str2Num" flag in file with ATTRIBUTEs</a></li><li><a href="#67">Write XML files with COMMENTs</a></li><li><a href="#73">Write XML files with PROCESSING_INSTRUCTIONs</a></li><li><a href="#79">Write XML files with CDATA Sections</a></li><li><a href="#81">Write XML files with special characters in TAG names</a></li><li><a href="#85">Write XML files with Namespaces</a></li><li><a href="#87">"Pref.KeepNS" flag in "xml_read"</a></li><li><a href="#89">Read XML files with special node types</a></li><li><a href="#92">"Pref.ReadAttr" flag in "xml_read" (control handling of nodes with attributes)</a></li><li><a href="#93">"Pref.ReadSpec" flag in "xml_read"</a></li><li><a href="#94">"Pref.RootOnly" flag in "xml_read"</a></li><li><a href="#95">"Pref.RootOnly" flag in "xml_write"</a></li><li><a href="#97">"Pref.NumLevels" flag in "xml_read"</a></li><li><a href="#100">Create DOM object based on a Struct using "xml_write"</a></li><li><a href="#102">Convert DOM object to Struct using "xml_read"</a></li><li><a href="#103">Write XML file based on a DOM using "xml_write_xerces"</a></li><li><a href="#104">Write XML to string instead of a file</a></li><li><a href="#105">Write XML file with embedded binary data encoded as Base64 (using java version)</a></li><li><a href="#106">Read XML file with embedded binary data encoded as Base64 (using java version)</a></li><li><a href="#107">Write XML file with embedded binary data encoded as Base64 (simpler version using only matlab code</a></li><li><a href="#108">Read XML file with embedded binary data encoded as Base64 (simpler version using only matlab code</a></li></ul></div><h2>This package can:<a name="1"></a></h2><div><ul><li>Read most XML files, created inside and outside of MATLAB environment, and convert them to MATLAB data structures.</li><li>Write any MATLAB's struct tree to XML file</li><li>Handle XML attributes and special XML nodes like comments, processing instructions and CDATA sections</li><li>Supports base64 encoding and decoding to allow handling embeded binary data</li><li>Be studied, modified, customized, rewritten and used in other packages without any limitations. All code is included and documented. Software is distributed under BSD Licence (included).</li></ul></div><h2>This package does not:<a name="2"></a></h2><div><ul><li>Guarantee to recover the same Matlab objects that were saved. If you need to be able to recover carbon copy of the structure that was saved than you will have to use one of the packages that uses special set of tags saved as xml attributes that help to guide the parsing of XML code. This package does not use those tags.</li><li>Guarantee to work with older versions of MATLAB. Functions do not work with versions of MATLAB prior to 7.1 (26-Jul-2005).</li></ul></div><h2>Change History<a name="3"></a></h2><div><ul><li>2006-11-06 - original version</li><li>2006-11-26 - corrected xml_write to handle writing Matlab's column arrays to xml files. Bug discovered and diagnosed by Kalyan Dutta.</li><li>2006-11-28 - made changes to handle special node types like: COMMENTS and CDATA sections</li><li>2007-03-12 - Writing CDATA sections still did not worked. The problem was diagnosed and fixed by Alberto Amaro. The fix involved rewriting xmlwrite to use Apache Xerces java files directly instead of MATLAB's XMLUtils java class.</li><li>2007-06-21 - Fixed problem reported by Anna Kelbert in Reviews about not writing attributes of ROOT node. Also: added support for Processing Instructions, added support for global text nodes: Processing Instructions and comments, allowed writing tag names with special characters</li><li>2007-07-20 - Added tutorial script file. Extended support for global text nodes. Added more Preference fields.</li><li>2008-01-23 - Fixed problem reported by Anna Krewet of converting dates in format '2007-01-01' to numbers. Improved and added warning messages. Added detection of old Matlab versions incompatible with the library. Expanded documentation.</li><li>2008-06-23 - Fixed problem with writing 1D array reported by Mark Neil. Extended xml_read's Pref.Num2Str to 3 settings (never, smart and always) for better control. Added parameter Pref.KeepNS for keeping or ignoring namespace data when reading. Fixed a bug related to writing 2D cell arrays brought up by Andrej's Mosat review.</li><li>2008-09-11 - Resubmitting last upload - zip file is still old</li><li>2009-02-26 - Small changes. More error handling. More robust in case of large binary objects. Added support for Base64 encoding/decoding of binary objects (using functions by Peter J. Acklam).</li><li>2009-06-26 - changes to xml_read: added CellItem parameter to allow better control of reading files with 'item' notation (see comment by Shlomi); changed try-catch statements so xml_read would work for mablab versions prior to 7.5 (see Thomas Pilutti comment)</li><li>2009-12-03 - added PreserveSpace parameter for contolling empty string handling as suggested by Sebastiaan. Fix suggested by Michael Murphy. Fixed number recognition code as suggested by Yuan Ren.</li><li>2010-05-04 - implemented fixes suggested by Dylan Reynolds from Airbus.</li><li>2010-07-28 - implemented support for 2D arrays of cells and structs suggested by Rodney Behn from MIT Lincoln Laboratory. Also attempted large scale cleanup of xml_write function</li><li>2010-08-18 - minor extension to allow better handling of logical scalars and arrays and function handles suggested by Andreas Richter and others</li><li>2010-09-20 - allow reading and writing of sparse matrices. Improve reading of 1D boolean arrays.</li><li>2010-11-05 - Fix problem with empty cells reported by Richard Cotton; fixed issues with reading boolean arrays reported by Zohar Bar-Yehuda; Improved speed of base64 coding and decoding by switching to java based code.</li></ul></div><h2>Licence<a name="4"></a></h2><p>The package is distributed under BSD License</p><pre class="codeinput">format <span class="string">compact</span>; <span class="comment">% viewing preference</span>
clear <span class="string">variables</span>;
type(<span class="string">'license.txt'</span>)
</pre><pre class="codeoutput">
Copyright (c) 2007, Jaroslaw Tuszynski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre><h2>Write XML file based on a Struct using "xml_write"<a name="5"></a></h2><p>Any MATLAB data struct can be saved to XML file.</p><pre class="codeinput">MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = <span class="string">'Hello World'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><h2>Read XML file producing a Struct using "xml_read"<a name="6"></a></h2><pre class="codeinput">[tree treeName] = xml_read (<span class="string">'test.xml'</span>);
disp([treeName{1} <span class="string">' ='</span>])
gen_object_display(tree)
</pre><pre class="codeoutput">MyTree =
MyNumber: [13]
MyString: 'Hello World'
</pre><h2>"Pref.XmlEngine" flag in "xml_write"<a name="7"></a></h2><p>Occasionaly some operations are performed better by Apache Xerces XML engine than default xmlread function. That is why xml_write provide an option for choosing the underlaying xml engine. Code below performs the same operation as the previous section but using Apache Xerces XML engine. Notice that in this case name of root element was passed as variable and not extracted from the variable name.</p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'TreeOfMine'</span>, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;TreeOfMine&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/TreeOfMine&gt;
</pre><h2>Writing Struct with different type MATLAB arrays<a name="8"></a></h2><pre class="codeinput">MyTree=[];
MyTree.Empty = []; <span class="comment">% Empty variable</span>
MyTree.Num_1x1 = 13; <span class="comment">% simple scalar</span>
MyTree.Vec_1x3 = [1 2 3]; <span class="comment">% horizontal vector</span>
MyTree.Vec_4x1 = [1; 2; 3; 4]; <span class="comment">% vertical vector</span>
MyTree.Mat_2x2 = [1, 2; 3, 4]; <span class="comment">% 2D matrix</span>
MyTree.Cube_3D = reshape(1:8,[2 2 2]); <span class="comment">% 3D array</span>
MyTree.String1 = <span class="string">'[2003 10 30]'</span>; <span class="comment">% number string with [] brackets</span>
MyTree.String2 = <span class="string">' 2003 10 30 '</span>; <span class="comment">% number string without [] brackets</span>
MyTree.Logical_1x1 = false; <span class="comment">% single logical</span>
MyTree.Logical_2x2 = [false, true; true, false]; <span class="comment">% 2D matrix of logicals</span>
MyTree.Logical_Str = <span class="string">'False False True True'</span>;
MyTree.Int_2x2 = uint8([1 2;3 4]); <span class="comment">% 2D matrix of uint8 integers</span>
MyTree.Complex_1x1 = complex(1, 7); <span class="comment">% complex scalar</span>
MyTree.Complex_2x2 = complex([1 2;3 4],[2 2;7 7]); <span class="comment">% 2D matrix of complex numbers</span>
MyTree.Sparse_9x9 = sparse(1:9,1:9,1); <span class="comment">% sparse 9x9 matrix</span>
MyTree.Function = @sum; <span class="comment">% function handle</span>
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;Empty/&gt;
&lt;Num_1x1&gt;13&lt;/Num_1x1&gt;
&lt;Vec_1x3&gt;[1 2 3]&lt;/Vec_1x3&gt;
&lt;Vec_4x1&gt;[1;2;3;4]&lt;/Vec_4x1&gt;
&lt;Mat_2x2&gt;[1 2;3 4]&lt;/Mat_2x2&gt;
&lt;Cube_3D&gt;[1;2;3;4;5;6;7;8]&lt;/Cube_3D&gt;
&lt;String1&gt;[2003 10 30]&lt;/String1&gt;
&lt;String2&gt;2003 10 30&lt;/String2&gt;
&lt;Logical_1x1&gt;[false]&lt;/Logical_1x1&gt;
&lt;Logical_2x2&gt;[false true;true false]&lt;/Logical_2x2&gt;
&lt;Logical_Str&gt;False False True True&lt;/Logical_Str&gt;
&lt;Int_2x2&gt;[uint8([1 2;3 4])]&lt;/Int_2x2&gt;
&lt;Complex_1x1&gt;1+i*7&lt;/Complex_1x1&gt;
&lt;Complex_2x2&gt;[1+i*2 2+i*2;3+i*7 4+i*7]&lt;/Complex_2x2&gt;
&lt;Sparse_9x9&gt;[sparse([1;2;3;4;5;6;7;8;9], [1;2;3;4;5;6;7;8;9], [1;1;1;1;1;1;1;1;1], 9, 9)]&lt;/Sparse_9x9&gt;
&lt;Function&gt;[@sum]&lt;/Function&gt;
&lt;/MyTree&gt;
</pre><h2>Read Struct with MATLAB arrays<a name="9"></a></h2><p>Notice that 'Cube_3D' did not preserve original dimentions</p><pre class="codeinput">[tree treeName] = xml_read (<span class="string">'test.xml'</span>);
disp([treeName{1} <span class="string">' ='</span>])
gen_object_display(tree)
</pre><pre class="codeoutput">MyTree =
Empty: [0x0 double]
Num_1x1: [13]
Vec_1x3: [1 2 3]
Vec_4x1: [4x1 double]
Mat_2x2: [2x2 double]
Cube_3D: [8x1 double]
String1: [2003 10 30]
String2: [2003 10 30]
Logical_1x1: false
Logical_2x2: [2x2 logical]
Logical_Str: [1x4 logical]
Int_2x2: [2x2 double]
Complex_1x1: [1+7i]
Complex_2x2: [2x2 double]
Sparse_9x9: [9x9 double]
Function: [No method to display type]
</pre><h2>"Pref.StructItem" flag in "xml_write" (controls 1D arrays of structs)<a name="10"></a></h2><p><b>Create a simple structure with 1D array of struct's</b></p><pre class="codeinput">MyTree = [];
MyTree.a(1).b = <span class="string">'jack'</span>;
MyTree.a(2).b = <span class="string">'john'</span>;
gen_object_display(MyTree)
</pre><pre class="codeoutput"> a: [1x2 struct]
b: 'jack'
b: 'john'
</pre><p><b>Write XML with "StructItem = true" (default). Notice single 'a' section and multiple 'item' sub-sections. Those subsections are used to store array elements</b></p><pre class="codeinput">wPref.StructItem = true;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,wPref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>)
gen_object_display(xml_read (<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;item&gt;
&lt;b&gt;john&lt;/b&gt;
&lt;/item&gt;
&lt;/a&gt;
&lt;/MyTree&gt;
xml_read output:
a: [2x1 struct]
b: 'jack'
b: 'john'
</pre><p><b>Write XML with "StructItem = false". Notice multiple 'a' sections</b></p><pre class="codeinput">wPref.StructItem = false;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,wPref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>)
gen_object_display(xml_read (<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/a&gt;
&lt;a&gt;
&lt;b&gt;john&lt;/b&gt;
&lt;/a&gt;
&lt;/MyTree&gt;
xml_read output:
a: [2x1 struct]
b: 'jack'
b: 'john'
</pre><p><b>Notice that xml_read function produced the same struct when reading both files</b></p><p><b>Potential problems with "StructItem = true":</b></p><pre class="codeinput">wPref.StructItem = true;
MyTree1 = []; MyTree1.a.b = <span class="string">'jack'</span>;
MyTree2 = []; MyTree2.a(1).b = <span class="string">'jack'</span>;
MyTree3 = []; MyTree3.a(2).b = <span class="string">'jack'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree1, [], wPref); type(<span class="string">'test.xml'</span>);
xml_write(<span class="string">'test.xml'</span>, MyTree2, [], wPref); type(<span class="string">'test.xml'</span>);
xml_write(<span class="string">'test.xml'</span>, MyTree3, [], wPref); type(<span class="string">'test.xml'</span>);
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree1&gt;
&lt;a&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/a&gt;
&lt;/MyTree1&gt;
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree2&gt;
&lt;a&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/a&gt;
&lt;/MyTree2&gt;
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree3&gt;
&lt;a&gt;
&lt;item&gt;
&lt;b/&gt;
&lt;/item&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;/a&gt;
&lt;/MyTree3&gt;
</pre><p><b>Notice that MyTree1 and MyTree2 produce identical files with no 'items', while MyTree2 and MyTree3 produce very different file structures. It was pointed out to me that files produced from MyTree2 and MyTree3 can not belong to the same schema, which can be a problem. The solution is to use cells.</b></p><pre class="codeinput">wPref.CellItem = true;
wPref.NoCells = true;
MyTree2 = []; MyTree2.a{1}.b = <span class="string">'jack'</span>;
MyTree3 = []; MyTree3.a{2}.b = <span class="string">'jack'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree2, [], wPref); type(<span class="string">'test.xml'</span>);
xml_write(<span class="string">'test.xml'</span>, MyTree3, [], wPref); type(<span class="string">'test.xml'</span>);
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree2&gt;
&lt;a&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;/a&gt;
&lt;/MyTree2&gt;
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree3&gt;
&lt;a&gt;
&lt;item/&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;/a&gt;
&lt;/MyTree3&gt;
</pre><h2>"Pref.CellItem" flag in "xml_write" (controls 1D arrays of cells)<a name="16"></a></h2><p><b>Create a simple structure with cell arrays</b></p><pre class="codeinput">MyTree = [];
MyTree.a = {<span class="string">'jack'</span>, <span class="string">'john'</span>};
disp(MyTree)
</pre><pre class="codeoutput"> a: {'jack' 'john'}
</pre><p><b>Write XML with "CellItem = true" (default). Notice single 'a' section and multiple 'item' sections</b></p><pre class="codeinput">Pref=[]; Pref.CellItem = true;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,Pref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>);
disp(xml_read (<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;
&lt;item&gt;jack&lt;/item&gt;
&lt;item&gt;john&lt;/item&gt;
&lt;/a&gt;
&lt;/MyTree&gt;
xml_read output:
a: {'jack' 'john'}
</pre><p><b>Write XML with "CellItem = false". Notice multiple 'a' sections</b></p><pre class="codeinput">Pref=[]; Pref.CellItem = false;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,Pref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>);
disp(xml_read (<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;jack&lt;/a&gt;
&lt;a&gt;john&lt;/a&gt;
&lt;/MyTree&gt;
xml_read output:
a: {'jack' 'john'}
</pre><p><b>Notice that xml_read function produced the same struct when reading both files</b></p><h2>"Pref.NoCells" flag in "xml_read"<a name="20"></a></h2><p><b>Create a cell/struct mixture object</b></p><pre class="codeinput">MyTree = [];
MyTree.a{1}.b = <span class="string">'jack'</span>;
MyTree.a{2}.b = [];
MyTree.a{2}.c = <span class="string">'john'</span>;
gen_object_display(MyTree);
</pre><pre class="codeoutput"> a: [1x2 cell] =
b: 'jack'
b: [0x0 double]
c: 'john'
</pre><p><b>Save it to xml file</b></p><pre class="codeinput">Pref=[]; Pref.CellItem = false;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/a&gt;
&lt;a&gt;
&lt;b/&gt;
&lt;c&gt;john&lt;/c&gt;
&lt;/a&gt;
&lt;/MyTree&gt;
</pre><p><b>Read above file with "Pref.NoCells=true" (default) - output is quite different then input</b> By default program is trying to convert everything to struct's and arrays of structs. In case arrays of structs all the structs in array need to have the same fields, and if they are not than MATLAB creates empty fields.</p><pre class="codeinput">Pref=[]; Pref.NoCells=true;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> a: [2x1 struct]
b: 'jack'
c: [0x0 double]
b: [0x0 double]
c: 'john'
</pre><p><b>Read above file with "Pref.NoCells=false" - now input and output are the same</b> Cell arrays of structs allow structs in array to have different fields.</p><pre class="codeinput">Pref=[]; Pref.NoCells=false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> a: [1x2 cell] =
b: 'jack'
b: [0x0 double]
c: 'john'
</pre><h2>"Pref.ItemName" flag in "xml_write" (customize 1D arrays of structs and cells)<a name="24"></a></h2><p><b>Create a cell/struct mixture object</b></p><pre class="codeinput">MyTree = [];
MyTree.a{1}.b = <span class="string">'jack'</span>;
MyTree.a{2}.c = <span class="string">'john'</span>;
gen_object_display(MyTree);
</pre><pre class="codeoutput"> a: [1x2 cell] =
b: 'jack'
c: 'john'
</pre><p><b>Save it to xml file, using 'item' notation but with different name</b></p><pre class="codeinput">Pref=[];
Pref.CellItem = true;
Pref.ItemName = <span class="string">'MyItem'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;
&lt;MyItem&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/MyItem&gt;
&lt;MyItem&gt;
&lt;c&gt;john&lt;/c&gt;
&lt;/MyItem&gt;
&lt;/a&gt;
&lt;/MyTree&gt;
</pre><h2>"Pref.ItemName" flag in "xml_read"<a name="26"></a></h2><p><b>Read above file with default settings ("Pref.ItemName = 'item'")</b> The results do not match the original structure</p><pre class="codeinput">Pref=[]; Pref.NoCells = false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> a: [1x1 struct]
MyItem: [1x2 cell] =
b: 'jack'
c: 'john'
</pre><p><b>Read above file with "Pref.ItemName = 'MyItem'" - now saved and read MATLAB structures are the same</b></p><pre class="codeinput">Pref=[];
Pref.ItemName = <span class="string">'MyItem'</span>;
Pref.NoCells = false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> a: [1x2 cell] =
b: 'jack'
c: 'john'
</pre><h2>"Pref.CellItem" flag in "xml_read"<a name="28"></a></h2><p>"Pref.ItemName" is used to create xml files with clearly marked arrays "Pref.CellItem" flag in "xml_read" ensures that they are always read as arrays by forcing output to stay in cell format. In cell format s{1} is different than s, while s(1) is indistinguishable from s.</p><p><b>Create a test file</b></p><pre class="codeinput">MyTree = [];
MyTree.a1{1}.b = <span class="string">'jack'</span>; <span class="comment">% a1 - single struct</span>
MyTree.a2{1}.b = <span class="string">'jack'</span>; <span class="comment">% a2 - cell array of structs with the same fields</span>
MyTree.a2{2}.b = <span class="string">'john'</span>;
MyTree.a3{1}.b = <span class="string">'jack'</span>; <span class="comment">% a3 - cell array of structs with the different fields</span>
MyTree.a3{2}.c = <span class="string">'john'</span>;
Pref=[];
Pref.CellItem = true;
Pref.Debug = true;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a1&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;/a1&gt;
&lt;a2&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;item&gt;
&lt;b&gt;john&lt;/b&gt;
&lt;/item&gt;
&lt;/a2&gt;
&lt;a3&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;item&gt;
&lt;c&gt;john&lt;/c&gt;
&lt;/item&gt;
&lt;/a3&gt;
&lt;/MyTree&gt;
</pre><p><b>Read above file with "Pref.CellItem = true" (default)</b> All outputs are in cell format</p><pre class="codeinput">Pref=[];
Pref.NoCells = false; <span class="comment">% allow cell output</span>
Pref.CellItem = true; <span class="comment">% keep 'item' arrays as cells</span>
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> a1: [1x1 cell] =
b: 'jack'
a2: [1x1 cell] =
[1x1 struct] [1x1 struct]
a3: [1x1 cell] =
[1x1 struct] [1x1 struct]
</pre><p><b>Read above file with "Pref.CellItem = false"</b> Outputs format is determined by content</p><pre class="codeinput">Pref=[];
Pref.NoCells = false; <span class="comment">% allow cell output</span>
Pref.CellItem = false; <span class="comment">% allow 'item' arrays to beheave like other fields</span>
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> a1: [1x1 struct]
b: 'jack'
a2: [2x1 struct]
b: 'jack'
b: 'john'
a3: [1x2 cell] =
b: 'jack'
c: 'john'
</pre><p><b>Read above file with "Pref.CellItem = false" and "Pref.NoCells = true"</b> All outputs are in struct format</p><pre class="codeinput">Pref=[];
Pref.NoCells = true; <span class="comment">% don't allow cell output</span>
Pref.CellItem = false; <span class="comment">% allow 'item' arrays to beheave like other fields</span>
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> a1: [1x1 struct]
b: 'jack'
a2: [2x1 struct]
b: 'jack'
b: 'john'
a3: [2x1 struct]
b: 'jack'
c: [0x0 double]
b: [0x0 double]
c: 'john'
</pre><h2>"Pref.CellTable" flag in "xml_write" (controls 2D arrays of cells)<a name="33"></a></h2><p><b>Create a structure with 2D arrays of cells</b></p><pre class="codeinput">MyTree = [];
MyTree.M = {[1,2;3,4], <span class="string">'M12'</span>; struct(<span class="string">'a'</span>,<span class="string">'jack'</span>), {11, <span class="string">'N12'</span>; 21, <span class="string">'N22'</span>}};
gen_object_display(MyTree)
</pre><pre class="codeoutput"> M: [2x2 cell] =
[2x2 double] 'M12'
[1x1 struct] {2x2 cell}
</pre><p><b>Write XML with "CellTable = 'Html" (default). This option mimics use of HTML "tr" and "td" tags to encode 2D tables. Tag names can be changed using TableName parameter (see below)</b></p><pre class="codeinput">wPref = [];
wPref.CellTable = <span class="string">'Html'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,wPref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>)
rPref=[]; rPref.NoCells=false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, rPref))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;M&gt;
&lt;tr&gt;
&lt;td&gt;[1 2;3 4]&lt;/td&gt;
&lt;td&gt;M12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a&gt;jack&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;N12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;N22&lt;/td&gt;
&lt;/tr&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/M&gt;
&lt;/MyTree&gt;
xml_read output:
M: [2x2 cell] =
[2x2 double] 'M12'
[1x1 struct] {2x2 cell}
</pre><p><b>Write XML with "CellTable = 'Vector'".</b> Converts 2D arrays to 1D array and item or regular notation. This option is mostly provided for backward compatibility since this was the behavior in prior verions of the code</p><pre class="codeinput">wPref = [];
wPref.CellTable = <span class="string">'Vector'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,wPref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>)
rPref=[]; rPref.NoCells=false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, rPref))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;M&gt;
&lt;item&gt;[1 2;3 4]&lt;/item&gt;
&lt;item&gt;
&lt;a&gt;jack&lt;/a&gt;
&lt;/item&gt;
&lt;item&gt;M12&lt;/item&gt;
&lt;item&gt;
&lt;item&gt;11&lt;/item&gt;
&lt;item&gt;21&lt;/item&gt;
&lt;item&gt;N12&lt;/item&gt;
&lt;item&gt;N22&lt;/item&gt;
&lt;/item&gt;
&lt;/M&gt;
&lt;/MyTree&gt;
xml_read output:
M: [1x4 cell] =
1 2
3 4
a: 'jack'
M12
[11] [21] 'N12' 'N22'
</pre><p><b>Create a simpler structure without struct's</b></p><pre class="codeinput">MyTree = [];
MyTree.M = {[1,2;3,4], <span class="string">'M12'</span>; <span class="string">'M21'</span>, {11, <span class="string">'N12'</span>; 21, <span class="string">'N22'</span>}};
gen_object_display(MyTree)
</pre><pre class="codeoutput"> M: [2x2 cell] =
[2x2 double] 'M12'
'M21' {2x2 cell}
</pre><p><b>Write XML with "CellTable = 'Matlab". This option encodes tables consisting of numbers, strings and other cell arrays as MATLAB command string. Unlike 'Html' option it does not work if one of the cells is a struct</b></p><pre class="codeinput">wPref = [];
wPref.CellTable = <span class="string">'Matlab'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,wPref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>)
rPref=[]; rPref.NoCells=false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, rPref))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;M&gt;{[1 2;3 4],'M12';'M21',{11,'N12';21,'N22';};}&lt;/M&gt;
&lt;/MyTree&gt;
xml_read output:
M: [2x2 cell] =
[2x2 double] 'M12'
'M21' {2x2 cell}
</pre><h2>Write 2D cell array in HTML format<a name="38"></a></h2><pre class="codeinput">MyTree = [];
MyTree.table.ATTRIBUTE.border=1;
MyTree.table.CONTENT = {<span class="string">'Apples'</span>, <span class="string">'44%'</span>; <span class="string">'Bannanas'</span>, <span class="string">'23%'</span>; <span class="string">'Oranges'</span>, <span class="string">'13%'</span>; <span class="string">'Other'</span>, <span class="string">'10%'</span>};
xml_write(<span class="string">'html/test.html'</span>, MyTree);
type(<span class="string">'html/test.html'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;table border="1"&gt;
&lt;tr&gt;
&lt;td&gt;Apples&lt;/td&gt;
&lt;td&gt;44%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bannanas&lt;/td&gt;
&lt;td&gt;23%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oranges&lt;/td&gt;
&lt;td&gt;13%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/MyTree&gt;
</pre><p>Click on <a href="test.html">test.html</a> to opened this file with a web brouwser</p><h2>"Pref.StructTable" flag in "xml_write" (controls 2D arrays of structs)<a name="40"></a></h2><p><b>Create a simple structure with arrays of struct's</b></p><pre class="codeinput">MyTree = [];
MyTree.a(1,1).b = <span class="string">'jack'</span>;
MyTree.a(1,2).b = <span class="string">'john'</span>;
MyTree.a(2,1).b = <span class="string">'jim'</span>;
MyTree.a(2,2).b = <span class="string">'jill'</span>;
gen_object_display(MyTree)
</pre><pre class="codeoutput"> a: [2x2 struct]
a(1,1) =
b: 'jack'
a(1,2) =
b: 'john'
a(2,1) =
b: 'jim'
a(2,2) =
b: 'jill'
</pre><p><b>Write XML with "StructTable = 'Html" (default). This option mimics use of HTML "tr" and "td" tags to encode 2D tables. Tag names can be changed using TableName parameter (see below)</b></p><pre class="codeinput">wPref = [];
wPref.StructTable = <span class="string">'Html'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,wPref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>)
gen_object_display(xml_read (<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;john&lt;/b&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;jim&lt;/b&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;jill&lt;/b&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/a&gt;
&lt;/MyTree&gt;
xml_read output:
a: [2x2 struct]
a(1,1) =
b: 'jack'
a(1,2) =
b: 'john'
a(2,1) =
b: 'jim'
a(2,2) =
b: 'jill'
</pre><p><b>Write XML with "CellTable = 'Vector'".</b> Converts 2D arrays to 1D array and item or regular notation. This option is mostly provided for backward compatibility since this was the behavior in prior verions of the code</p><pre class="codeinput">wPref = [];
wPref.StructTable = <span class="string">'Vector'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,wPref);
type(<span class="string">'test.xml'</span>)
fprintf(<span class="string">'\nxml_read output:\n'</span>)
gen_object_display(xml_read (<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;a&gt;
&lt;item&gt;
&lt;b&gt;jack&lt;/b&gt;
&lt;/item&gt;
&lt;item&gt;
&lt;b&gt;jim&lt;/b&gt;
&lt;/item&gt;
&lt;item&gt;
&lt;b&gt;john&lt;/b&gt;
&lt;/item&gt;
&lt;item&gt;
&lt;b&gt;jill&lt;/b&gt;
&lt;/item&gt;
&lt;/a&gt;
&lt;/MyTree&gt;
xml_read output:
a: [4x1 struct]
b: 'jack'
b: 'jim'
b: 'john'
b: 'jill'
</pre><h2>"Pref.TableName" flag in "xml_write" (controls encoding tags used for 2D arrays)<a name="43"></a></h2><p><b>Create a cell object</b></p><pre class="codeinput">MyTree = [];
MyTree.M = {[1,2;3,4], <span class="string">'M12'</span>; 21, {11, <span class="string">'N12'</span>; 21, <span class="string">'N22'</span>}};
gen_object_display(MyTree);
</pre><pre class="codeoutput"> M: [2x2 cell] =
[2x2 double] 'M12'
[21] {2x2 cell}
</pre><p><b>Save it to xml file, using 'Html' notation but with different names for rows and cells</b></p><pre class="codeinput">Pref=[]; Pref.TableName = {<span class="string">'row'</span>,<span class="string">'cell'</span>};
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>,Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;M&gt;
&lt;row&gt;
&lt;cell&gt;[1 2;3 4]&lt;/cell&gt;
&lt;cell&gt;M12&lt;/cell&gt;
&lt;/row&gt;
&lt;row&gt;
&lt;cell&gt;21&lt;/cell&gt;
&lt;cell&gt;
&lt;row&gt;
&lt;cell&gt;11&lt;/cell&gt;
&lt;cell&gt;N12&lt;/cell&gt;
&lt;/row&gt;
&lt;row&gt;
&lt;cell&gt;21&lt;/cell&gt;
&lt;cell&gt;N22&lt;/cell&gt;
&lt;/row&gt;
&lt;/cell&gt;
&lt;/row&gt;
&lt;/M&gt;
&lt;/MyTree&gt;
</pre><h2>"Pref.TableName" flag in "xml_read"<a name="45"></a></h2><p><b>Read above file with default settings ("Pref.TableName = {'tr','td'}")</b> The results do not match the original structure</p><pre class="codeinput">Pref=[]; Pref.NoCells = false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> M: [1x1 struct]
row: [2x1 struct]
cell: [1x2 cell] =
1 2
3 4
M12
cell: [1x2 cell] =
21
row: [2x1 struct]
cell: [1x2 cell] =
11
N12
cell: [1x2 cell] =
21
N22
</pre><p><b>Read above file with "Pref.TableName = {'row','cell'}" - now saved and read MATLAB structures are the same</b></p><pre class="codeinput">Pref=[];
Pref.TableName = {<span class="string">'row'</span>,<span class="string">'cell'</span>};
Pref.NoCells = false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> M: [2x2 cell] =
[2x2 double] 'M12'
[21] {2x2 cell}
</pre><h2>"Pref.Str2Num" flag in xml_read (control conversion to numbers while reading)<a name="47"></a></h2><p><b>Create a cell/struct mixture object</b></p><pre class="codeinput">MyTree = [];
MyTree.str = <span class="string">'sphere'</span>;
MyTree.num1 = 123;
MyTree.num2 = <span class="string">'123'</span>;
MyTree.num3 = <span class="string">'[Inf,NaN]'</span>;
MyTree.calc = <span class="string">'1+2+3+4'</span>;
MyTree.func = <span class="string">'sin(pi)/2'</span>;
MyTree.String1 = <span class="string">'[2003 10 30]'</span>;
MyTree.String2 = <span class="string">'2003 10 30'</span>; <span class="comment">% array resembling date</span>
MyTree.ISO8601 = <span class="string">'2003-10-30'</span>; <span class="comment">% date in ISO 8601 format</span>
MyTree.US_date = <span class="string">'2003/10/30'</span>; <span class="comment">% US style date format</span>
MyTree.complex = <span class="string">'2003i-10e-30'</span>; <span class="comment">% complex number resembling a date</span>
gen_object_display(MyTree);
</pre><pre class="codeoutput"> str: 'sphere'
num1: [123]
num2: '123'
num3: '[Inf,NaN]'
calc: '1+2+3+4'
func: 'sin(pi)/2'
String1: '[2003 10 30]'
String2: '2003 10 30'
ISO8601: '2003-10-30'
US_date: '2003/10/30'
complex: '2003i-10e-30'
</pre><p><b>Save it to xml file</b></p><pre class="codeinput">xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;str&gt;sphere&lt;/str&gt;
&lt;num1&gt;123&lt;/num1&gt;
&lt;num2&gt;123&lt;/num2&gt;
&lt;num3&gt;[Inf,NaN]&lt;/num3&gt;
&lt;calc&gt;1+2+3+4&lt;/calc&gt;
&lt;func&gt;sin(pi)/2&lt;/func&gt;
&lt;String1&gt;[2003 10 30]&lt;/String1&gt;
&lt;String2&gt;2003 10 30&lt;/String2&gt;
&lt;ISO8601&gt;2003-10-30&lt;/ISO8601&gt;
&lt;US_date&gt;2003/10/30&lt;/US_date&gt;
&lt;complex&gt;2003i-10e-30&lt;/complex&gt;
&lt;/MyTree&gt;
</pre><p><b>Read above file with default settings</b> ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all strings that look like numbers are converted to numbers, except for strings that are recognized by MATLAB 'datenum' function as dates</p><pre class="codeinput">gen_object_display(xml_read(<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput"> str: 'sphere'
num1: [123]
num2: [123]
num3: [Inf NaN]
calc: [10]
func: 'sin(pi)/2'
String1: [2003 10 30]
String2: [2003 10 30]
ISO8601: '2003-10-30'
US_date: '2003/10/30'
complex: [-1e-029+2003i]
</pre><p><b>Note that all the fields of 'MyTree' can be converted to numbers (even 'sphere') but by default the function is trying to 'judge' if a string should be converted to a number or not</b></p><pre class="codeinput">MyCell = {<span class="string">'sphere'</span>,<span class="string">'1+2+3+4'</span>,<span class="string">'sin(pi)/2'</span>,<span class="string">'2003 10 30'</span>,<span class="string">'2003-10-30'</span>,<span class="string">'2003/10/30'</span>,<span class="string">'2003i-10e-30'</span>};
cellfun(@str2num, MyCell, <span class="string">'UniformOutput'</span>, false)
</pre><pre class="codeoutput">ans =
Columns 1 through 6
[21x21 double] [10] [6.1232e-017] [1x3 double] [1963] [6.6767]
Column 7
[-1.0000e-029 +2.0030e+003i]
</pre><p><b>Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'" to keep all the fields in string format</b></p><pre class="codeinput">Pref=[]; Pref.Str2Num = false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> str: 'sphere'
num1: '123'
num2: '123'
num3: '[Inf,NaN]'
calc: '1+2+3+4'
func: 'sin(pi)/2'
String1: '[2003 10 30]'
String2: '2003 10 30'
ISO8601: '2003-10-30'
US_date: '2003/10/30'
complex: '2003i-10e-30'
</pre><p><b>Read above file with "Pref.Str2Num = always" to convert all strings that look like numbers to numbers</b> note the likelly unintendet conversion of 'ISO8601'</p><pre class="codeinput">Pref=[]; Pref.Str2Num = <span class="string">'always'</span>;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> str: 'sphere'
num1: [123]
num2: [123]
num3: [Inf NaN]
calc: [10]
func: 'sin(pi)/2'
String1: [2003 10 30]
String2: [2003 10 30]
ISO8601: [1963]
US_date: '2003/10/30'
complex: [-1e-029+2003i]
</pre><p><b>Notice that all three settings will produce the same output for "num1" and "num2" and there is no way to reproduce the original "MyTree" structure.</b></p><h2>"Pref.PreserveSpace" flag in xml_write (control handling of strings with leading/trailing spaces)<a name="54"></a></h2><p><b>Create a struct with strings</b></p><pre class="codeinput">MyTree=[];
MyTree.Empty = <span class="string">''</span>;
MyTree.OneSpace = <span class="string">' '</span>;
MyTree.TwoSpaces = <span class="string">' '</span>;
MyTree.String1 = <span class="string">' Hello World '</span>;
</pre><p><b>Write XML with "PreserveSpace = false" (default).</b></p><pre class="codeinput">Pref=[]; Pref.PreserveSpace = false; <span class="comment">% (default setting)</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, [], Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;Empty/&gt;
&lt;OneSpace/&gt;
&lt;TwoSpaces/&gt;
&lt;String1&gt;Hello World&lt;/String1&gt;
&lt;/MyTree&gt;
</pre><p><b>Write XML with "PreserveSpace = true".</b></p><pre class="codeinput">Pref=[]; Pref.PreserveSpace = true;
xml_write(<span class="string">'test.xml'</span>, MyTree, [], Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;Empty/&gt;
&lt;OneSpace&gt; &lt;/OneSpace&gt;
&lt;TwoSpaces&gt; &lt;/TwoSpaces&gt;
&lt;String1&gt; Hello World &lt;/String1&gt;
&lt;/MyTree&gt;
</pre><h2>"Pref.PreserveSpace" flag in xml_read<a name="57"></a></h2><p><b>Read file while using "PreserveSpace = false" (default).</b></p><pre class="codeinput">Pref=[]; Pref.PreserveSpace = false; <span class="comment">% (default setting)</span>
gen_object_display(xml_read(<span class="string">'test.xml'</span>,Pref))
</pre><pre class="codeoutput"> Empty: [0x0 double]
OneSpace: [0x0 double]
TwoSpaces: [0x0 double]
String1: 'Hello World'
</pre><p><b>Read file while using "PreserveSpace = true".</b></p><pre class="codeinput">Pref=[]; Pref.PreserveSpace = true;
gen_object_display(xml_read(<span class="string">'test.xml'</span>,Pref))
</pre><pre class="codeoutput"> Empty: [0x0 double]
OneSpace: ' '
TwoSpaces: ' '
String1: ' Hello World '
</pre><h2>Write XML files with ATTRIBUTEs<a name="59"></a></h2><p>In order to add node attributes a special ATTRIBUTE field is used. ATTRIBUTEs have to be of simple types like numbers or strings (not struct or cells). Attributes are easy to attach to structs nodes like MyTree below.</p><pre class="codeinput">MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = <span class="string">'Hello World'</span>; <span class="comment">% simple case</span>
MyTree.ATTRIBUTE.Num = 2;
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree Num="2"&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p>In case when one needs to attach attributes to nodes which are not structs (for example strings, numbers or calls) then special CONTENT field needs to be used to make the node a struct node.</p><pre class="codeinput">MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString.CONTENT = <span class="string">'Hello World'</span>; <span class="comment">% simple case</span>
MyTree.MyString.ATTRIBUTE.Num = 2;
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString Num="2"&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><h2>"Pref.Str2Num" flag in file with ATTRIBUTEs<a name="61"></a></h2><p><b>Create a cell/struct mixture object</b></p><pre class="codeinput">MyTree = [];
MyTree.X.ATTRIBUTE.str = <span class="string">'sphere'</span>;
MyTree.X.ATTRIBUTE.num1 = 123;
MyTree.X.ATTRIBUTE.num2 = <span class="string">'123'</span>;
MyTree.X.ATTRIBUTE.num3 = <span class="string">'[Inf,NaN]'</span>;
MyTree.X.ATTRIBUTE.calc = <span class="string">'1+2+3+4'</span>;
MyTree.X.ATTRIBUTE.func = <span class="string">'sin(pi)/2'</span>;
MyTree.X.ATTRIBUTE.String1 = <span class="string">'[2003 10 30]'</span>;
MyTree.X.ATTRIBUTE.String2 = <span class="string">'2003 10 30'</span>; <span class="comment">% array resembling date</span>
MyTree.X.ATTRIBUTE.ISO8601 = <span class="string">'2003-10-30'</span>; <span class="comment">% date in ISO 8601 format</span>
MyTree.X.ATTRIBUTE.US_date = <span class="string">'2003/10/30'</span>; <span class="comment">% US style date format</span>
MyTree.X.ATTRIBUTE.complex = <span class="string">'2003i-10e-30'</span>; <span class="comment">% complex number resembling a date</span>
gen_object_display(MyTree);
</pre><pre class="codeoutput"> X: [1x1 struct]
ATTRIBUTE: [1x1 struct]
str: 'sphere'
num1: [123]
num2: '123'
num3: '[Inf,NaN]'
calc: '1+2+3+4'
func: 'sin(pi)/2'
String1: '[2003 10 30]'
String2: '2003 10 30'
ISO8601: '2003-10-30'
US_date: '2003/10/30'
complex: '2003i-10e-30'
</pre><p><b>Save it to xml file</b></p><pre class="codeinput">xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;X ISO8601="2003-10-30" String1="[2003 10 30]" String2="2003 10 30" US_date="2003/10/30" calc="1+2+3+4" complex="2003i-10e-30" func="sin(pi)/2" num1="123" num2="123" num3="[Inf,NaN]" str="sphere"/&gt;
&lt;/MyTree&gt;
</pre><p><b>Read above file with default settings</b> ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all strings that look like numbers are converted to numbers, except for strings that are recognized by MATLAB 'datenum' function as dates</p><pre class="codeinput">gen_object_display(xml_read(<span class="string">'test.xml'</span>))
</pre><pre class="codeoutput"> X: [1x1 struct]
CONTENT: [0x0 double]
ATTRIBUTE: [1x1 struct]
ISO8601: '2003-10-30'
String1: '[2003 10 30]'
String2: '2003 10 30'
US_date: '2003/10/30'
calc: '1+2+3+4'
complex: [-1e-029+2003i]
func: 'sin(pi)/2'
num1: [123]
num2: [123]
num3: '[Inf,NaN]'
str: 'sphere'
</pre><p><b>Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'" to keep all the fields in string format</b></p><pre class="codeinput">Pref=[]; Pref.Str2Num = false;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> X: [1x1 struct]
CONTENT: [0x0 double]
ATTRIBUTE: [1x1 struct]
ISO8601: '2003-10-30'
String1: '[2003 10 30]'
String2: '2003 10 30'
US_date: '2003/10/30'
calc: '1+2+3+4'
complex: '2003i-10e-30'
func: 'sin(pi)/2'
num1: '123'
num2: '123'
num3: '[Inf,NaN]'
str: 'sphere'
</pre><p><b>Read above file with "Pref.Str2Num = always" to convert all strings that look like numbers to numbers</b></p><pre class="codeinput">Pref=[]; Pref.Str2Num = <span class="string">'always'</span>;
gen_object_display(xml_read(<span class="string">'test.xml'</span>, Pref))
</pre><pre class="codeoutput"> X: [1x1 struct]
CONTENT: [0x0 double]
ATTRIBUTE: [1x1 struct]
ISO8601: '2003-10-30'
String1: '[2003 10 30]'
String2: '2003 10 30'
US_date: '2003/10/30'
calc: '1+2+3+4'
complex: [-1e-029+2003i]
func: 'sin(pi)/2'
num1: [123]
num2: [123]
num3: '[Inf,NaN]'
str: 'sphere'
</pre><p><b>Notice that all three settings will produce the same output for "num1" and "num2" and there is no way to reproduce the original "MyTree" structure.</b></p><h2>Write XML files with COMMENTs<a name="67"></a></h2><p>Insertion of Comments is done with help of special COMMENT field. Note that MATLAB's xmlwrite is less readable due to lack of end-of-line characters around comment section.</p><pre class="codeinput">MyTree=[];
MyTree.COMMENT = <span class="string">'This is a comment'</span>;
MyTree.MyNumber = 13;
MyTree.MyString.CONTENT = <span class="string">'Hello World'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;&lt;!--This is a comment--&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Same operation using Apache Xerces XML engine</b> gives the same result</p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;MyTree&gt;
&lt;!--This is a comment--&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Comments in XML top level (method #1)</b> This method uses cell array</p><pre class="codeinput">MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = <span class="string">'Hello World'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, {<span class="string">'MyTree'</span>, [], <span class="string">'This is a global comment'</span>});
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;!--This is a global comment--&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Same operation using Apache Xerces XML engine</b> gives even nicer results.</p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, {<span class="string">'MyTree'</span>, [], <span class="string">'This is a global comment'</span>}, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!--This is a global comment--&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Comments in XML top level (method #2)</b> This method adds an extra top layer to the struct 'tree' and sets "Pref.RootOnly = false", which informs the function about the extra layer. Notice that RootName is also saved as a part of the 'tree', and does not have to be passed in separately.</p><pre class="codeinput">MyTree=[];
MyTree.COMMENT = <span class="string">'This is a global comment'</span>;
MyTree.MyTest.MyNumber = 13;
MyTree.MyTest.MyString = <span class="string">'Hello World'</span>;
Pref=[]; Pref.RootOnly = false;
xml_write(<span class="string">'test.xml'</span>, MyTree, [], Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;!--This is a global comment--&gt;
&lt;MyTest&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTest&gt;
</pre><p><b>Same operation using Apache Xerces XML engine</b></p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
Pref.RootOnly = false;
xml_write(<span class="string">'test.xml'</span>, MyTree, [], Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!--This is a global comment--&gt;
&lt;MyTest&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTest&gt;
</pre><h2>Write XML files with PROCESSING_INSTRUCTIONs<a name="73"></a></h2><p>Insertion of Processing Instructions is done through use of special PROCESSING_INSTRUCTION field, which stores the instruction string. The string has to be in 'target data' format separated by space.</p><pre class="codeinput">MyTree=[];
MyTree.PROCESSING_INSTRUCTION = <span class="string">'xml-stylesheet type="a" href="foo"'</span>;
MyTree.MyNumber = 13;
MyTree.MyString = <span class="string">'Hello World'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;&lt;?xml-stylesheet type="a" href="foo"?&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Same operation using Apache Xerces XML engine</b></p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;MyTree&gt;&lt;?xml-stylesheet type="a" href="foo"?&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>PROCESSING_INSTRUCTIONs in XML top level (method #1)</b> This method uses cell array</p><pre class="codeinput">MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = <span class="string">'Hello World'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, {<span class="string">'MyTree'</span>, <span class="string">'xml-stylesheet type="a" href="foo"'</span>});
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;?xml-stylesheet type="a" href="foo"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Same operation using Apache Xerces XML engine</b></p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, {<span class="string">'MyTree'</span>, <span class="string">'xml-stylesheet type="a" href="foo"'</span>}, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;?xml-stylesheet type="a" href="foo"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>PROCESSING_INSTRUCTIONs in XML top level (method #2)</b> This method adds an extra top layer to the struct 'tree' and sets pref.RootOnly=false, which informs the function about the extra layer. Notice that RootName is also saved as a part of the 'tree', and does not have to be passed in separately.</p><pre class="codeinput">MyTree=[];
MyTree.PROCESSING_INSTRUCTION = <span class="string">'xml-stylesheet type="a" href="foo"'</span>;
MyTree.MyTest.MyNumber = 13;
MyTree.MyTest.MyString = <span class="string">'Hello World'</span>;
Pref=[]; Pref.RootOnly = false;
xml_write(<span class="string">'test.xml'</span>, MyTree, [], Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;?xml-stylesheet type="a" href="foo"?&gt;
&lt;MyTest&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTest&gt;
</pre><p><b>Same operation using Apache Xerces XML engine</b></p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
Pref.RootOnly = false;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;?xml-stylesheet type="a" href="foo"?&gt;
&lt;MyTest&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTest&gt;
</pre><h2>Write XML files with CDATA Sections<a name="79"></a></h2><p>"In an XML document a CDATA (Character DATA) section is a section of element content that is marked for the parser to interpret as only character data, not markup." (from Wikipedia) To insert CDATA Sections one use special CDATA_SECTION field, which stores the instruction string. Note that MATLAB's xmlwrite created wrong xml code for CDATA section</p><pre class="codeinput">MyTree=[];
MyTree.CDATA_SECTION = <span class="string">'&lt;A&gt;txt&lt;/A&gt;'</span>;
MyTree.MyNumber = 13;
MyTree.MyString = <span class="string">'Hello World'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;&amp;lt;A&amp;gt;txt&amp;lt;/A&amp;gt;&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Same operation using Apache Xerces XML engine produces correct results</b></p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;MyTree&gt;&lt;![CDATA[&lt;A&gt;txt&lt;/A&gt;]]&gt;&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><h2>Write XML files with special characters in TAG names<a name="81"></a></h2><p>The input to xml_write requires that all tags one wants in XML document have to be encoded as field names of MATLAB's struct's. Matlab has a lot of restrictions on variable names. This section is about XML tags with names not allowed as MATLAB variables, or more specifically with characters allowed as xml tag names but not allowed as MATLAB variable names. Characters like that can be replaced by their hexadecimal representation just as it is done by genvarname function. Alternative way of writing the first example is:</p><pre class="codeinput">MyTree=[];
MyTree.(<span class="string">'MyNumber'</span>) = 13; <span class="comment">% same as MyTree.MyNumber = 13;</span>
MyTree.MyString.CONTENT = <span class="string">'Hello World'</span>;
MyTree.MyString.ATTRIBUTE.(<span class="string">'Num'</span>) = 2; <span class="comment">% same as MyTree.MyString.ATTRIBUTE.Num = 2;</span>
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString Num="2"&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>This approach fails for some characters like dash '-', colon ':', and international characters.</b></p><pre class="codeinput">MyTree=[];
<span class="keyword">try</span>
MyTree.(<span class="string">'My-Number'</span>) = 13;
MyTree.MyString.CONTENT = <span class="string">'Hello World'</span>;
MyTree.MyString.ATTRIBUTE.(<span class="string">'Num_&ouml;'</span>) = 2;
<span class="keyword">catch</span> <span class="comment">%#ok&lt;CTCH&gt;</span>
err = lasterror; <span class="comment">%#ok&lt;LERR&gt;</span>
disp(err.message);
<span class="keyword">end</span>
</pre><pre class="codeoutput">Invalid field name: 'My-Number'.
</pre><p>It can be overcome by replacing offending characters with their hexadecimal representation. That can be done manually or with use of genvarname function. Note that MATLAB 'type' function does not show correctly '&ouml;' letter in xml file, but opening the file in editor shows that it is correct.</p><pre class="codeinput">MyTree=[];
MyTree.(genvarname(<span class="string">'My-Number'</span>)) = 13;
MyTree.MyString.CONTENT = <span class="string">'Hello World'</span>;
MyTree.MyString.ATTRIBUTE.Num_0xF6 = 2;
gen_object_display(MyTree);
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput"> My0x2DNumber: [13]
MyString: [1x1 struct]
CONTENT: 'Hello World'
ATTRIBUTE: [1x1 struct]
Num_0xF6: [2]
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;My-Number&gt;13&lt;/My-Number&gt;
&lt;MyString Num_&Atilde;&para;="2"&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><p><b>Also two of the characters '-' and ':' can be encoded by a special strings: '_DASH_' and '_COLON_' respectively</b></p><pre class="codeinput">MyTree=[];
MyTree.My_DASH_Number = 13;
MyTree.MyString.CONTENT = <span class="string">'Hello World'</span>;
MyTree.MyString.ATTRIBUTE.Num0xF6 = 2;
xml_write(<span class="string">'test.xml'</span>, MyTree);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;My-Number&gt;13&lt;/My-Number&gt;
&lt;MyString Num&Atilde;&para;="2"&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><h2>Write XML files with Namespaces<a name="85"></a></h2><p>No extra special fields are needed to define XML namespaces, only colon character written using '0x3A' or '_COLON_'. Below is an example of a namespace definition</p><pre class="codeinput">MyTree=[];
MyTree.f_COLON_child.ATTRIBUTE.xmlns_COLON_f = <span class="string">'http://www.foo.com'</span>;
MyTree.f_COLON_child.f_COLON_MyNumber = 13;
MyTree.f_COLON_child.f_COLON_MyString = <span class="string">'Hello World'</span>;
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'MyTree'</span>);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;f:child xmlns:f="http://www.foo.com"&gt;
&lt;f:MyNumber&gt;13&lt;/f:MyNumber&gt;
&lt;f:MyString&gt;Hello World&lt;/f:MyString&gt;
&lt;/f:child&gt;
&lt;/MyTree&gt;
</pre><p><b>Same operation using Apache Xerces XML engine</b></p><pre class="codeinput">Pref=[]; Pref.XmlEngine = <span class="string">'Xerces'</span>; <span class="comment">% use Xerces xml generator directly</span>
xml_write(<span class="string">'test.xml'</span>, MyTree, <span class="string">'f_COLON_MyTree'</span>, Pref);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;f:MyTree&gt;
&lt;f:child xmlns:f="http://www.foo.com"&gt;
&lt;f:MyNumber&gt;13&lt;/f:MyNumber&gt;
&lt;f:MyString&gt;Hello World&lt;/f:MyString&gt;
&lt;/f:child&gt;
&lt;/f:MyTree&gt;
</pre><h2>"Pref.KeepNS" flag in "xml_read"<a name="87"></a></h2><p>Thise option allow keeping or exclusion of namespaces in tag names. By default the namespace data is kept but it produces much longer field names in the output structure. Ignoring namespace will produce more readible output. Perform default read of file with namespace</p><pre class="codeinput">tree = xml_read(<span class="string">'test.xml'</span>);
gen_object_display(tree);
</pre><pre class="codeoutput"> f_COLON_child: [1x1 struct]
f_COLON_MyNumber: [13]
f_COLON_MyString: 'Hello World'
ATTRIBUTE: [1x1 struct]
xmlns_COLON_f: 'http://www.foo.com'
</pre><p>Now the same operation with KeepNS = false.</p><pre class="codeinput">Pref=[]; Pref.KeepNS = false; <span class="comment">% do not read attributes</span>
tree = xml_read(<span class="string">'test.xml'</span>, Pref);
gen_object_display(tree);
</pre><pre class="codeoutput"> child: [1x1 struct]
MyNumber: [13]
MyString: 'Hello World'
ATTRIBUTE: [1x1 struct]
f: 'http://www.foo.com'
</pre><h2>Read XML files with special node types<a name="89"></a></h2><p>Display and read the file, then show the data structure. Note that MATLAB 'type' function shows '&ouml;' letter incorrectly as 'A&para;' in xml file, but opening the file in editor shows that it is correct.</p><pre class="codeinput">fprintf(<span class="string">'Test xml file:\n'</span>);
type(<span class="string">'test_file.xml'</span>)
</pre><pre class="codeoutput">Test xml file:
&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;?xml-stylesheet type="text/css" href="foo.css"?&gt;
&lt;!-- This is a Global Comment --&gt;
&lt;aaa xmlns:xsi="http://www.foo.org"&gt;
&lt;?ProcInst type="local processing instruction"?&gt;
&lt;!-- local comment 1 --&gt;
bbb
&lt;!-- local comment 2 --&gt;
ccc
&lt;matrix bad-name='fff'&gt;
5e3+2*i, Inf
NaN, pi
&lt;/matrix&gt;
&lt;ee_e&gt; ee_e &lt;/ee_e&gt;
&lt;ff-f&gt; ff-f &lt;/ff-f&gt;
&lt;gg&Atilde;&para;g&gt; gg&Atilde;&para;g &lt;/gg&Atilde;&para;g&gt;
&lt;![CDATA[
Here &lt;ddd&gt;xml&lt;/ddd&gt; tags are treated as ...
... text
]]&gt;
&lt;/aaa&gt;
</pre><p>Read only the Root Element (default)</p><pre class="codeinput">[tree GlobalTextNodes] = xml_read(<span class="string">'test_file.xml'</span>);
fprintf(<span class="string">'Global Data (Root name, Global Processing Instructions and Global Comments):\n'</span>);
disp(GlobalTextNodes')
fprintf(<span class="string">'\nStructure read from the file (uncludes COMMENT and CDATA sections):\n'</span>);
gen_object_display(tree);
</pre><pre class="codeoutput">Global Data (Root name, Global Processing Instructions and Global Comments):
'aaa'
'xml-stylesheet type="text/css" href="foo.css"'
'This is a Global Comment'
Structure read from the file (uncludes COMMENT and CDATA sections):
PROCESSING_INSTRUCTION: 'ProcInst type="local processing instruction"'
COMMENT: [1x2 cell] =
local comment 1
local comment 2
CONTENT: [1x2 cell] =
bbb
ccc
matrix: [1x1 struct]
CONTENT: [2x2 double]
ATTRIBUTE: [1x1 struct]
bad_DASH_name: 'fff'
ee_e: 'ee_e'
ff_DASH_f: 'ff-f'
gg0xF6g: 'gg&ouml;g'
CDATA_SECTION: 'Here &lt;ddd&gt;xml&lt;/ddd&gt; tags are treated as ...
... text'
ATTRIBUTE: [1x1 struct]
xmlns_COLON_xsi: 'http://www.foo.org'
</pre><p>Read the whole tree including global Comments and Processing Instructions</p><pre class="codeinput">Pref=[]; Pref.RootOnly = false;
[tree GlobalTextNodes] = xml_read(<span class="string">'test_file.xml'</span>, Pref);
fprintf(<span class="string">'Global Data (Root name, Global Processing Instructions and Global Comments):\n'</span>);
disp(GlobalTextNodes')
fprintf(<span class="string">'\nStructure read from the file (uncludes COMMENT and CDATA sections):\n'</span>);
gen_object_display(tree);
</pre><pre class="codeoutput">Global Data (Root name, Global Processing Instructions and Global Comments):
'aaa'
'xml-stylesheet type="text/css" href="foo.css"'
'This is a Global Comment'
Structure read from the file (uncludes COMMENT and CDATA sections):
PROCESSING_INSTRUCTION: 'xml-stylesheet type="text/css" href="foo.css"'
COMMENT: 'This is a Global Comment'
aaa: [1x1 struct]
PROCESSING_INSTRUCTION: 'ProcInst type="local processing instruction"'
COMMENT: [1x2 cell] =
local comment 1
local comment 2
CONTENT: [1x2 cell] =
bbb
ccc
matrix: [1x1 struct]
CONTENT: [2x2 double]
ATTRIBUTE: [1x1 struct]
bad_DASH_name: 'fff'
ee_e: 'ee_e'
ff_DASH_f: 'ff-f'
gg0xF6g: 'gg&ouml;g'
CDATA_SECTION: 'Here &lt;ddd&gt;xml&lt;/ddd&gt; tags are treated as ...
... text'
ATTRIBUTE: [1x1 struct]
xmlns_COLON_xsi: 'http://www.foo.org'
</pre><h2>"Pref.ReadAttr" flag in "xml_read" (control handling of nodes with attributes)<a name="92"></a></h2><p>Those option allow exclusion of attributes</p><pre class="codeinput">Pref=[]; Pref.ReadAttr = false; <span class="comment">% do not read attributes</span>
tree = xml_read(<span class="string">'test_file.xml'</span>, Pref);
gen_object_display(tree);
</pre><pre class="codeoutput"> PROCESSING_INSTRUCTION: 'ProcInst type="local processing instruction"'
COMMENT: [1x2 cell] =
local comment 1
local comment 2
CONTENT: [1x2 cell] =
bbb
ccc
matrix: [2x2 double]
ee_e: 'ee_e'
ff_DASH_f: 'ff-f'
gg0xF6g: 'gg&ouml;g'
CDATA_SECTION: 'Here &lt;ddd&gt;xml&lt;/ddd&gt; tags are treated as ...
... text'
</pre><h2>"Pref.ReadSpec" flag in "xml_read"<a name="93"></a></h2><p>Those option allow exclusion of special nodes, like comments, processing instructions, CData sections, etc.</p><pre class="codeinput">Pref=[]; Pref.ReadSpec = false; <span class="comment">% do not read special node types</span>
tree = xml_read(<span class="string">'test_file.xml'</span>, Pref);
gen_object_display(tree);
</pre><pre class="codeoutput"> CONTENT: [1x2 cell] =
bbb
ccc
matrix: [1x1 struct]
CONTENT: [2x2 double]
ATTRIBUTE: [1x1 struct]
bad_DASH_name: 'fff'
ee_e: 'ee_e'
ff_DASH_f: 'ff-f'
gg0xF6g: 'gg&ouml;g'
ATTRIBUTE: [1x1 struct]
xmlns_COLON_xsi: 'http://www.foo.org'
</pre><h2>"Pref.RootOnly" flag in "xml_read"<a name="94"></a></h2><p>As it was shown in previous examples RootOnly parameter can be used to capture global (top level) special nodes (like COMMENTs and PROCESSING_INSTRUCTIONs) which are ignored by default</p><pre class="codeinput">Pref=[]; Pref.RootOnly = false; <span class="comment">% do not read special node types</span>
tree = xml_read(<span class="string">'test_file.xml'</span>, Pref);
gen_object_display(tree);
</pre><pre class="codeoutput"> PROCESSING_INSTRUCTION: 'xml-stylesheet type="text/css" href="foo.css"'
COMMENT: 'This is a Global Comment'
aaa: [1x1 struct]
PROCESSING_INSTRUCTION: 'ProcInst type="local processing instruction"'
COMMENT: [1x2 cell] =
local comment 1
local comment 2
CONTENT: [1x2 cell] =
bbb
ccc
matrix: [1x1 struct]
CONTENT: [2x2 double]
ATTRIBUTE: [1x1 struct]
bad_DASH_name: 'fff'
ee_e: 'ee_e'
ff_DASH_f: 'ff-f'
gg0xF6g: 'gg&ouml;g'
CDATA_SECTION: 'Here &lt;ddd&gt;xml&lt;/ddd&gt; tags are treated as ...
... text'
ATTRIBUTE: [1x1 struct]
xmlns_COLON_xsi: 'http://www.foo.org'
</pre><h2>"Pref.RootOnly" flag in "xml_write"<a name="95"></a></h2><p>Writing previously read tree with default "Pref.RootOnly = true" gives wrong output file</p><pre class="codeinput">Pref=[]; Pref.RootOnly = true; <span class="comment">% do not read special node types</span>
xml_write(<span class="string">'test.xml'</span>, tree, [], Pref);
fprintf(<span class="string">'Test xml file:\n'</span>);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">Test xml file:
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;tree&gt;&lt;?xml-stylesheet type="text/css" href="foo.css"?&gt;&lt;!--This is a Global Comment--&gt;
&lt;aaa xmlns:xsi="http://www.foo.org"&gt;&lt;?ProcInst type="local processing instruction"?&gt;&lt;!--local comment 1--&gt;&lt;!--local comment 2--&gt;
&lt;item&gt;bbb&lt;/item&gt;
&lt;item&gt;ccc&lt;/item&gt;
&lt;matrix bad-name="fff"&gt;[5000+i*2 Inf;NaN 3.14159265358979]&lt;/matrix&gt;
&lt;ee_e&gt;ee_e&lt;/ee_e&gt;
&lt;ff-f&gt;ff-f&lt;/ff-f&gt;
&lt;gg&Atilde;&para;g&gt;gg&Atilde;&para;g&lt;/gg&Atilde;&para;g&gt;Here &amp;lt;ddd&amp;gt;xml&amp;lt;/ddd&amp;gt; tags are treated as ...
... text&lt;/aaa&gt;
&lt;/tree&gt;
</pre><p>Writing the same tree with "Pref.RootOnly = false" gives correct output</p><pre class="codeinput">Pref=[]; Pref.RootOnly = false; <span class="comment">% do not read special node types</span>
xml_write(<span class="string">'test.xml'</span>, tree, [], Pref);
fprintf(<span class="string">'Test xml file:\n'</span>);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">Test xml file:
&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;?xml-stylesheet type="text/css" href="foo.css"?&gt;&lt;!--This is a Global Comment--&gt;
&lt;aaa xmlns:xsi="http://www.foo.org"&gt;&lt;?ProcInst type="local processing instruction"?&gt;&lt;!--local comment 1--&gt;&lt;!--local comment 2--&gt;
&lt;item&gt;bbb&lt;/item&gt;
&lt;item&gt;ccc&lt;/item&gt;
&lt;matrix bad-name="fff"&gt;[5000+i*2 Inf;NaN 3.14159265358979]&lt;/matrix&gt;
&lt;ee_e&gt;ee_e&lt;/ee_e&gt;
&lt;ff-f&gt;ff-f&lt;/ff-f&gt;
&lt;gg&Atilde;&para;g&gt;gg&Atilde;&para;g&lt;/gg&Atilde;&para;g&gt;Here &amp;lt;ddd&amp;gt;xml&amp;lt;/ddd&amp;gt; tags are treated as ...
... text&lt;/aaa&gt;
</pre><h2>"Pref.NumLevels" flag in "xml_read"<a name="97"></a></h2><p>This parameter allows user to skip parts of the tree in order to save time and memory. Usefull only in a rare case when a small portion of large XML file is needed.</p><p>Create test tile</p><pre class="codeinput">MyTree = [];
MyTree.Level1 = 1;
MyTree.Level1_.Level2 = 2;
MyTree.Level1_.Level2_.Level3 = 3;
MyTree.Level1_.Level2_.Level3_.Level4 = 4;
xml_write(<span class="string">'test.xml'</span>, MyTree);
fprintf(<span class="string">'Test xml file:\n'</span>);
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">Test xml file:
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;Level1&gt;1&lt;/Level1&gt;
&lt;Level1_&gt;
&lt;Level2&gt;2&lt;/Level2&gt;
&lt;Level2_&gt;
&lt;Level3&gt;3&lt;/Level3&gt;
&lt;Level3_&gt;
&lt;Level4&gt;4&lt;/Level4&gt;
&lt;/Level3_&gt;
&lt;/Level2_&gt;
&lt;/Level1_&gt;
&lt;/MyTree&gt;
</pre><p><b>Use Default ("Pref.NumLevels = infinity") setting</b></p><pre class="codeinput">tree = xml_read(<span class="string">'test.xml'</span>);
gen_object_display(tree);
</pre><pre class="codeoutput"> Level1: [1]
Level1_: [1x1 struct]
Level2: [2]
Level2_: [1x1 struct]
Level3: [3]
Level3_: [1x1 struct]
Level4: [4]
</pre><p><b>Limit the read to only 2 levels</b></p><pre class="codeinput">Pref=[]; Pref.NumLevels = 2;
tree = xml_read(<span class="string">'test.xml'</span>, Pref);
gen_object_display(tree);
</pre><pre class="codeoutput"> Level1: [1]
Level1_: [1x1 struct]
Level2: [2]
Level2_: [0x0 double]
</pre><h2>Create DOM object based on a Struct using "xml_write"<a name="100"></a></h2><p><b>Create Struct tree</b></p><pre class="codeinput">MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = <span class="string">'Hello World'</span>;
</pre><p><b>Convert Struct to DOM object using xml_write</b></p><pre class="codeinput">DOM = xml_write([], MyTree);
xmlwrite(<span class="string">'test.xml'</span>, DOM); <span class="comment">% Save DOM object using MATLAB function</span>
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><h2>Convert DOM object to Struct using "xml_read"<a name="102"></a></h2><pre class="codeinput">DOM = xmlread(<span class="string">'test.xml'</span>); <span class="comment">% Read DOM object using MATLAB function</span>
[tree treeName] = xml_read(DOM); <span class="comment">% Convert DOM object to Struct</span>
disp([treeName{1} <span class="string">' ='</span>])
gen_object_display(tree)
</pre><pre class="codeoutput">MyTree =
MyNumber: [13]
MyString: 'Hello World'
</pre><h2>Write XML file based on a DOM using "xml_write_xerces"<a name="103"></a></h2><pre class="codeinput">xmlwrite_xerces(<span class="string">'test.xml'</span>, DOM); <span class="comment">% Save DOM object using Xerces library</span>
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><h2>Write XML to string instead of a file<a name="104"></a></h2><pre class="codeinput">DOM = xml_write([], MyTree);
str = xmlwrite(DOM);
disp(str)
</pre><pre class="codeoutput">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;MyNumber&gt;13&lt;/MyNumber&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;/MyTree&gt;
</pre><h2>Write XML file with embedded binary data encoded as Base64 (using java version)<a name="105"></a></h2><pre class="codeinput">fid = fopen(<span class="string">'football.jpg'</span>, <span class="string">'rb'</span>);
raw1 = uint8(fread(fid, <span class="string">'uint8'</span>)); <span class="comment">% read image file as a raw binary</span>
fclose(fid);
MyTree=[];
MyTree.Size = 13;
MyTree.MyString = <span class="string">'Hello World'</span>; <span class="comment">% simple case</span>
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = <span class="string">'base64'</span>;
MyTree.MyImage.CONTENT = base64encode(raw1,<span class="string">'java'</span>);<span class="comment">% perform base64 encoding of the binary data</span>
xml_write(<span class="string">'test.xml'</span>, MyTree); <span class="comment">% write xml file</span>
</pre><h2>Read XML file with embedded binary data encoded as Base64 (using java version)<a name="106"></a></h2><pre class="codeinput">tree = xml_read(<span class="string">'test.xml'</span>, Pref); <span class="comment">% read xml file</span>
raw = base64decode(tree.MyImage.CONTENT, <span class="string">''</span>, <span class="string">'java'</span>); <span class="comment">% convert xml image to raw binary</span>
fid = fopen(<span class="string">'MyFootball.jpg'</span>, <span class="string">'wb'</span>);
fwrite(fid, raw, <span class="string">'uint8'</span>); <span class="comment">% dumb the raw binary to the hard disk</span>
fclose(fid);
I = imread(<span class="string">'MyFootball.jpg'</span>); <span class="comment">% read it as an image</span>
imshow(I);
</pre><img vspace="5" hspace="5" src="xml_tutorial_script_01.png" alt=""> <h2>Write XML file with embedded binary data encoded as Base64 (simpler version using only matlab code<a name="107"></a></h2><p>Notice that process of writing to xml stripped all end-of-lie characters from base64 code.</p><pre class="codeinput">isChunked = true; <span class="comment">% break into chunks 76 characters long</span>
url_safe = true; <span class="comment">% 'base64url' encoding</span>
code = base64encode(<span class="string">'license.txt'</span>, <span class="string">'matlab'</span>, isChunked, url_safe);
disp(code)
MyTree=[];
MyTree.Size = 13;
MyTree.MyString = <span class="string">'Hello World'</span>;
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = <span class="string">'base64'</span>;
MyTree.MyImage.CONTENT = code; <span class="comment">% perform base64 encoding of the binary data</span>
xml_write(<span class="string">'test.xml'</span>, MyTree); <span class="comment">% write xml file</span>
type(<span class="string">'test.xml'</span>)
</pre><pre class="codeoutput">Q29weXJpZ2h0IChjKSAyMDA3LCBKYXJvc2xhdyBUdXN6eW5za2kKQWxsIHJpZ2h0cyByZXNlcnZl
ZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdp
dGggb3Igd2l0aG91dCAKbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQg
dGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSAKbWV0OgoKICAgICogUmVkaXN0cmlidXRpb25z
IG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgCiAgICAgIG5v
dGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1l
ci4KICAgICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRo
ZSBhYm92ZSBjb3B5cmlnaHQgCiAgICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMg
YW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiAKICAgICAgdGhlIGRvY3VtZW50YXRpb24g
YW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24KICAg
ICAgClRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFO
RCBDT05UUklCVVRPUlMgIkFTIElTIiAKQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFO
VElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSAKSU1QTElFRCBXQVJSQU5U
SUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBP
U0UgCkFSRSBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIE9XTkVS
IE9SIENPTlRSSUJVVE9SUyBCRSAKTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5D
SURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiAKQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJ
TkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgClNVQlNUSVRVVEUg
R09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJ
TkVTUyAKSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBM
SUFCSUxJVFksIFdIRVRIRVIgSU4gCkNPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JU
IChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIApBUklTSU5HIElOIEFOWSBXQVkg
T1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSAK
UE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCg==
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;MyTree&gt;
&lt;Size&gt;13&lt;/Size&gt;
&lt;MyString&gt;Hello World&lt;/MyString&gt;
&lt;MyImage EncodingMIMEType="base64"&gt;Q29weXJpZ2h0IChjKSAyMDA3LCBKYXJvc2xhdyBUdXN6eW5za2kKQWxsIHJpZ2h0cyByZXNlcnZl ZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdp dGggb3Igd2l0aG91dCAKbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQg dGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSAKbWV0OgoKICAgICogUmVkaXN0cmlidXRpb25z IG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgCiAgICAgIG5v dGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1l ci4KICAgICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRo ZSBhYm92ZSBjb3B5cmlnaHQgCiAgICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMg YW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiAKICAgICAgdGhlIGRvY3VtZW50YXRpb24g YW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24KICAg ICAgClRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFO RCBDT05UUklCVVRPUlMgIkFTIElTIiAKQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFO VElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSAKSU1QTElFRCBXQVJSQU5U SUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBP U0UgCkFSRSBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIE9XTkVS IE9SIENPTlRSSUJVVE9SUyBCRSAKTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5D SURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiAKQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJ TkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgClNVQlNUSVRVVEUg R09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJ TkVTUyAKSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBM SUFCSUxJVFksIFdIRVRIRVIgSU4gCkNPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JU IChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIApBUklTSU5HIElOIEFOWSBXQVkg T1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSAK UE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCg==&lt;/MyImage&gt;
&lt;/MyTree&gt;
</pre><h2>Read XML file with embedded binary data encoded as Base64 (simpler version using only matlab code<a name="108"></a></h2><pre class="codeinput">tree = xml_read(<span class="string">'test.xml'</span>, Pref); <span class="comment">% read xml file</span>
base64decode(tree.MyImage.CONTENT, <span class="string">'license2.txt'</span>, <span class="string">'matlab'</span>); <span class="comment">% save xml image as raw binary</span>
type(<span class="string">'license2.txt'</span>)
</pre><pre class="codeoutput">
Copyright (c) 2007, Jaroslaw Tuszynski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre><p class="footer"><br>
Published with MATLAB&reg; 7.10<br></p></div><!--
##### SOURCE BEGIN #####
%% Tutorial for xml_io_tools Package
% *By Jarek Tuszynski*
%
% Package xml_io_tools can read XML files into MATLAB struct and writes
% MATLAB data types to XML files with help of simple interface to
% MATLAB's xmlwrite and xmlread functions.
%
% Two function to simplify reading and writing XML files from MATLAB:
%
% * Function xml_read first calls MATLAB's xmlread function and than
% converts its output ('Document Object Model' tree of Java objects)
% to tree of MATLAB struct's. The output is in the format of nested
% structs and cells. In the output data structure field names are based on
% XML tags.
%
% * Function xml_write first convert input tree of MATLAB structs and cells
% and other types to tree of 'Document Object Model' nodes, and then writes
% resulting object to XML file using MATLAB's xmlwrite function. .
%
%% This package can:
% * Read most XML files, created inside and outside of MATLAB environment,
% and convert them to MATLAB data structures.
% * Write any MATLAB's struct tree to XML file
% * Handle XML attributes and special XML nodes like comments, processing
% instructions and CDATA sections
% * Supports base64 encoding and decoding to allow handling embeded binary
% data
% * Be studied, modified, customized, rewritten and used in other packages
% without any limitations. All code is included and documented. Software
% is distributed under BSD Licence (included).
%
%% This package does not:
% * Guarantee to recover the same Matlab objects that were saved. If you
% need to be able to recover carbon copy of the structure that was saved
% than you will have to use one of the packages that uses special set of
% tags saved as xml attributes that help to guide the parsing of XML code.
% This package does not use those tags.
% * Guarantee to work with older versions of MATLAB. Functions do not work
% with versions of MATLAB prior to 7.1 (26-Jul-2005).
%
%% Change History
% * 2006-11-06 - original version
% * 2006-11-26 - corrected xml_write to handle writing Matlab's column
% arrays to xml files. Bug discovered and diagnosed by Kalyan Dutta.
% * 2006-11-28 - made changes to handle special node types like:
% COMMENTS and CDATA sections
% * 2007-03-12 - Writing CDATA sections still did not worked. The problem
% was diagnosed and fixed by Alberto Amaro. The fix involved rewriting
% xmlwrite to use Apache Xerces java files directly instead of MATLAB's
% XMLUtils java class.
% * 2007-06-21 - Fixed problem reported by Anna Kelbert in Reviews about
% not writing attributes of ROOT node. Also: added support for Processing
% Instructions, added support for global text nodes: Processing
% Instructions and comments, allowed writing tag names with special
% characters
% * 2007-07-20 - Added tutorial script file. Extended support for global
% text nodes. Added more Preference fields.
% * 2008-01-23 - Fixed problem reported by Anna Krewet of converting dates
% in format '2007-01-01' to numbers. Improved and added warning messages.
% Added detection of old Matlab versions incompatible with the library.
% Expanded documentation.
% * 2008-06-23 - Fixed problem with writing 1D array reported by Mark Neil.
% Extended xml_read's Pref.Num2Str to 3 settings (never, smart and always)
% for better control. Added parameter Pref.KeepNS for keeping or ignoring
% namespace data when reading. Fixed a bug related to writing 2D cell
% arrays brought up by Andrej's Mosat review.
% * 2008-09-11 - Resubmitting last upload - zip file is still old
% * 2009-02-26 - Small changes. More error handling. More robust in case of
% large binary objects. Added support for Base64 encoding/decoding of
% binary objects (using functions by Peter J. Acklam).
% * 2009-06-26 - changes to xml_read: added CellItem parameter to allow
% better control of reading files with 'item' notation (see comment by
% Shlomi); changed try-catch statements so xml_read would work for mablab
% versions prior to 7.5 (see Thomas Pilutti comment)
% * 2009-12-03 - added PreserveSpace parameter for contolling empty string
% handling as suggested by Sebastiaan. Fix suggested by Michael Murphy.
% Fixed number recognition code as suggested by Yuan Ren.
% * 2010-05-04 - implemented fixes suggested by Dylan Reynolds from Airbus.
% * 2010-07-28 - implemented support for 2D arrays of cells and structs
% suggested by Rodney Behn from MIT Lincoln Laboratory. Also attempted
% large scale cleanup of xml_write function
% * 2010-08-18 - minor extension to allow better handling of logical
% scalars and arrays and function handles suggested by Andreas Richter
% and others
% * 2010-09-20 - allow reading and writing of sparse matrices. Improve
% reading of 1D boolean arrays.
% * 2010-11-05 - Fix problem with empty cells reported by Richard Cotton;
% fixed issues with reading boolean arrays reported by Zohar Bar-Yehuda;
% Improved speed of base64 coding and decoding by switching to java based
% code.
%% Licence
% The package is distributed under BSD License
format compact; % viewing preference
clear variables;
type('license.txt')
%% Write XML file based on a Struct using "xml_write"
% Any MATLAB data struct can be saved to XML file.
MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World';
xml_write('test.xml', MyTree);
type('test.xml')
%% Read XML file producing a Struct using "xml_read"
[tree treeName] = xml_read ('test.xml');
disp([treeName{1} ' ='])
gen_object_display(tree)
%% "Pref.XmlEngine" flag in "xml_write"
% Occasionaly some operations are performed better by Apache Xerces XML
% engine than default xmlread function. That is why xml_write provide an
% option for choosing the underlaying xml engine. Code below performs the
% same operation as the previous section but using Apache Xerces XML engine.
% Notice that in this case name of root element
% was passed as variable and not extracted from the variable name.
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
xml_write('test.xml', MyTree, 'TreeOfMine', Pref);
type('test.xml')
%% Writing Struct with different type MATLAB arrays
MyTree=[];
MyTree.Empty = []; % Empty variable
MyTree.Num_1x1 = 13; % simple scalar
MyTree.Vec_1x3 = [1 2 3]; % horizontal vector
MyTree.Vec_4x1 = [1; 2; 3; 4]; % vertical vector
MyTree.Mat_2x2 = [1, 2; 3, 4]; % 2D matrix
MyTree.Cube_3D = reshape(1:8,[2 2 2]); % 3D array
MyTree.String1 = '[2003 10 30]'; % number string with [] brackets
MyTree.String2 = ' 2003 10 30 '; % number string without [] brackets
MyTree.Logical_1x1 = false; % single logical
MyTree.Logical_2x2 = [false, true; true, false]; % 2D matrix of logicals
MyTree.Logical_Str = 'False False True True';
MyTree.Int_2x2 = uint8([1 2;3 4]); % 2D matrix of uint8 integers
MyTree.Complex_1x1 = complex(1, 7); % complex scalar
MyTree.Complex_2x2 = complex([1 2;3 4],[2 2;7 7]); % 2D matrix of complex numbers
MyTree.Sparse_9x9 = sparse(1:9,1:9,1); % sparse 9x9 matrix
MyTree.Function = @sum; % function handle
xml_write('test.xml', MyTree);
type('test.xml')
%% Read Struct with MATLAB arrays
% Notice that 'Cube_3D' did not preserve original dimentions
[tree treeName] = xml_read ('test.xml');
disp([treeName{1} ' ='])
gen_object_display(tree)
%% "Pref.StructItem" flag in "xml_write" (controls 1D arrays of structs)
% *Create a simple structure with 1D array of struct's*
MyTree = [];
MyTree.a(1).b = 'jack';
MyTree.a(2).b = 'john';
gen_object_display(MyTree)
%%
% *Write XML with "StructItem = true" (default). Notice single 'a'
% section and multiple 'item' sub-sections. Those subsections are used
% to store array elements*
wPref.StructItem = true;
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
fprintf('\nxml_read output:\n')
gen_object_display(xml_read ('test.xml'))
%%
% *Write XML with "StructItem = false". Notice multiple 'a' sections*
wPref.StructItem = false;
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
fprintf('\nxml_read output:\n')
gen_object_display(xml_read ('test.xml'))
%%
% *Notice that xml_read function produced the same struct when reading both files*
%%
% *Potential problems with "StructItem = true":*
wPref.StructItem = true;
MyTree1 = []; MyTree1.a.b = 'jack';
MyTree2 = []; MyTree2.a(1).b = 'jack';
MyTree3 = []; MyTree3.a(2).b = 'jack';
xml_write('test.xml', MyTree1, [], wPref); type('test.xml');
xml_write('test.xml', MyTree2, [], wPref); type('test.xml');
xml_write('test.xml', MyTree3, [], wPref); type('test.xml');
%%
% *Notice that MyTree1 and MyTree2 produce identical files with no 'items',
% while MyTree2 and MyTree3 produce very different file structures. It was
% pointed out to me that files produced from MyTree2 and MyTree3 can not
% belong to the same schema, which can be a problem. The solution is to use
% cells.*
wPref.CellItem = true;
wPref.NoCells = true;
MyTree2 = []; MyTree2.a{1}.b = 'jack';
MyTree3 = []; MyTree3.a{2}.b = 'jack';
xml_write('test.xml', MyTree2, [], wPref); type('test.xml');
xml_write('test.xml', MyTree3, [], wPref); type('test.xml');
%% "Pref.CellItem" flag in "xml_write" (controls 1D arrays of cells)
% *Create a simple structure with cell arrays*
MyTree = [];
MyTree.a = {'jack', 'john'};
disp(MyTree)
%%
% *Write XML with "CellItem = true" (default). Notice single 'a'
% section and multiple 'item' sections*
Pref=[]; Pref.CellItem = true;
xml_write('test.xml', MyTree, 'MyTree',Pref);
type('test.xml')
fprintf('\nxml_read output:\n');
disp(xml_read ('test.xml'))
%%
% *Write XML with "CellItem = false". Notice multiple 'a' sections*
Pref=[]; Pref.CellItem = false;
xml_write('test.xml', MyTree, 'MyTree',Pref);
type('test.xml')
fprintf('\nxml_read output:\n');
disp(xml_read ('test.xml'))
%%
% *Notice that xml_read function produced the same struct when reading both files*
%% "Pref.NoCells" flag in "xml_read"
% *Create a cell/struct mixture object*
MyTree = [];
MyTree.a{1}.b = 'jack';
MyTree.a{2}.b = [];
MyTree.a{2}.c = 'john';
gen_object_display(MyTree);
%%
% *Save it to xml file*
Pref=[]; Pref.CellItem = false;
xml_write('test.xml', MyTree, 'MyTree',Pref);
type('test.xml')
%%
% *Read above file with "Pref.NoCells=true" (default) - output is quite different then input*
% By default program is trying to convert everything to struct's and arrays
% of structs. In case arrays of structs all the structs in array need to have the
% same fields, and if they are not than MATLAB creates empty fields.
Pref=[]; Pref.NoCells=true;
gen_object_display(xml_read('test.xml', Pref))
%%
% *Read above file with "Pref.NoCells=false" - now input and output are the same*
% Cell arrays of structs allow structs in array to have different fields.
Pref=[]; Pref.NoCells=false;
gen_object_display(xml_read('test.xml', Pref))
%% "Pref.ItemName" flag in "xml_write" (customize 1D arrays of structs and cells)
% *Create a cell/struct mixture object*
MyTree = [];
MyTree.a{1}.b = 'jack';
MyTree.a{2}.c = 'john';
gen_object_display(MyTree);
%%
% *Save it to xml file, using 'item' notation but with different name*
Pref=[];
Pref.CellItem = true;
Pref.ItemName = 'MyItem';
xml_write('test.xml', MyTree, 'MyTree',Pref);
type('test.xml')
%% "Pref.ItemName" flag in "xml_read"
% *Read above file with default settings ("Pref.ItemName = 'item'")*
% The results do not match the original structure
Pref=[]; Pref.NoCells = false;
gen_object_display(xml_read('test.xml', Pref))
%%
% *Read above file with "Pref.ItemName = 'MyItem'" - now saved and read
% MATLAB structures are the same*
Pref=[];
Pref.ItemName = 'MyItem';
Pref.NoCells = false;
gen_object_display(xml_read('test.xml', Pref))
%% "Pref.CellItem" flag in "xml_read"
% "Pref.ItemName" is used to create xml files with clearly marked arrays
% "Pref.CellItem" flag in "xml_read" ensures that they are always read as
% arrays by forcing output to stay in cell format. In cell format s{1} is
% different than s, while s(1) is indistinguishable from s.
%%
% *Create a test file*
MyTree = [];
MyTree.a1{1}.b = 'jack'; % a1 - single struct
MyTree.a2{1}.b = 'jack'; % a2 - cell array of structs with the same fields
MyTree.a2{2}.b = 'john';
MyTree.a3{1}.b = 'jack'; % a3 - cell array of structs with the different fields
MyTree.a3{2}.c = 'john';
Pref=[];
Pref.CellItem = true;
Pref.Debug = true;
xml_write('test.xml', MyTree, 'MyTree',Pref);
type('test.xml')
%%
% *Read above file with "Pref.CellItem = true" (default)*
% All outputs are in cell format
Pref=[];
Pref.NoCells = false; % allow cell output
Pref.CellItem = true; % keep 'item' arrays as cells
gen_object_display(xml_read('test.xml', Pref))
%%
% *Read above file with "Pref.CellItem = false"*
% Outputs format is determined by content
Pref=[];
Pref.NoCells = false; % allow cell output
Pref.CellItem = false; % allow 'item' arrays to beheave like other fields
gen_object_display(xml_read('test.xml', Pref))
%%
% *Read above file with "Pref.CellItem = false" and "Pref.NoCells = true"*
% All outputs are in struct format
Pref=[];
Pref.NoCells = true; % don't allow cell output
Pref.CellItem = false; % allow 'item' arrays to beheave like other fields
gen_object_display(xml_read('test.xml', Pref))
%% "Pref.CellTable" flag in "xml_write" (controls 2D arrays of cells)
% *Create a structure with 2D arrays of cells*
MyTree = [];
MyTree.M = {[1,2;3,4], 'M12'; struct('a','jack'), {11, 'N12'; 21, 'N22'}};
gen_object_display(MyTree)
%%
% *Write XML with "CellTable = 'Html" (default). This option mimics use of
% HTML "tr" and "td" tags to encode 2D tables. Tag names can
% be changed using TableName parameter (see below)*
wPref = [];
wPref.CellTable = 'Html';
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
fprintf('\nxml_read output:\n')
rPref=[]; rPref.NoCells=false;
gen_object_display(xml_read('test.xml', rPref))
%%
% *Write XML with "CellTable = 'Vector'".*
% Converts 2D arrays to 1D array and item or regular notation. This option
% is mostly provided for backward compatibility since this was the
% behavior in prior verions of the code
wPref = [];
wPref.CellTable = 'Vector';
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
fprintf('\nxml_read output:\n')
rPref=[]; rPref.NoCells=false;
gen_object_display(xml_read('test.xml', rPref))
%%
% *Create a simpler structure without struct's*
MyTree = [];
MyTree.M = {[1,2;3,4], 'M12'; 'M21', {11, 'N12'; 21, 'N22'}};
gen_object_display(MyTree)
%%
% *Write XML with "CellTable = 'Matlab". This option encodes tables
% consisting of numbers, strings and other cell arrays as MATLAB command
% string. Unlike 'Html' option it does not work if one of the cells is
% a struct*
wPref = [];
wPref.CellTable = 'Matlab';
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
fprintf('\nxml_read output:\n')
rPref=[]; rPref.NoCells=false;
gen_object_display(xml_read('test.xml', rPref))
%% Write 2D cell array in HTML format
MyTree = [];
MyTree.table.ATTRIBUTE.border=1;
MyTree.table.CONTENT = {'Apples', '44%'; 'Bannanas', '23%'; 'Oranges', '13%'; 'Other', '10%'};
xml_write('html/test.html', MyTree);
type('html/test.html')
%%
% Click on <test.html> to opened this file with a web brouwser
%% "Pref.StructTable" flag in "xml_write" (controls 2D arrays of structs)
% *Create a simple structure with arrays of struct's*
MyTree = [];
MyTree.a(1,1).b = 'jack';
MyTree.a(1,2).b = 'john';
MyTree.a(2,1).b = 'jim';
MyTree.a(2,2).b = 'jill';
gen_object_display(MyTree)
%%
% *Write XML with "StructTable = 'Html" (default). This option mimics use of
% HTML "tr" and "td" tags to encode 2D tables. Tag names can
% be changed using TableName parameter (see below)*
wPref = [];
wPref.StructTable = 'Html';
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
fprintf('\nxml_read output:\n')
gen_object_display(xml_read ('test.xml'))
%%
% *Write XML with "CellTable = 'Vector'".*
% Converts 2D arrays to 1D array and item or regular notation. This option
% is mostly provided for backward compatibility since this was the
% behavior in prior verions of the code
wPref = [];
wPref.StructTable = 'Vector';
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
fprintf('\nxml_read output:\n')
gen_object_display(xml_read ('test.xml'))
%% "Pref.TableName" flag in "xml_write" (controls encoding tags used for 2D arrays)
% *Create a cell object*
MyTree = [];
MyTree.M = {[1,2;3,4], 'M12'; 21, {11, 'N12'; 21, 'N22'}};
gen_object_display(MyTree);
%%
% *Save it to xml file, using 'Html' notation but with different names for
% rows and cells*
Pref=[]; Pref.TableName = {'row','cell'};
xml_write('test.xml', MyTree, 'MyTree',Pref);
type('test.xml')
%% "Pref.TableName" flag in "xml_read"
% *Read above file with default settings ("Pref.TableName = {'tr','td'}")*
% The results do not match the original structure
Pref=[]; Pref.NoCells = false;
gen_object_display(xml_read('test.xml', Pref))
%%
% *Read above file with "Pref.TableName = {'row','cell'}" - now saved and read
% MATLAB structures are the same*
Pref=[];
Pref.TableName = {'row','cell'};
Pref.NoCells = false;
gen_object_display(xml_read('test.xml', Pref))
%% "Pref.Str2Num" flag in xml_read (control conversion to numbers while reading)
% *Create a cell/struct mixture object*
MyTree = [];
MyTree.str = 'sphere';
MyTree.num1 = 123;
MyTree.num2 = '123';
MyTree.num3 = '[Inf,NaN]';
MyTree.calc = '1+2+3+4';
MyTree.func = 'sin(pi)/2';
MyTree.String1 = '[2003 10 30]';
MyTree.String2 = '2003 10 30'; % array resembling date
MyTree.ISO8601 = '2003-10-30'; % date in ISO 8601 format
MyTree.US_date = '2003/10/30'; % US style date format
MyTree.complex = '2003i-10e-30'; % complex number resembling a date
gen_object_display(MyTree);
%%
% *Save it to xml file*
xml_write('test.xml', MyTree);
type('test.xml')
%%
% *Read above file with default settings*
% ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all
% strings that look like numbers are converted to numbers, except for
% strings that are recognized by MATLAB 'datenum' function as dates
gen_object_display(xml_read('test.xml'))
%%
% *Note that all the fields of 'MyTree' can be converted to numbers (even
% 'sphere') but by default the function is trying to 'judge' if a string
% should be converted to a number or not*
MyCell = {'sphere','1+2+3+4','sin(pi)/2','2003 10 30','2003-10-30','2003/10/30','2003i-10e-30'};
cellfun(@str2num, MyCell, 'UniformOutput', false)
%%
% *Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'"
% to keep all the fields in string format*
Pref=[]; Pref.Str2Num = false;
gen_object_display(xml_read('test.xml', Pref))
%%
% *Read above file with "Pref.Str2Num = always"
% to convert all strings that look like numbers to numbers* note the likelly
% unintendet conversion of 'ISO8601'
Pref=[]; Pref.Str2Num = 'always';
gen_object_display(xml_read('test.xml', Pref))
%%
% *Notice that all three settings will produce the same output for "num1" and
% "num2" and there is no way to reproduce the original "MyTree" structure.*
%% "Pref.PreserveSpace" flag in xml_write (control handling of strings with leading/trailing spaces)
% *Create a struct with strings*
MyTree=[];
MyTree.Empty = '';
MyTree.OneSpace = ' ';
MyTree.TwoSpaces = ' ';
MyTree.String1 = ' Hello World ';
%%
% *Write XML with "PreserveSpace = false" (default).*
Pref=[]; Pref.PreserveSpace = false; % (default setting)
xml_write('test.xml', MyTree, [], Pref);
type('test.xml')
%%
% *Write XML with "PreserveSpace = true".*
Pref=[]; Pref.PreserveSpace = true;
xml_write('test.xml', MyTree, [], Pref);
type('test.xml')
%% "Pref.PreserveSpace" flag in xml_read
% *Read file while using "PreserveSpace = false" (default).*
Pref=[]; Pref.PreserveSpace = false; % (default setting)
gen_object_display(xml_read('test.xml',Pref))
%%
% *Read file while using "PreserveSpace = true".*
Pref=[]; Pref.PreserveSpace = true;
gen_object_display(xml_read('test.xml',Pref))
%% Write XML files with ATTRIBUTEs
% In order to add node attributes a special ATTRIBUTE field is used.
% ATTRIBUTEs have to be of simple types like numbers or strings (not
% struct or cells). Attributes are easy to attach to structs nodes like
% MyTree below.
MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World'; % simple case
MyTree.ATTRIBUTE.Num = 2;
xml_write('test.xml', MyTree);
type('test.xml')
%%
% In case when one needs to attach attributes to nodes which are not
% structs (for example strings, numbers or calls) then special CONTENT
% field needs to be used to make the node a struct node.
MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString.CONTENT = 'Hello World'; % simple case
MyTree.MyString.ATTRIBUTE.Num = 2;
xml_write('test.xml', MyTree);
type('test.xml')
%% "Pref.Str2Num" flag in file with ATTRIBUTEs
% *Create a cell/struct mixture object*
MyTree = [];
MyTree.X.ATTRIBUTE.str = 'sphere';
MyTree.X.ATTRIBUTE.num1 = 123;
MyTree.X.ATTRIBUTE.num2 = '123';
MyTree.X.ATTRIBUTE.num3 = '[Inf,NaN]';
MyTree.X.ATTRIBUTE.calc = '1+2+3+4';
MyTree.X.ATTRIBUTE.func = 'sin(pi)/2';
MyTree.X.ATTRIBUTE.String1 = '[2003 10 30]';
MyTree.X.ATTRIBUTE.String2 = '2003 10 30'; % array resembling date
MyTree.X.ATTRIBUTE.ISO8601 = '2003-10-30'; % date in ISO 8601 format
MyTree.X.ATTRIBUTE.US_date = '2003/10/30'; % US style date format
MyTree.X.ATTRIBUTE.complex = '2003i-10e-30'; % complex number resembling a date
gen_object_display(MyTree);
%%
% *Save it to xml file*
xml_write('test.xml', MyTree);
type('test.xml')
%%
% *Read above file with default settings*
% ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all
% strings that look like numbers are converted to numbers, except for
% strings that are recognized by MATLAB 'datenum' function as dates
gen_object_display(xml_read('test.xml'))
%%
% *Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'"
% to keep all the fields in string format*
Pref=[]; Pref.Str2Num = false;
gen_object_display(xml_read('test.xml', Pref))
%%
% *Read above file with "Pref.Str2Num = always"
% to convert all strings that look like numbers to numbers*
Pref=[]; Pref.Str2Num = 'always';
gen_object_display(xml_read('test.xml', Pref))
%%
% *Notice that all three settings will produce the same output for "num1" and
% "num2" and there is no way to reproduce the original "MyTree" structure.*
%% Write XML files with COMMENTs
% Insertion of Comments is done with help of special COMMENT field.
% Note that MATLAB's xmlwrite is less readable due to lack of end-of-line
% characters around comment section.
MyTree=[];
MyTree.COMMENT = 'This is a comment';
MyTree.MyNumber = 13;
MyTree.MyString.CONTENT = 'Hello World';
xml_write('test.xml', MyTree);
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine*
% gives the same result
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
xml_write('test.xml', MyTree, 'MyTree', Pref);
type('test.xml')
%%
% *Comments in XML top level (method #1)*
% This method uses cell array
MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World';
xml_write('test.xml', MyTree, {'MyTree', [], 'This is a global comment'});
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine*
% gives even nicer results.
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
xml_write('test.xml', MyTree, {'MyTree', [], 'This is a global comment'}, Pref);
type('test.xml')
%%
% *Comments in XML top level (method #2)*
% This method adds an extra top layer to the struct 'tree' and sets
% "Pref.RootOnly = false", which informs the function about the extra
% layer. Notice that RootName is also saved as a part of
% the 'tree', and does not have to be passed in separately.
MyTree=[];
MyTree.COMMENT = 'This is a global comment';
MyTree.MyTest.MyNumber = 13;
MyTree.MyTest.MyString = 'Hello World';
Pref=[]; Pref.RootOnly = false;
xml_write('test.xml', MyTree, [], Pref);
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine*
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
Pref.RootOnly = false;
xml_write('test.xml', MyTree, [], Pref);
type('test.xml')
%% Write XML files with PROCESSING_INSTRUCTIONs
% Insertion of Processing Instructions is done through use of special
% PROCESSING_INSTRUCTION field, which stores the instruction string. The
% string has to be in 'target data' format separated by space.
MyTree=[];
MyTree.PROCESSING_INSTRUCTION = 'xml-stylesheet type="a" href="foo"';
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World';
xml_write('test.xml', MyTree);
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine*
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
xml_write('test.xml', MyTree, 'MyTree', Pref);
type('test.xml')
%%
% *PROCESSING_INSTRUCTIONs in XML top level (method #1)*
% This method uses cell array
MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World';
xml_write('test.xml', MyTree, {'MyTree', 'xml-stylesheet type="a" href="foo"'});
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine*
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
xml_write('test.xml', MyTree, {'MyTree', 'xml-stylesheet type="a" href="foo"'}, Pref);
type('test.xml')
%%
% *PROCESSING_INSTRUCTIONs in XML top level (method #2)*
% This method adds an extra top layer to the struct 'tree' and sets
% pref.RootOnly=false, which informs the function about the extra
% layer. Notice that RootName is also saved as a part of
% the 'tree', and does not have to be passed in separately.
MyTree=[];
MyTree.PROCESSING_INSTRUCTION = 'xml-stylesheet type="a" href="foo"';
MyTree.MyTest.MyNumber = 13;
MyTree.MyTest.MyString = 'Hello World';
Pref=[]; Pref.RootOnly = false;
xml_write('test.xml', MyTree, [], Pref);
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine*
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
Pref.RootOnly = false;
xml_write('test.xml', MyTree, 'MyTree', Pref);
type('test.xml')
%% Write XML files with CDATA Sections
% "In an XML document a CDATA (Character DATA) section is a section of
% element content that is marked for the parser to interpret as only
% character data, not markup." (from Wikipedia)
% To insert CDATA Sections one use special CDATA_SECTION field,
% which stores the instruction string. Note that MATLAB's xmlwrite created
% wrong xml code for CDATA section
MyTree=[];
MyTree.CDATA_SECTION = '<A>txt</A>';
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World';
xml_write('test.xml', MyTree);
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine produces correct results*
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
xml_write('test.xml', MyTree, 'MyTree', Pref);
type('test.xml')
%% Write XML files with special characters in TAG names
% The input to xml_write requires that all tags one wants in XML document
% have to be encoded as field names of MATLAB's struct's. Matlab has a lot
% of restrictions on variable names. This section is about XML tags with
% names not allowed as MATLAB variables, or more specifically with
% characters allowed as xml tag names but not allowed as MATLAB variable
% names. Characters like that can be replaced by their hexadecimal
% representation just as it is done by genvarname function. Alternative way
% of writing the first example is:
MyTree=[];
MyTree.('MyNumber') = 13; % same as MyTree.MyNumber = 13;
MyTree.MyString.CONTENT = 'Hello World';
MyTree.MyString.ATTRIBUTE.('Num') = 2; % same as MyTree.MyString.ATTRIBUTE.Num = 2;
xml_write('test.xml', MyTree);
type('test.xml')
%%
% *This approach fails for some characters like dash '-', colon ':', and
% international characters.*
MyTree=[];
try
MyTree.('My-Number') = 13;
MyTree.MyString.CONTENT = 'Hello World';
MyTree.MyString.ATTRIBUTE.('Num_ö') = 2;
catch %#ok<CTCH>
err = lasterror; %#ok<LERR>
disp(err.message);
end
%%
% It can be overcome by replacing offending characters with their
% hexadecimal representation. That can be done manually or with use of
% genvarname function. Note that MATLAB 'type' function does not show
% correctly 'ö' letter in xml file, but opening the file in editor shows
% that it is correct.
MyTree=[];
MyTree.(genvarname('My-Number')) = 13;
MyTree.MyString.CONTENT = 'Hello World';
MyTree.MyString.ATTRIBUTE.Num_0xF6 = 2;
gen_object_display(MyTree);
xml_write('test.xml', MyTree);
type('test.xml')
%%
% *Also two of the characters '-' and ':' can be encoded by a special strings:
% '_DASH_' and '_COLON_' respectively*
MyTree=[];
MyTree.My_DASH_Number = 13;
MyTree.MyString.CONTENT = 'Hello World';
MyTree.MyString.ATTRIBUTE.Num0xF6 = 2;
xml_write('test.xml', MyTree);
type('test.xml')
%% Write XML files with Namespaces
% No extra special fields are needed to define XML namespaces, only colon
% character written using '0x3A' or '_COLON_'. Below is an
% example of a namespace definition
MyTree=[];
MyTree.f_COLON_child.ATTRIBUTE.xmlns_COLON_f = 'http://www.foo.com';
MyTree.f_COLON_child.f_COLON_MyNumber = 13;
MyTree.f_COLON_child.f_COLON_MyString = 'Hello World';
xml_write('test.xml', MyTree, 'MyTree');
type('test.xml')
%%
% *Same operation using Apache Xerces XML engine*
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
xml_write('test.xml', MyTree, 'f_COLON_MyTree', Pref);
type('test.xml')
%% "Pref.KeepNS" flag in "xml_read"
% Thise option allow keeping or exclusion of namespaces in tag names.
% By default the namespace data is kept but it produces much longer field
% names in the output structure. Ignoring namespace will produce more
% readible output.
% Perform default read of file with namespace
tree = xml_read('test.xml');
gen_object_display(tree);
%%
% Now the same operation with KeepNS = false.
Pref=[]; Pref.KeepNS = false; % do not read attributes
tree = xml_read('test.xml', Pref);
gen_object_display(tree);
%% Read XML files with special node types
% Display and read the file, then show the data structure. Note that
% MATLAB 'type' function shows 'ö' letter incorrectly as 'A¶' in xml file,
% but opening the file in editor shows that it is correct.
fprintf('Test xml file:\n');
type('test_file.xml')
%%
% Read only the Root Element (default)
[tree GlobalTextNodes] = xml_read('test_file.xml');
fprintf('Global Data (Root name, Global Processing Instructions and Global Comments):\n');
disp(GlobalTextNodes')
fprintf('\nStructure read from the file (uncludes COMMENT and CDATA sections):\n');
gen_object_display(tree);
%%
% Read the whole tree including global Comments and Processing Instructions
Pref=[]; Pref.RootOnly = false;
[tree GlobalTextNodes] = xml_read('test_file.xml', Pref);
fprintf('Global Data (Root name, Global Processing Instructions and Global Comments):\n');
disp(GlobalTextNodes')
fprintf('\nStructure read from the file (uncludes COMMENT and CDATA sections):\n');
gen_object_display(tree);
%% "Pref.ReadAttr" flag in "xml_read" (control handling of nodes with attributes)
% Those option allow exclusion of attributes
Pref=[]; Pref.ReadAttr = false; % do not read attributes
tree = xml_read('test_file.xml', Pref);
gen_object_display(tree);
%% "Pref.ReadSpec" flag in "xml_read"
% Those option allow exclusion of special nodes, like
% comments, processing instructions, CData sections, etc.
Pref=[]; Pref.ReadSpec = false; % do not read special node types
tree = xml_read('test_file.xml', Pref);
gen_object_display(tree);
%% "Pref.RootOnly" flag in "xml_read"
% As it was shown in previous examples RootOnly parameter can be used to
% capture global (top level) special nodes (like COMMENTs and
% PROCESSING_INSTRUCTIONs) which are ignored by default
Pref=[]; Pref.RootOnly = false; % do not read special node types
tree = xml_read('test_file.xml', Pref);
gen_object_display(tree);
%% "Pref.RootOnly" flag in "xml_write"
% Writing previously read tree with default "Pref.RootOnly = true" gives
% wrong output file
Pref=[]; Pref.RootOnly = true; % do not read special node types
xml_write('test.xml', tree, [], Pref);
fprintf('Test xml file:\n');
type('test.xml')
%%
% Writing the same tree with "Pref.RootOnly = false" gives correct output
Pref=[]; Pref.RootOnly = false; % do not read special node types
xml_write('test.xml', tree, [], Pref);
fprintf('Test xml file:\n');
type('test.xml')
%% "Pref.NumLevels" flag in "xml_read"
% This parameter allows user to skip parts of the tree in order to save
% time and memory. Usefull only in a rare case when a small portion of
% large XML file is needed.
%
% Create test tile
MyTree = [];
MyTree.Level1 = 1;
MyTree.Level1_.Level2 = 2;
MyTree.Level1_.Level2_.Level3 = 3;
MyTree.Level1_.Level2_.Level3_.Level4 = 4;
xml_write('test.xml', MyTree);
fprintf('Test xml file:\n');
type('test.xml')
%%
% *Use Default ("Pref.NumLevels = infinity") setting*
tree = xml_read('test.xml');
gen_object_display(tree);
%%
% *Limit the read to only 2 levels*
Pref=[]; Pref.NumLevels = 2;
tree = xml_read('test.xml', Pref);
gen_object_display(tree);
%% Create DOM object based on a Struct using "xml_write"
% *Create Struct tree*
MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World';
%%
% *Convert Struct to DOM object using xml_write*
DOM = xml_write([], MyTree);
xmlwrite('test.xml', DOM); % Save DOM object using MATLAB function
type('test.xml')
%% Convert DOM object to Struct using "xml_read"
DOM = xmlread('test.xml'); % Read DOM object using MATLAB function
[tree treeName] = xml_read(DOM); % Convert DOM object to Struct
disp([treeName{1} ' ='])
gen_object_display(tree)
%% Write XML file based on a DOM using "xml_write_xerces"
xmlwrite_xerces('test.xml', DOM); % Save DOM object using Xerces library
type('test.xml')
%% Write XML to string instead of a file
DOM = xml_write([], MyTree);
str = xmlwrite(DOM);
disp(str)
%% Write XML file with embedded binary data encoded as Base64 (using java version)
fid = fopen('football.jpg', 'rb');
raw1 = uint8(fread(fid, 'uint8')); % read image file as a raw binary
fclose(fid);
MyTree=[];
MyTree.Size = 13;
MyTree.MyString = 'Hello World'; % simple case
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = 'base64';
MyTree.MyImage.CONTENT = base64encode(raw1,'java');% perform base64 encoding of the binary data
xml_write('test.xml', MyTree); % write xml file
%% Read XML file with embedded binary data encoded as Base64 (using java version)
tree = xml_read('test.xml', Pref); % read xml file
raw = base64decode(tree.MyImage.CONTENT, '', 'java'); % convert xml image to raw binary
fid = fopen('MyFootball.jpg', 'wb');
fwrite(fid, raw, 'uint8'); % dumb the raw binary to the hard disk
fclose(fid);
I = imread('MyFootball.jpg'); % read it as an image
imshow(I);
%% Write XML file with embedded binary data encoded as Base64 (simpler version using only matlab code
% Notice that process of writing to xml stripped all end-of-lie characters
% from base64 code.
isChunked = true; % break into chunks 76 characters long
url_safe = true; % 'base64url' encoding
code = base64encode('license.txt', 'matlab', isChunked, url_safe);
disp(code)
MyTree=[];
MyTree.Size = 13;
MyTree.MyString = 'Hello World';
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = 'base64';
MyTree.MyImage.CONTENT = code; % perform base64 encoding of the binary data
xml_write('test.xml', MyTree); % write xml file
type('test.xml')
%% Read XML file with embedded binary data encoded as Base64 (simpler version using only matlab code
tree = xml_read('test.xml', Pref); % read xml file
base64decode(tree.MyImage.CONTENT, 'license2.txt', 'matlab'); % save xml image as raw binary
type('license2.txt')
##### SOURCE END #####
--></body></html>