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