17        character(len=*), 
intent(in) :: element_name       
    18        character(len=*), 
dimension(:), 
intent(in) :: attribute_names, attribute_values
    19        integer, 
intent(in) :: number_of_attributes
    24        character(len=*), 
intent(in) :: element_name
    35   subroutine xml_parse(raw_contents, start_element_callback, end_element_callback)
    36     character, 
dimension(:), 
intent(in) :: raw_contents
    40     character(len=size(raw_contents)) :: string_to_process
    42     integer :: current_index, start_index, end_index, i
    46     do i=1, 
size(raw_contents)
    47       string_to_process(i:i)=raw_contents(i)
    49     do while (current_index .lt. len(string_to_process))
    50       start_index=index(string_to_process(current_index:),
"<")
    51       if (start_index .eq. 0) 
exit    52       start_index=start_index+current_index-1
    53       end_index=index(string_to_process(start_index:),
">")
    54       if (end_index .eq. 0) 
exit    55       end_index=end_index+start_index-1
    56       call process_individual_tag(string_to_process, start_element_callback, end_element_callback, start_index, end_index)
    57       current_index=end_index
    67   subroutine process_individual_tag(raw_contents, start_element_callback, end_element_callback, start_index, end_index)
    68     character(len=*), 
intent(in) :: raw_contents
    71     integer, 
intent(in) :: start_index, end_index
    73     character(len=STRING_LENGTH) :: tag_name
    74     character(len=STRING_LENGTH), 
dimension(:), 
allocatable :: attribute_names, attribute_values
    76     integer :: name_start_index, name_end_index, number_attributes, attribute_index, i, attribute_start_posn, new_start_posn
    78     if (raw_contents(start_index+1:start_index+1) .eq. 
"!") 
return    80     start_tag=.not. raw_contents(start_index+1:start_index+1) .eq. 
"/"    81     name_start_index = start_index+1
    82     if (.not. start_tag) name_start_index=name_start_index+1
    83     name_end_index=index(raw_contents(name_start_index:end_index), 
" ")
    84     if (name_end_index .eq. 0) 
then    85       name_end_index=end_index-1
    87       name_end_index=name_end_index+name_start_index-1
    90     tag_name=raw_contents(name_start_index : name_end_index)    
    92     if (.not. start_tag) 
then    93       call end_element_callback(tag_name)
    97       attribute_start_posn=1
    98       allocate(attribute_names(number_attributes), attribute_values(number_attributes))
   100       attribute_values(:)=
""   101       do i=1,number_attributes
   102         new_start_posn=
get_attribute(raw_contents(name_end_index+1:end_index), attribute_start_posn, attribute_names, &
   104         attribute_start_posn=new_start_posn
   106       call start_element_callback(tag_name, number_attributes, attribute_names, attribute_values)
   107       deallocate(attribute_names, attribute_values)
   108       if (raw_contents(end_index-1:end_index) .eq. 
"/>") 
call end_element_callback(tag_name)
   119   integer function get_attribute(contents, start_index, attribute_names, attribute_values, attribute_index)
   120     character(len=*), 
intent(in) :: contents
   121     integer, 
intent(in) :: start_index, attribute_index
   122     character(len=*), 
dimension(:), 
allocatable, 
intent(inout) :: attribute_names, attribute_values
   124     integer :: equals_posn, end_oftag_absolute, equals_absolute, open_quote, close_quote, begin_index, space_point
   127     equals_posn=index(contents(start_index:), 
"=")
   128     if (equals_posn .ne. 0) 
then   130       equals_absolute=equals_posn+start_index-1
   131       if (index(trim(adjustl(contents(start_index:equals_absolute))), 
" ") .ne. 0) 
then   133         call log_log(
log_warn, 
"Ignorning leading garbage in attribute name '"//contents(start_index:equals_absolute)//
"'")
   134         begin_index=start_index+index(trim(adjustl(contents(start_index:equals_absolute))), 
" ")
   136         begin_index=start_index
   138       open_quote=index(contents(equals_absolute:), 
"""")
   139       if (open_quote .ne. 0) close_quote=index(contents(equals_absolute+open_quote:), 
"""")
   141       if (close_quote == 0) 
then   143         space_point=index(contents(equals_absolute+open_quote:), 
" ")        
   144         close_quote=index(contents(equals_absolute+open_quote:), 
"/>")-1
   145         if (close_quote .lt. 0) close_quote=index(contents(equals_absolute+open_quote:), 
">")-1
   146         if (space_point .ne. 0 .and. space_point .lt. close_quote) close_quote=space_point
   148         if (open_quote .gt. 2) 
then   150           if (len(trim(adjustl(contents(equals_absolute+1:equals_absolute+open_quote-1)))) .gt. 0) 
then           151             close_quote=index(trim(adjustl(contents(equals_absolute+1:equals_absolute+open_quote-1))), 
" ")
   156       end_oftag_absolute=close_quote+equals_absolute+open_quote
   158       attribute_names(attribute_index)=trim(adjustl(contents(begin_index:equals_absolute-1)))
   159       attribute_values(attribute_index)=trim(adjustl(contents(equals_absolute+1:end_oftag_absolute-1)))
   160       if (len_trim(attribute_names(attribute_index)) == 0 .or. len_trim(attribute_values(attribute_index)) == 0) 
then   173     character(len=*), 
intent(in) :: string, substring
   175     integer :: current_index, found_index, sub_len
   177     sub_len=len(substring)
   182     do while (found_index .gt. 0)
   183       found_index = index(string(current_index:), substring)
   184       if (found_index .gt. 0) 
then   186         current_index=current_index+found_index+sub_len
 integer function occurances_of_substring(string, substring)
Returns the number of times a specific substring can be found in a string. 
 
The end element callback interface (on closing of XML tag, this is not called if an opening tag self ...
 
subroutine, public xml_parse(raw_contents, start_element_callback, end_element_callback)
Parses some raw XML raw_contents The raw (unparsed) XML string start_element_callback Subroutine to c...
 
integer, parameter, public log_error
Only log ERROR messages. 
 
Contains common definitions for the data and datatypes used by MONC. 
 
subroutine, public log_log(level, message, str)
Logs a message at the specified level. If the level is above the current level then the message is ig...
 
The start element callback interface (on opening of XML tag) 
 
integer function get_attribute(contents, start_index, attribute_names, attribute_values, attribute_index)
Retrieves the "next" attribute from the XML tag and returns the position after this attribute to sear...
 
integer, parameter, public log_warn
Log WARNING and ERROR messages. 
 
integer, parameter, public string_length
Default length of strings. 
 
subroutine process_individual_tag(raw_contents, start_element_callback, end_element_callback, start_index, end_index)
Processes an individual XML tag. This deduces whether it is a start or end tag, the name and any addi...
 
A SAX parser for XML files. This is used to parse the description of the data and rules...