!parsing model node subroutine parseModel(mp, np, parentformat, format, parentmeta, & meta, name, meta_verify) type(MODEL), pointer, intent(in) :: mp type(Node), pointer, intent(in) :: np real, intent(in), optional :: parentformat, parentmeta real, intent(out) :: format, meta character (len = *), intent(out), optional :: name optional :: meta_verify interface subroutine meta_verify (meta) real, intent(in) :: meta end subroutine end interface !handle format version if (present(parentformat)) then format = parentformat else !parse the version call parseModelVersions(np, format = format) end if !verify the format version call verifyModelFormatVersion(format) !handle meta version if (present(parentmeta)) then meta = parentmeta else !parse the version call parseModelVersions(np, meta = meta) end if !parse the model object name if(present(name)) then call parseModelName(np, name, format) end if !verify the meta if(present(meta_verify)) then call meta_verify(meta) end if !parse the parameters call parseModelParameters(mp, np, format, meta) end subroutine !parse children elements and callback to the calling module subroutine parseModelChildren(mp, np, format, meta, & children_tag, child_tag, child_callback) type(MODEL), pointer, intent(in) :: mp type(Node), pointer, intent(in) :: np real, intent(in) :: format, meta character (len=*), intent(in) :: children_tag, child_tag interface subroutine child_callback(mp, cnp, format, meta, & child_index, child_count) use model_xml !this may fail in wonderful ways! import :: MODEL type(MODEL), pointer, intent(in) :: mp type(Node), pointer, intent(in) :: cnp real, intent(in) :: format, meta integer, intent(in) :: child_index, child_count end subroutine end interface type(Node), pointer :: cs, c type(NodeList), pointer :: clist integer :: i cs => item(getElementsByTagName(np, children_tag, recursive=.false.), 0) !test that the children node isn't null/undefined if(associated(cs)) then !get the node list of child elements clist => getElementsByTagName(cs, child_tag, recursive=.false.) !loop over each of the children !WARNING, FoX is using zero based index! Why? do i=0, getLength(clist) - 1 !c is a pointer to the child element node c => item(clist, i) !call the callback for each child element call child_callback(mp=mp, cnp=c, format=format, meta=meta, & !convert the index to 1 based child_index=i+1, child_count=getLength(clist)) end do else print *, "WARNING: no children: ", children_tag end if end subroutine subroutine parseModelParameters(mp, np, format, meta) type(MODEL), pointer, intent(in) :: mp type(Node), pointer, intent(in) :: np real, intent(in) :: format, meta type(Node), pointer :: ps, p, vnp, name_p, value_container type(Node), pointer :: units_node type(NodeList), pointer :: plist integer :: i type(NodeList), pointer :: series_list, multidim_list, value_list integer :: series_index, series_count integer :: value_index, value_count integer :: multidim_index, multidim_count integer :: dim_index, dim_count integer :: index, count character (len=100) :: name, value, units !verify version call verifyModelFormatVersion(format) !ps points to the parameters element ps => item(getElementsByTagName(np, tag_parameters, recursive=.false.), 0) !test that the parameters node isn't null/undefined if(associated(ps)) then !get the nodelist of parameter elements plist => getElementsByTagName(ps, tag_parameter, recursive=.false.) !loop over each of the parameters !WARNING, FoX is using zero based index! Why? do i=0, getLength(plist) - 1 !p is a pointer to the parameter element node p => item(plist, i) !name is required, pointer to the name attribute node name_p => getAttributeNode(p, attr_name) !test that the name attribute wasn't missing if(associated(name_p)) then call extractDataAttribute (p, attr_name, name) else print *, "ERROR: name attribute is required for model parameter." stop 1 end if !get the list of series series_list => getElementsByTagName(p, tag_series, recursive=.false.) series_count = getLength(series_list) !test that when there are series there aren't values or multidims if(series_count .gt. 0) then call verifyElementCount(p, tag_value, max=0) call verifyElementCount(p, tag_multidim, max=0) end if value_container => p do series_index = 0, series_count if(series_index .gt. 0) then value_container=> item(series_list, series_index-1) end if !get list of multidim multidim_list => getElementsByTagName(value_container, tag_multidim, recursive=.false.) multidim_count = getLength(multidim_list) !test that when there are multidims there aren't values if(multidim_count .gt. 0) then call verifyElementCount(value_container, tag_value, max=0) end if do multidim_index=0, multidim_count if(multidim_index .gt. 0) then value_container => item(multidim_list, multidim_index-1) end if !get list of values value_list => getElementsByTagName(value_container, tag_value, recursive=.false.) value_count = getLength(value_list) !test that when there are value there aren't multidim if(value_count .gt. 0) then call verifyElementCount(value_container, tag_multidim, max=0) end if do value_index = 0, value_count if(series_count .eq. 0 .and. multidim_count .eq. 0 .and. value_count .eq. 0) then !this is a simple parameter, value is in the text of parameter vnp => p else if (value_index .eq. 0) then cycle else vnp => item(value_list, value_index - 1) end if !get the value call extractDataContent(vnp, value) !get the units units_node => getAttributeNode(vnp, attr_units) if(associated(units_node)) then !the attribute exists, parse as a real call extractDataAttribute (vnp, attr_units, units) else units = "" end if !value index/count represents the value or multidim location if (value_count .eq. 0) then index = 1 count = 1 dim_index = 1 dim_count = 1 else if (multidim_count .gt. 0 ) then index = multidim_index count = multidim_count dim_index = value_index dim_count = value_count else index = value_index count = value_count dim_index = 1 dim_count = 1 end if !print a debug ! print *, name ! print *, series_index, series_count, index, count, dim_index, dim_count ! print *, "" !callback to the calling xml module call assignParameterValue( & !model pointer mp=mp, & !format and meta version format=format, meta=meta, & pnp=p, & !parameter node pointer vnp=vnp, & !value node pointer name=name, & !parameter name value=value, & !parameter value units=units, & !value units !series series_index = series_index, series_count=series_count, & !values/multidims index = index, count=count, & !dimensions dim_index = dim_index, dim_count=dim_count & ) end do end do end do !figure out if we have a list of values or multidim !basic parameter, only a single value end do else print*, "WARNING: no parameters" end if end subroutine