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