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. .

Contents

This package can:

This package can't:

Change History:

Licence

The package is distributed under MIT Licence

format compact; % viewing preference
clear all;
type('MIT_Licence.txt')
Copyright (c) 2007 Jarek Tuszynski

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Save data structure using xml_write

Any MATLAB data struct can be saved to XML file. Notice that 'tree' only defines content of the root element. Its name has to be either passed separately or deduced from the input variable name.

MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString = 'Hello World';
xml_write('test.xml', MyTree);
type('test.xml')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTree>

Using "Pref.XmlEngine" flag in xml_write

Same operation using Apache Xerces XML engine. Notice that in this case root element name 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')
<?xml version="1.0" encoding="UTF-8"?>
<TreeOfMine>
    <MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</TreeOfMine>

Read XML file using xml_read

[tree treeName] = xml_read ('test.xml');
disp([treeName ' ='])
gen_object_display(tree)
TreeOfMine =
    MyNumber: [13]
    MyString: 'Hello World'

Using "Pref.StructItem" flag in xml_write

Create a simple structure with arrays of struct's

MyTree = [];
MyTree.a(1).b = 'jack';
MyTree.a(2).b = 'john';
gen_object_display(MyTree)
    a: [1x2 struct]
       b: 'jack'

       b: 'john'

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')
disp('\nxml_read output:\n')
gen_object_display(xml_read ('test.xml'))
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <a>
      <item>
         <b>jack</b>
      </item>
      <item>
         <b>john</b>
      </item>
   </a>
</MyTree>
\nxml_read output:\n
    a: [1x2 struct]
       b: 'jack'

       b: 'john'

Write XML with "StructItem = false". Notice multiple 'a' sections

wPref.StructItem = false;
xml_write('test.xml', MyTree, 'MyTree',wPref);
type('test.xml')
disp('\nxml_read output:\n')
gen_object_display(xml_read ('test.xml'))
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <a>
      <b>jack</b>
   </a>
   <a>
      <b>john</b>
   </a>
</MyTree>
\nxml_read output:\n
    a: [1x2 struct]
       b: 'jack'

       b: 'john'

Notice that xml_read function produced the same struct when reading both files

Using "Pref.CellItem" flag in xml_write

Create a simple structure with cell arrays

MyTree = [];
MyTree.a = {'jack', 'john'};
disp(MyTree)
    a: {'jack'  'john'}

Write XML with "StructItem = 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'))
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <a>
      <item>jack</item>
      <item>john</item>
   </a>
</MyTree>

xml_read output:
    a: {'jack'  'john'}

Write XML with "StructItem = 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'))
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <a>jack</a>
   <a>john</a>
</MyTree>

xml_read output:
    a: {'jack'  'john'}

Notice that xml_read function produced the same struct when reading both files

Using "Pref.NoCells" flag in xml_read

Create a cell/struct mixture object

MyTree = [];
MyTree.a{1}.b = 'jack';
MyTree.a{2}.c = 'john';
gen_object_display(MyTree);
    a: [1x2 cell] = 
       b: 'jack'
       c: 'john'

Save it to xml file

Pref=[]; Pref.CellItem = false;
xml_write('test.xml', MyTree, 'MyTree',Pref);
type('test.xml')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <a>
      <b>jack</b>
   </a>
   <a>
      <c>john</c>
   </a>
</MyTree>

Read above file with "Pref.NoCells=true" (default) - output is quite different then input

Pref=[]; Pref.NoCells=true;
gen_object_display(xml_read('test.xml', Pref))
    a: [2x1 struct]
       b: 'jack'
       c: [0x0 double]

       b: [0x0 double]
       c: 'john'

Read above file with "Pref.NoCells=false" - now input and output are the same

Pref=[]; Pref.NoCells=false;
gen_object_display(xml_read('test.xml', Pref))
    a: [1x2 cell] = 
       b: 'jack'
       c: 'john'

Using "Pref.ItemName" flag in xml_write and xml_read

Create a cell/struct mixture object

MyTree = [];
MyTree.a{1}.b = 'jack';
MyTree.a{2}.c = 'john';
gen_object_display(MyTree);
    a: [1x2 cell] = 
       b: 'jack'
       c: 'john'

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')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <a>
      <MyItem>
         <b>jack</b>
      </MyItem>
      <MyItem>
         <c>john</c>
      </MyItem>
   </a>
</MyTree>

Read above file with default settings ("Pref.ItemName = 'item'")

Pref=[]; Pref.NoCells  = false;
gen_object_display(xml_read('test.xml', Pref))
    a: [1x1 struct]
       MyItem: [1x2 cell] = 
               b: 'jack'
               c: 'john'

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))
    a: [1x2 cell] = 
       b: 'jack'
       c: 'john'

Write XML files with ATTRIBUTEs

In order to add node attributes a special ATTRIBUTE and CONTENT fields are used.

MyTree=[];
MyTree.MyNumber = 13;
MyTree.MyString.CONTENT = 'Hello World';
MyTree.MyString.ATTRIBUTE.Num = 2;
xml_write('test.xml', MyTree);
type('test.xml')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <MyNumber>13</MyNumber>
   <MyString Num="2">Hello World</MyString>
</MyTree>

Same operation using Apache Xerces XML engine

Pref=[]; Pref.XmlEngine = 'Xerces';  % use Xerces xml generator directly
xml_write('test.xml', MyTree, [], Pref);
type('test.xml')
<?xml version="1.0" encoding="UTF-8"?>
<MyTree>
    <MyNumber>13</MyNumber>
    <MyString Num="2">Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="utf-8"?>
<MyTree><!--This is a comment-->
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="UTF-8"?>
<MyTree>
    <!--This is a comment-->
    <MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="utf-8"?><!--This is a global comment-->
<MyTree>
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="UTF-8"?>
<!--This is a global comment-->
<MyTree>
    <MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="utf-8"?><!--This is a global comment-->
<MyTest>
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTest>

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')
<?xml version="1.0" encoding="UTF-8"?>
<!--This is a global comment-->
<MyTest>
    <MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</MyTest>

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')
<?xml version="1.0" encoding="utf-8"?>
<MyTree><?xml-stylesheet type="a" href="foo"?>
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="UTF-8"?>
<MyTree><?xml-stylesheet type="a" href="foo"?>
    <MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="a" href="foo"?>
<MyTree>
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="a" href="foo"?>
<MyTree>
    <MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="a" href="foo"?>
<MyTest>
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTest>

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')
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="a" href="foo"?>
<MyTest>
    <MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</MyTest>

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')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>&lt;A&gt;txt&lt;/A&gt;<MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="UTF-8"?>
<MyTree><![CDATA[<A>txt</A>]]><MyNumber>13</MyNumber>
    <MyString>Hello World</MyString>
</MyTree>

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;
MyTree.MyString.CONTENT = 'Hello World';
MyTree.MyString.ATTRIBUTE.('Num') = 2;
xml_write('test.xml', MyTree);
type('test.xml')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <MyNumber>13</MyNumber>
   <MyString Num="2">Hello World</MyString>
</MyTree>

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
  err = lasterror;
  disp(err.message);
end
Error using ==> evalin
Invalid field name: 'My-Number'.

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')
    My0x2DNumber: [13]
        MyString: [1x1 struct]
                    CONTENT: 'Hello World'
                  ATTRIBUTE: [1x1 struct]
                             Num_0xF6: [2]

<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <My-Number>13</My-Number>
   <MyString Num_ö="2">Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <My-Number>13</My-Number>
   <MyString Numö="2">Hello World</MyString>
</MyTree>

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')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <f:child xmlns:f="http://www.foo.com">
      <f:MyNumber>13</f:MyNumber>
      <f:MyString>Hello World</f:MyString>
   </f:child>
</MyTree>

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')
<?xml version="1.0" encoding="UTF-8"?>
<MyTree>
    <f:child xmlns:f="http://www.foo.com">
        <f:MyNumber>13</f:MyNumber>
        <f:MyString>Hello World</f:MyString>
    </f:child>
</f:MyTree>

Another example of namespaces which is handled differently by both xml writing methods. Either I have created illegal configuration or both methods have bugs.

MyTree=[];
MyTree.ATTRIBUTE.xmlns_COLON_f = 'http://www.foo.com';
MyTree.f_COLON_MyNumber = 13;
MyTree.f_COLON_MyString = 'Hello World';
xml_write('test.xml', MyTree, 'f_COLON_MyTree');
type('test.xml')
<?xml version="1.0" encoding="utf-8"?>
<f:MyTree xmlns:f="">
   <f:MyNumber>13</f:MyNumber>
   <f:MyString>Hello World</f:MyString>
</f:MyTree>

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')
<?xml version="1.0" encoding="UTF-8"?>
<MyTree xmlns:f="http://www.foo.com">
    <f:MyNumber>13</f:MyNumber>
    <f:MyString>Hello World</f:MyString>
</f:MyTree>

Read xml file with all special node types

Display and read the file, then show the data structure. Note that MATLAB 'type' function does not show correctly 'ö' letter in xml file, but opening the file in editor shows that it is correct.

fprintf('Test xml file:\n');
type('test_file.xml')
Test xml file:

<?xml version="1.0" encoding="utf-8" ?> 
<?xml-stylesheet type="text/css" href="foo.css"?>
<!-- This is a Global Comment -->
<aaa xmlns:xsi="http://www.foo.org">
  <?ProcInst type="local processing instruction"?>
  <!-- local comment 1 -->
  bbb
  <!-- local comment 2 -->
  ccc
  <matrix bad-name='fff'>
    5e3+2*i, Inf
    NaN,     pi
  </matrix>
  <ee_e> ee_e </ee_e>
  <ff-f> ff-f </ff-f>
  <ggög> ggög </ggög>
  <![CDATA[
    Here <ddd>xml</ddd> tags are treated as ...
    ... text
	]]>
</aaa>


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);
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ög'
             CDATA_SECTION: 'Here <ddd>xml</ddd> tags are treated as ...
    ... text'
                 ATTRIBUTE: [1x1 struct]
                            xmlns_COLON_xsi: 'http://www.foo.org'

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);
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ög'
                                     CDATA_SECTION: 'Here <ddd>xml</ddd> tags are treated as ...
    ... text'
                                         ATTRIBUTE: [1x1 struct]
                                                    xmlns_COLON_xsi: 'http://www.foo.org'

Using "Pref.ReadAttr" and "Pref.ReadSpec" flags in xml_read

Those option allow exclusion of attributes or special nodes, like comments, processing instructions, CData sections, etc.

Pref=[];
Pref.ReadAttr = false; % do not read attributes
Pref.ReadSpec = false; % do not read special node types
tree = xml_read('test_file.xml', Pref);
gen_object_display(tree);
      CONTENT: [1x2 cell] = 
               bbb
               ccc
       matrix: [2x2 double]
         ee_e: 'ee_e'
    ff_DASH_f: 'ff-f'
      gg0xF6g: 'ggög'

Working with DOM objects

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')
<?xml version="1.0" encoding="utf-8"?>
<MyTree>
   <MyNumber>13</MyNumber>
   <MyString>Hello World</MyString>
</MyTree>

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 ' ='])
gen_object_display(tree)
MyTree =
    MyNumber: [13]
    MyString: 'Hello World'

Using xmlwrite_xerces function

xmlwrite_xerces('test.xml', MyTree); % Save DOM object using Xerces library
type('test.xml')
No constructor org.apache.xml.serialize.OutputFormat with matching signature found