Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents
stylesquare


Warning
titleversion 3.0.0

Please note that this documentation covers version 3.0.0 . There are new features in version 3.2.0  that are not yet covered in this document.



Info
titlesource

Note that this document is based on TeX  based documentation prepared by Thomas Johnson. You can find TeX  file inside GIT  repository of xmllib - inside doc  directory

Code Block
> git clone ssh://git@git.iter.org/lib/xmllib.git
> cd xmllib/doc



What is XMLLIB?

XMLLIB is a library for parsing xml-les in Fortran. This means that it provides subroutines for extracting values from an xml file.

...

Code Block
call xml2eg_free_doc(doc)

The Xpath interface

It is not recommended to do any new implementations using the Xpath interface. For examples of how to use this interface, see the sample code.

The Konz interface

It is not recommended to do any new implementations using the Konz interface. For examples of how to use this interface, see the sample code.

Brief history of XMLLIB versions

The XMLLIB was originally develop by Christian Konz, who wrote the Konz interface within the EFDA-ITM environment, i.e. using CPOs.  An extension to this interface then later written by Michal Owsiak and Denis Kalupin, who provided a routine find_parameter , which greatly simplified the parsing. On top of the find_parameter subroutine, Thomas Jonsson built the Xpath interface to even further simplify the parsing. The final component of the XMLLIB, the xml2eg  interface, was provided by Edmondo Giovannozzi.

All this development was done within the EFDA-ITM environment (later renamed EUROfusion-WPCD) with a dependence on the CPOs. With the development of the ITER IMAS, a branched of the XMLLIB library was developed that provided an IDS based interface.

The most recent step (as of september 2018) in the evolution of XMLLIB  was to develop a version that was completely independent of the IDS  and CPO  data structures. The first version of IDS  and CPO  independent version is based on the ITER git repository and is tagged 3.0.0. Unfortunately, there are versions of XMLLIB, stored in the WPCD svn repository, that have version numbers 3.? that are still dependent on the CPOs.

Switching to version 3.0.0, independent of IDSs and CPOs

The 3.0.0 version of XMLLIB is independent of both the IDSs and CPOs. Earlier version of XMLLIB include all git-versions with version number below 3.0.0 (dependent on the IDSs) and all version stored in the WPCD svn repository (dependent on the CPOs). Here follows instructions for how to switch from the IDS or CPO dependent to version 3.0.0.

Real and integer precision

In IDS and CPO dependent versions of XMLLIB all subroutines use real and integer precision, as well as string lengths, defined within the IDS and CPO definitions. In order to move to a dataversion independent XMLLIB these types have been replaced by types defined within the XMLLIB module xmllib_types. The translations between declarations within different XMLLIB version is provided in the table below.


IDSCPOXMLLIB 3.0.0
Moduleids_schema euitm_schemas xmllib_types 
Integerinteger(ids_int) integer(itm_i4) integer(int4) 
Floatreal(ids_real) real(euitm_r8) real(r8) 
Stringscharacter(132) character(ids_string_length) character(132) 

Reading XML information from file

XML data can be read from file in two ways, using fill_param, or file2buffer. While the latter has always been independent of the CPOs and IDSs, the latter used to be CPO/IDS dependent. The typical usage of fill_param in an IDS environment is as follows:

Code Block
use ids_schemas, only: ids_parameters_input
use xml_file_reader, only: fill_param
type(ids_parameters_input) :: param
call fill_param( param, 'input.xml' , 'input.xsd' , 'input_default.xml' )

The corresponding usage in a CPO environment is:

Code Block
use euitm_schemas, only: type_param
use xml_file_reader, only: fill_param
type(type_param) :: param
call fill_param( param, 'input.xml' , 'input.xsd' , 'input_default.xml' )

The corresponding usage in XMLLIB 3.0.0 environment is:

Code Block
use xml_file_reader, only: fill_param
character(132), pointer :: param_xml(:)     => NULL()
character(132), pointer :: param_xsd(:)     => NULL()
character(132), pointer :: param_default(:) => NULL()
call fill_param( param_xml  ,  param_xsd  ,  param_default , &
                'input.xml' , 'input.xsd' , 'input_default.xml' )

Parsing XML data

The xml2eg interface for parsing data is already completely independent of the IDSs and the CPOs. The Xpath and Konz interfaces for parsing data depend on the IDSs and the CPOs in only one place, in the call to imas_xml_parse  and euitm_xml_parse, respectively. Such calls using an IDS dependent version may read

Code Block
use ids_schemas, only: type_parameters_input
use imas_xml_parser, only: tree, imas_xml_parse
type (type_param), intent(in) :: code_parameters
type(tree) :: parameter_list
call euitm_xml_parse(code_parameters, 0, parameter_list)


The corresponding call in a CPO dependent version is

Code Block
use euitm_schemas, only: type_param
use euitm_xml_parser, only: tree, euitm_xml_parse
type (type_param), intent(in) :: code_parameters
type(tree) :: parameter_list
call euitm_xml_parse(code_parameters, 0, parameter_list)


In XMLLIB 3.0.0 the corresponding call is

Code Block
use xmllib_parser, only: tree, xmllib_parse
character(132), pointer :: param_xml(:)
character(132), pointer :: param_xsd(:)
character(132), pointer :: param_default(:)
type(tree) :: parameter_list
call xmllib_parse(param_xml, param_xsd, param_default, 0, parameter_list)

Examples

The following examples are taken from the directory examples  inside: ssh://git@git.iter.org/lib/xmllib.git.

Example 1 for the xml2eg interface

The file data.xml 

Code Block
<parameters>
  <some_int> 13 </some_int>
  <some_real> 21.00 </some_real>
  <myfamily>
    <dad>
      <age>50</age>
      <name>Steve</name>
    </dad>
    <mum>
      <age>48</age>
      <name>Eve</name>
    </mum>
  </myfamily>
  <anotherfamily>
    <dad>
      <age>30</age>
      <name>Knut</name>
    </dad>
    <mum>
      <age>33</age>
      <name>Anna</name>
    </mum>
  </anotherfamily>
</parameters>

The file data.xsd




Code Block
<?xml version="1.0" encoding="UTF-8"?>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
	   elementFormDefault="qualified">
   <xs:annotation>
     <xs:documentation>Code parameters for Nuclearsim 
                     (nuclear reaction rates for thermal plasmas)</xs:documentation>
   </xs:annotation>
   <xs:element name="parameters">
     <xs:complexType>
       <xs:all>
         <xs:element name="some_int" type="xs:integer"/>
         <xs:element name="some_real" type="xs:float"/>
         <xs:element name="myfamily" type="family"/>
         <xs:element name="anotherfamily" type="family"/>
       </xs:all>
     </xs:complexType>
   </xs:element>
   <xs:complexType name="family">
     <xs:all>
       <xs:element name="dad" type="person"/>
       <xs:element name="mum" type="person"/>
     </xs:all>
   </xs:complexType>
   <xs:complexType name="person">
     <xs:all>
       <xs:element name="age" type="xs:integer"/>
       <xs:element name="name" type="xs:string"/>
     </xs:all>
   </xs:complexType>
 </xs:schema>




The file sample.f90 

Code Block
program sample

  use f90_file_reader, only: file2buffer
  use xml2eg_mdl, only: xml2eg_parse_memory, xml2eg_get, &
       type_xml2eg_document, xml2eg_free_doc

  implicit none

  type(type_xml2eg_document) :: doc
  character(len=132), pointer :: buffer(:)

  character(30) :: str
  character(30) :: name
  integer :: test_int
  real(8) :: test_real
  integer :: io_unit = 1
  logical :: errorflag

  ! Here we read the xml-file and the schema from file. 
  ! In ITM codes this call is typically done outside the actor, in the wrapper.
  ! The output from the call is the codeparam structure, which is the one 
  ! used as input to ITM actors.
  call file2buffer('data.xml', io_unit, buffer)

  ! This call translated (parses) the xml data, stored in the string 
  ! codeparam%parameters, into the DOM format used by libxml2.
  ! The output is the DOM document "dom".
  call xml2eg_parse_memory( buffer , doc )

  ! Below fetch data fields from the DOM document using the xml2eg_get,  
  ! which is overloads reading routines for strings, reals, doubles and integers, 
  ! as well as vectors of reals, doubles and integers.
  call xml2eg_get(doc , 'some_int' , test_int)
  write(0,*)'First we read a single integer:',test_int

  call xml2eg_get(doc , 'some_real' , test_real)
  write(0,*)'...and a single real:',test_real

  write(0,*)''
  write(0,*)'Next lets test reading structured data, here using multiple ', &
     'instances of a "family" type:'
  call xml2eg_get(doc , 'myfamily/dad/name' , name)
  write(0,*)'  myfamily/dad/name=',name

  call xml2eg_get(doc , 'myfamily/dad/age' , test_int)
  write(0,*)'  myfamily/dad/age=',test_int

  call xml2eg_get(doc , 'myfamily/mum/name' , name)
  write(0,*)'  myfamily/mum/name=',name

  call xml2eg_get(doc , 'myfamily/mum/age' , test_int)
  write(0,*)'  myfamily/mum/age=',test_int

  call xml2eg_get(doc , 'anotherfamily/dad/name' , name)
  write(0,*)'  anotherfamily/dad/name=',name

  call xml2eg_get(doc , 'anotherfamily/dad/age' , test_int)
  write(0,*)'  anotherfamily/dad/age=',test_int

  call xml2eg_get(doc , 'anotherfamily/mum/name' , name)
  write(0,*)'  anotherfamily/mum/name=',name

  call xml2eg_get(doc , 'anotherfamily/mum/age' , test_int)
  write(0,*)'  anotherfamily/mum/age=',test_int

  write(0,*)
  str='does/not/exists'
  write(0,*)'When attempting reading a path that does not exists in the ', &
       'xml (e.g. "',trim(str),'") then...'
  write(0,*)'    (a) The following error message is generated:'

  call xml2eg_get(doc , str , test_int, errorflag)

  write(0,*)'    (b) for integers you recieve the answer: ',test_int
  write(0,*)'    (c) you may recieve an optional error-flag (logical) with value: ', &
       errorflag

  call xml2eg_free_doc(doc)
  deallocate(buffer)

end program sample

Example 2 for the xml2eg interface

The file actor_example.xml 

Code Block
<parameter>
  <branch_1>
    <my_integer> 153</my_integer>
  </branch_1>
  <branch_2>
    <my_real1>3.14</my_real1>
    <my_real>1.6022e-19</my_real>
  </branch_2>
</parameter>

The file actor_example.f90

Code Block
subroutine actor_example(equilibrium, core_profiles, codeparam)

  use ids_schemas, only: ids_real, ids_int, ids_equilibrium, &
     ids_core_profiles, ids_parameters_input
  use iso_c_binding, only: c_double, c_int

  implicit none

  type(ids_equilibrium), intent(in) :: equilibrium
  type(ids_core_profiles), intent(out) :: core_profiles
  type(ids_parameters_input), intent(in) :: codeparam

  ! Internal
  integer(ids_int) :: value_int       ! IDS compatible variable
  real(ids_real)   :: value_real1     ! IDS compatible variable
  real(ids_real)   :: value_real2     ! IDS compatible variable
  integer(c_int)   :: tmp_value_int   ! XML2EG compatible variable
  real(c_double)   :: tmp_value_real1 ! XML2EG compatible variable
  real(c_double)   :: tmp_value_real2 ! XML2EG compatible variable

  interface
     subroutine assign_codeparam(codeparam_string, value_int, value_real1, value_real2)
       use iso_c_binding, only: c_double, c_int
       character(len=132), pointer :: codeparam_string(:)
       integer(c_int) :: value_int
       real(c_double) :: value_real1
       real(c_double) :: value_real2
     end subroutine assign_codeparam
  end interface

  call assign_codeparam(codeparam%parameters_value, &
       tmp_value_int, tmp_value_real1, tmp_value_real2)
  value_int  = int(  tmp_value_int  , ids_int  )
  value_real1 = real( tmp_value_real1 , ids_real )
  value_real2 = real( tmp_value_real2 , ids_real )

  write(*,*)'Hello!'
  write(*,*)'Integer value, 153_ids_int = ', value_int
  write(*,*)'Real value, 3.14_ids_real          = ', value_real1
  write(*,*)'Real value, 1.6022000E-19_ids_real = ', value_real2

end subroutine actor_example

!------------------------------------------------------------------------------------------

subroutine assign_codeparam(codeparam_string, value_int, value_real1, value_real2)

  use xml2eg_mdl, only: xml2eg_parse_memory, xml2eg_get, type_xml2eg_document, &
      xml2eg_free_doc, set_verbose
  use iso_c_binding, only: c_double, c_int

  implicit none

  ! Input/Output
  character(len=132), pointer :: codeparam_string(:)
  integer(c_int) :: value_int
  real(c_double) :: value_real1
  real(c_double) :: value_real2

  ! Internal
  type(type_xml2eg_document) :: doc

  ! Parse the "codeparam_string". This means that the data is put into a document "doc"
  call xml2eg_parse_memory( codeparam_string  , doc )
  call set_verbose(.TRUE.) ! Only needed if you want to see what's going on in the parsing

  ! Extract data in "doc" at position "branch_1/my_integer" and store it in "value_int"
  call xml2eg_get( doc , 'branch_1/my_integer' , value_int  )

  ! Extract data in "doc" at position "branch_1/my_real1" and store it in "value_real1"
  call xml2eg_get( doc , 'branch_2/my_real1'    , value_real1 )

  ! Extract data in "doc" at position "branch_1/my_real" and store it in "value_real2"
  call xml2eg_get( doc , 'branch_2/my_real'    , value_real2 )

  ! Make sure to clean up after you!!
  ! When calling "xml2eg_parse_memory" memory was allocated in the "doc" object.
  ! This memory is freed by "xml2eg_free_doc(doc)"
  call xml2eg_free_doc(doc)

end subroutine assign_codeparam

The file prog_actor_example.f90 

Code Block
program prog_actor_example

  use ids_schemas, only: ids_equilibrium, ids_core_profiles, ids_parameters_input
  use f90_file_reader, only: file2buffer

  type(ids_equilibrium) :: equilibrium
  type(ids_core_profiles) :: core_profiles
  type(ids_parameters_input) :: codeparam
  integer :: iounit = 1
  character(len=132), pointer :: buffer(:)

  interface
     subroutine actor_example(equilibrium, core_profiles, codeparam)
       use ids_schemas, only: ids_equilibrium, ids_core_profiles, ids_parameters_input
       type(ids_equilibrium), intent(in) :: equilibrium
       type(ids_core_profiles), intent(out) :: core_profiles
       type(ids_parameters_input), intent(in) :: codeparam
     end subroutine actor_example
  end interface

  write(*,*)'Reading actor_example.xml...'
  call file2buffer('actor_example.xml',iounit, codeparam%parameters_value)
  write(*,*)'call actor_example...'
  call actor_example(equilibrium, core_profiles, codeparam)

end program prog_actor_example