! Fortran does not have built-in XML support, so we'll use a third-party library
! called 'fox' (Fortran XML library) for this example.
! You would need to install and link against this library to run this code.
module plant_module
use fox_dom
use fox_wxml
implicit none
type :: Plant
integer :: id
character(len=50) :: name
character(len=50), dimension(:), allocatable :: origin
end type Plant
contains
function plant_to_string(p) result(str)
type(Plant), intent(in) :: p
character(len=200) :: str
character(len=50) :: temp
integer :: i
write(temp, '(I0)') p%id
str = "Plant id=" // trim(temp) // ", name=" // trim(p%name) // ", origin="
do i = 1, size(p%origin)
str = trim(str) // trim(p%origin(i))
if (i < size(p%origin)) str = trim(str) // ","
end do
end function plant_to_string
end module plant_module
program xml_example
use plant_module
use fox_dom
use fox_wxml
implicit none
type(Plant) :: coffee, tomato
type(Plant), dimension(2) :: plants
type(xmlf_t) :: xf
type(xml_t) :: doc
type(element_t) :: root, plant_elem, name_elem, origin_elem
character(len=1000) :: xml_string
! Initialize coffee plant
coffee%id = 27
coffee%name = "Coffee"
allocate(coffee%origin(2))
coffee%origin(1) = "Ethiopia"
coffee%origin(2) = "Brazil"
! Create XML document
call xml_newElement(doc, "plant", root)
call xml_setAttribute(root, "id", coffee%id)
call xml_newElement(root, "name", name_elem)
call xml_addCharacters(name_elem, coffee%name)
do i = 1, size(coffee%origin)
call xml_newElement(root, "origin", origin_elem)
call xml_addCharacters(origin_elem, coffee%origin(i))
end do
! Output XML
call xml_ToString(doc, xml_string)
print *, trim(xml_string)
! Add XML header
print *, '<?xml version="1.0" encoding="UTF-8"?>'
print *, trim(xml_string)
! Parse XML back into a Plant object
call xml_Parse(doc, xml_string, fatal=.true.)
call xml_GetElementByPath(doc, "/plant", root)
call xml_GetAttribute(root, "id", coffee%id)
call xml_GetElementByPath(root, "name", name_elem)
call xml_GetCharacters(name_elem, coffee%name)
! Note: For simplicity, we're not parsing the origin elements back
print *, plant_to_string(coffee)
! Initialize tomato plant
tomato%id = 81
tomato%name = "Tomato"
allocate(tomato%origin(2))
tomato%origin(1) = "Mexico"
tomato%origin(2) = "California"
! Create nested XML structure
call xml_newElement(doc, "nesting", root)
call xml_newElement(root, "parent", plant_elem)
call xml_newElement(plant_elem, "child", plant_elem)
plants = [coffee, tomato]
do i = 1, size(plants)
call create_plant_element(plant_elem, plants(i))
end do
! Output nested XML
call xml_ToString(doc, xml_string)
print *, trim(xml_string)
contains
subroutine create_plant_element(parent, p)
type(element_t), intent(inout) :: parent
type(Plant), intent(in) :: p
type(element_t) :: plant_elem, name_elem, origin_elem
integer :: i
call xml_newElement(parent, "plant", plant_elem)
call xml_setAttribute(plant_elem, "id", p%id)
call xml_newElement(plant_elem, "name", name_elem)
call xml_addCharacters(name_elem, p%name)
do i = 1, size(p%origin)
call xml_newElement(plant_elem, "origin", origin_elem)
call xml_addCharacters(origin_elem, p%origin(i))
end do
end subroutine create_plant_element
end program xml_example