Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_xml.F90
Go to the documentation of this file.
1 !------------------------------------------------------------------------------
2 ! SELALIB
3 !------------------------------------------------------------------------------
4 ! MODULE: sll_m_xml
5 !
6 ! DESCRIPTION:
12 !------------------------------------------------------------------------------
13 module sll_m_xml
14 
15 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16  implicit none
17 
18  public :: &
21 
22  private
23 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24 
25 !==============================================================================
26 
27  character, parameter :: nl = achar(10) ! newline character
28  integer, parameter :: maxlen = 256 ! max string length
29 
30  !============================================================================
31  ! USER-DEFINED TYPES
32  !============================================================================
33 
34  !----------------------------------------------------------------------------
36  type, abstract :: c_xml_item
37  contains
38  procedure(i_xml_item__write), deferred :: write
39  procedure(i_xml_item__delete), deferred :: delete
40  end type c_xml_item
41 
42  !----------------------------------------------------------------------------
44  type, extends(c_xml_item) :: t_xml_content
45  class(c_xml_item), pointer :: item
46  type(t_xml_content), pointer :: next => null()
47  contains
48  procedure :: write => t_xml_content__write
49  procedure :: delete => t_xml_content__delete
50  procedure :: new_content => t_xml_content__new_content
51  end type
52 
53  !----------------------------------------------------------------------------
56 ! character(len=:), allocatable :: name
57  character(len=maxlen) :: name
58 ! Notice: it could be useful introducing a type for the attvalue,
59 ! representing the formal definition
60 ! AttValue ::= '"' ([^<&"] | Reference)* '"'
61 ! | "'" ([^<&'] | Reference)* "'"
62 ! character(len=:), allocatable :: attvalue
63  character(len=maxlen) :: attvalue
64  contains
65  procedure :: to_string => attribute_name_val_string
66  end type t_xml_attribute
67 
68  !----------------------------------------------------------------------------
70  type, extends(c_xml_item) :: sll_t_xml_element
71 ! character(len=:) , allocatable :: name
72  character(len=maxlen) :: name
73  type(t_xml_attribute), allocatable :: attributes(:)
74  type(t_xml_content), allocatable :: content
75  contains
76  procedure :: write => t_xml_element__write
77  procedure :: delete => t_xml_element__delete
78  procedure :: new_element => t_xml_element__new_element
79  procedure :: add_attribute => t_xml_element__add_attribute
80  procedure :: add_chardata_string => t_xml_element__add_chardata_string
81  procedure :: add_chardata_printer => t_xml_element__add_chardata_printer
82  generic :: add_chardata => add_chardata_string, add_chardata_printer
83  end type sll_t_xml_element
84 
85  !----------------------------------------------------------------------------
88  character(len=maxlen), allocatable :: header_lines(:)
89  type(sll_t_xml_element), allocatable :: root
90  contains
91  procedure :: add_header_line => t_xml_document__add_header_line
92  procedure :: new_element => t_xml_document__new_element
93  procedure :: write => t_xml_document__write
94  procedure :: delete => t_xml_document__delete
95  end type sll_t_xml_document
96 
97  !----------------------------------------------------------------------------
99  type, abstract :: c_text_data_printer
100  contains
101  procedure(i_print_text), deferred, pass(self) :: print_text
102  procedure(i_delete_printer), deferred, pass(self) :: delete
103  end type c_text_data_printer
104 
105  !----------------------------------------------------------------------------
108 ! character(len=:), allocatable :: text
109  character(len=maxlen) :: text
110  contains
111  procedure, pass(self) :: print_text => default_print_text
112  procedure, pass(self) :: delete => default_delete
114 
115  !----------------------------------------------------------------------------
117  type, extends(c_xml_item) :: t_xml_chardata
118  class(c_text_data_printer), allocatable :: chardata
119  contains
120  procedure :: write => t_xml_chardata__write
121  procedure :: delete => t_xml_chardata__delete
122  end type t_xml_chardata
123 
124  !============================================================================
125  ! ABSTRACT INTERFACES
126  !============================================================================
127 
128  !----------------------------------------------------------------------------
130  abstract interface
131  subroutine i_xml_item__write(self, indent, fid)
132  import :: c_xml_item
133  implicit none
134  class(c_xml_item), intent(in) :: self
135  integer, intent(in) :: indent
136  integer, intent(in) :: fid
137  end subroutine i_xml_item__write
138  end interface
139 
140  !----------------------------------------------------------------------------
142  abstract interface
143  subroutine i_xml_item__delete(self)
144  import :: c_xml_item
145  implicit none
146  class(c_xml_item), intent(inout) :: self
147  end subroutine i_xml_item__delete
148  end interface
149 
150  !----------------------------------------------------------------------------
152  abstract interface
153  subroutine i_print_text(self, indent, fid)
154  import :: c_text_data_printer
155  implicit none
156  class(c_text_data_printer), intent(in) :: self
157  integer, intent(in) :: indent
158  integer, intent(in) :: fid
159  end subroutine i_print_text
160  end interface
161 
162  !----------------------------------------------------------------------------
164  abstract interface
165  subroutine i_delete_printer(self)
166  import :: c_text_data_printer
167  implicit none
168  class(c_text_data_printer), intent(inout) :: self
169  end subroutine i_delete_printer
170  end interface
171 
173 contains
175 
176 !------------------------------------------------------------------------------
177  recursive subroutine t_xml_content__write(self, indent, fid)
178  class(t_xml_content), intent(in) :: self
179  integer, intent(in) :: indent
180  integer, intent(in) :: fid
181 
182  if (.not. associated(self%item)) then
183  ! TODO: Give error, item should always exist
184  end if
185 
186  ! 1) Write local item
187  call self%item%write(indent, fid)
188 
189  ! 2) Write following container: recursive step
190  if (associated(self%next)) call self%next%write(indent, fid)
191 
192  end subroutine t_xml_content__write
193 
194 !------------------------------------------------------------------------------
195  recursive subroutine t_xml_content__delete(self)
196  class(t_xml_content), intent(inout) :: self
197 
198  if (.not. associated(self%item)) then
199  ! TODO: Give error, item should always exist
200  end if
201 
202  ! 1) Delete (and deallocate) following container: recursive step
203  if (associated(self%next)) then
204  call self%next%delete()
205  deallocate (self%next)
206  end if
207 
208  ! 2) Delete (and deallocate) local item
209  call self%item%delete()
210  deallocate (self%item)
211 
212  end subroutine t_xml_content__delete
213 
214 !------------------------------------------------------------------------------
215  recursive function t_xml_content__new_content(self) result(new_cont)
216  class(t_xml_content), intent(inout) :: self
217 
218  type(t_xml_content), pointer :: new_cont
219 
220  if (.not. associated(self%item)) then
221  ! TODO: Give error, item should always exist
222  end if
223 
224  if (associated(self%next)) then
225  new_cont => self%next%new_content()
226  else
227  allocate (t_xml_content :: self%next)
228  new_cont => self%next
229  end if
230 
231  end function t_xml_content__new_content
232 
233 !------------------------------------------------------------------------------
234  subroutine t_xml_document__add_header_line(self, line)
235  class(sll_t_xml_document), intent(inout) :: self
236  character(len=*), intent(in) :: line
237 
238  integer :: nl
239  character(len=maxlen), allocatable :: tmp(:)
240 
241  if (allocated(self%header_lines)) then
242  nl = size(self%header_lines)
243  allocate (tmp(nl + 1))
244  tmp(1:nl) = self%header_lines(1:nl)
245  else
246  nl = 0
247  allocate (tmp(1))
248  end if
249 
250  tmp(nl + 1) = trim(line)
251 
252  call move_alloc(from=tmp, to=self%header_lines)
253 
254  end subroutine t_xml_document__add_header_line
255 
256 !------------------------------------------------------------------------------
257  function t_xml_document__new_element(self, name) result(new_root)
258  class(sll_t_xml_document), target, intent(inout) :: self
259  character(len=*), intent(in) :: name
260 
261  type(sll_t_xml_element), pointer :: new_root
262 
263  if (allocated(self%root)) then
264  ! TODO: give error!!! Only one root element may exist
265  else
266  allocate (self%root)
267  self%root%name = trim(name)
268  end if
269 
270  new_root => self%root
271 
272  end function t_xml_document__new_element
273 
274 !------------------------------------------------------------------------------
275  subroutine t_xml_document__write(self, fname)
276  class(sll_t_xml_document), intent(in) :: self
277  character(len=*), intent(in) :: fname
278 
279  integer :: fid, i
280 
281  ! Create a new file using default properties
282  open (file=fname, status='replace', form='formatted', newunit=fid)
283 
284  ! Print header lines
285  if (allocated(self%header_lines)) then
286  do i = lbound(self%header_lines, 1), ubound(self%header_lines, 1)
287  write (fid, '(a)') trim(self%header_lines(i))
288  end do
289  end if
290 
291  ! Print root element, recursively
292  if (allocated(self%root)) then
293  call self%root%write(0, fid)
294  end if
295 
296  ! Close file
297  close (fid)
298 
299  end subroutine t_xml_document__write
300 
301 !------------------------------------------------------------------------------
302  subroutine t_xml_document__delete(self)
303  class(sll_t_xml_document), intent(inout) :: self
304 
305  ! Remove header lines
306  if (allocated(self%header_lines)) deallocate (self%header_lines)
307 
308  ! Remove root element (and therefore the whole XML tree, recursively)
309  if (allocated(self%root)) then
310  call self%root%delete()
311  deallocate (self%root)
312  end if
313 
314  end subroutine t_xml_document__delete
315 
316 !------------------------------------------------------------------------------
317  recursive subroutine t_xml_element__write(self, indent, fid)
318  class(sll_t_xml_element), intent(in) :: self
319  integer, intent(in) :: indent
320  integer, intent(in) :: fid
321 
322  logical :: empty_element
323  integer :: na, i
324  character(len=2) :: closing
325 
326  ! Does element have content?
327  empty_element = .not. allocated(self%content)
328 
329  ! How many attributes in element?
330  if (allocated(self%attributes)) then
331  na = size(self%attributes)
332  else
333  na = 0
334  end if
335 
336  ! Select closing tag for first line
337  if (empty_element) then
338  closing = '/>'
339  else
340  closing = '>'
341  end if
342 
343  ! Write first line (only line if element is empty)
344  if (na > 0) then
345  write (fid, '(*(a))') &
346  repeat(' ', indent)//'<'//trim(self%name), & ! element name
347  (' '//self%attributes(i)%to_string(), i=1, na), & ! attributes
348  trim(closing) ! closing tag
349  else
350  write (fid, '(*(a))') &
351  repeat(' ', indent)//'<'//trim(self%name), & ! element name
352  trim(closing) ! closing tag
353  end if
354  ! Write contents and last line (do nothing if element is empty)
355  if (.not. empty_element) then
356  call self%content%write(indent + 2, fid)
357  write (fid, '(a)') repeat(' ', indent)//'</'//trim(self%name)//'>'
358  end if
359 
360  end subroutine t_xml_element__write
361 
362 !------------------------------------------------------------------------------
363  recursive subroutine t_xml_element__delete(self)
364  class(sll_t_xml_element), intent(inout) :: self
365 
366  ! Deallocate attributes
367  if (allocated(self%attributes)) then
368  deallocate (self%attributes)
369  end if
370 
371  ! Delete and deallocate content
372  if (allocated(self%content)) then
373  call self%content%delete()
374  deallocate (self%content)
375  end if
376 
377  end subroutine t_xml_element__delete
378 
379 !------------------------------------------------------------------------------
380  subroutine t_xml_element__add_attribute(self, name, attvalue)
381  class(sll_t_xml_element), intent(inout) :: self
382  character(len=*), intent(in) :: name
383  character(len=*), intent(in) :: attvalue
384 
385  integer :: na
386  type(t_xml_attribute), allocatable :: tmp(:)
387 
388  if (allocated(self%attributes)) then
389  na = size(self%attributes)
390  allocate (tmp(na + 1))
391  tmp(1:na) = self%attributes(1:na)
392  else
393  na = 0
394  allocate (tmp(1))
395  end if
396 
397  tmp(na + 1)%name = name
398  tmp(na + 1)%attvalue = attvalue
399 
400  call move_alloc(from=tmp, to=self%attributes)
401 
402  end subroutine t_xml_element__add_attribute
403 
404 !------------------------------------------------------------------------------
405  subroutine t_xml_element__add_chardata_string(self, string)
406  class(sll_t_xml_element), target, intent(inout) :: self
407  character(len=*), intent(in) :: string
408 
409  type(t_xml_content), pointer :: new_cont ! local variable
410 
411  ! Allocate new content (container)
412  if (.not. allocated(self%content)) then
413  allocate (self%content)
414  new_cont => self%content
415  else
416  new_cont => self%content%new_content()
417  end if
418 
419  ! Create new chardata inside the container
420  allocate (t_xml_chardata :: new_cont%item)
421  select type (new_item => new_cont%item); type is (t_xml_chardata)
422 
423  ! Create new default data printer inside the chardata
424  allocate (t_default_text_data_printer :: new_item%chardata)
425  select type (new_cdata => new_item%chardata)
427 
428  ! Add text to printer
429  new_cdata%text = adjustl(string)
430 
431  end select
432  end select
433 
435 
436 !------------------------------------------------------------------------------
437  subroutine t_xml_element__add_chardata_printer(self, printer)
438  class(sll_t_xml_element), target, intent(inout) :: self
439  class(c_text_data_printer), intent(in) :: printer
440 
441  type(t_xml_content), pointer :: new_cont ! local variable
442 
443  ! Allocate new content (container)
444  if (.not. allocated(self%content)) then
445  allocate (self%content)
446  new_cont => self%content
447  else
448  new_cont => self%content%new_content()
449  end if
450 
451  ! Create new chardata inside container
452  allocate (t_xml_chardata :: new_cont%item)
453  select type (new_item => new_cont%item); type is (t_xml_chardata)
454 
455  ! Copy user-defined printer inside chardata
456  allocate (new_item%chardata, source=printer)
457 
458  end select
459 
461 
462 !------------------------------------------------------------------------------
463  function t_xml_element__new_element(self, name) result(new_elem)
464  class(sll_t_xml_element), target, intent(inout) :: self
465  character(len=*), intent(in) :: name
466 
467  type(sll_t_xml_element), pointer :: new_elem ! output argument
468  type(t_xml_content), pointer :: new_cont ! local variable
469 
470  ! Allocate new content (container)
471  if (.not. allocated(self%content)) then
472  allocate (self%content)
473  new_cont => self%content
474  else
475  new_cont => self%content%new_content()
476  end if
477 
478  ! Create new element inside the container
479  allocate (sll_t_xml_element :: new_cont%item)
480  select type (new_item => new_cont%item); type is (sll_t_xml_element)
481  new_elem => new_item
482  new_elem%name = name
483  end select
484 
485  end function t_xml_element__new_element
486 
487 !------------------------------------------------------------------------------
488  subroutine t_xml_chardata__write(self, indent, fid)
489  class(t_xml_chardata), intent(in) :: self
490  integer, intent(in) :: indent
491  integer, intent(in) :: fid
492 
493  call self%chardata%print_text(indent, fid)
494 
495  end subroutine t_xml_chardata__write
496 
497 !------------------------------------------------------------------------------
498  subroutine t_xml_chardata__delete(self)
499  class(t_xml_chardata), intent(inout) :: self
500 
501  if (allocated(self%chardata)) then
502  call self%chardata%delete()
503  deallocate (self%chardata)
504  end if
505 
506  end subroutine
507 
508 !------------------------------------------------------------------------------
509  subroutine default_print_text(self, indent, fid)
510  class(t_default_text_data_printer), intent(in) :: self
511  integer, intent(in) :: indent
512  integer, intent(in) :: fid
513 
514  integer :: i
515 
516  write (fid, '(*(a))') (' ', i=1, indent), trim(self%text)
517 
518  end subroutine default_print_text
519 
520 !------------------------------------------------------------------------------
521  subroutine default_delete(self)
522  class(t_default_text_data_printer), intent(inout) :: self
523 
524  return
525  print *, storage_size(self)
526  ! Do nothing for now
527  end subroutine
528 
529 !------------------------------------------------------------------------------
530  pure function attribute_name_val_string(self) result(s)
531  class(t_xml_attribute), intent(in) :: self
532  !character( len = len(self%name)+1+len(self%attvalue) ) :: s
533  character(len=:), allocatable :: s
534 
535  integer :: char_len
536 
537  char_len = len_trim(self%name) + len_trim(self%attvalue) + 3
538  allocate (character(len=char_len) :: s)
539 
540  s = trim(self%name)//"='"//trim(self%attvalue)//"'"
541 
542  end function attribute_name_val_string
543 
544 !------------------------------------------------------------------------------
545 
546 end module sll_m_xml
547 
Delete chardata printer.
Definition: sll_m_xml.F90:165
Write chardata to file.
Definition: sll_m_xml.F90:153
Delete XML item (deallocate everything)
Definition: sll_m_xml.F90:143
Write XML content to file.
Definition: sll_m_xml.F90:131
Facilities for constructing an XML tree and printing it to file.
Definition: sll_m_xml.F90:13
type(sll_t_xml_element) function, pointer t_xml_document__new_element(self, name)
Definition: sll_m_xml.F90:258
subroutine t_xml_document__add_header_line(self, line)
Definition: sll_m_xml.F90:235
subroutine t_xml_element__add_chardata_printer(self, printer)
Definition: sll_m_xml.F90:438
recursive subroutine t_xml_element__delete(self)
Definition: sll_m_xml.F90:364
subroutine t_xml_chardata__delete(self)
Definition: sll_m_xml.F90:499
recursive subroutine t_xml_content__delete(self)
Definition: sll_m_xml.F90:196
subroutine t_xml_document__delete(self)
Definition: sll_m_xml.F90:303
subroutine t_xml_chardata__write(self, indent, fid)
Definition: sll_m_xml.F90:489
type(sll_t_xml_element) function, pointer t_xml_element__new_element(self, name)
Definition: sll_m_xml.F90:464
pure character(len=:) function, allocatable attribute_name_val_string(self)
Definition: sll_m_xml.F90:531
recursive subroutine t_xml_element__write(self, indent, fid)
Definition: sll_m_xml.F90:318
subroutine t_xml_element__add_attribute(self, name, attvalue)
Definition: sll_m_xml.F90:381
subroutine default_print_text(self, indent, fid)
Definition: sll_m_xml.F90:510
recursive type(t_xml_content) function, pointer t_xml_content__new_content(self)
Definition: sll_m_xml.F90:216
subroutine t_xml_document__write(self, fname)
Definition: sll_m_xml.F90:276
subroutine t_xml_element__add_chardata_string(self, string)
Definition: sll_m_xml.F90:406
character, parameter nl
Definition: sll_m_xml.F90:27
subroutine default_delete(self)
Definition: sll_m_xml.F90:522
integer, parameter maxlen
Definition: sll_m_xml.F90:28
recursive subroutine t_xml_content__write(self, indent, fid)
Definition: sll_m_xml.F90:178
XML abstract class: generic printer for writing chardata to file.
Definition: sll_m_xml.F90:99
Base class for all the XML entities which can appear in content.
Definition: sll_m_xml.F90:36
XML document type.
Definition: sll_m_xml.F90:87
XML type: default printer for writing chardata.
Definition: sll_m_xml.F90:107
XML attribute type.
Definition: sll_m_xml.F90:55
XML type: chardata.
Definition: sll_m_xml.F90:117
XML type: linked list of XML entities, used in element content.
Definition: sll_m_xml.F90:44
    Report Typos and Errors