Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Reading XML files from Fortran

GWats1
New Contributor I
3,087 Views

I did find this old thread from 10 years ago:

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/274838

It points to this site: http://sourceforge.net/projects/xml-fortran/  as a possible solution. So, I'm wondering if there is anything newer or easier for a rank beginner to use for reading an XML file?

I'm using Visual Studio 2013 Shell with Intel Parallel Studio XE 2016 Update 1 Composer Edition for Fortran Windows if that makes any difference. What I would like to do is read an XML file that has some data (real and text) so I can write some Fortran code to solve some equations based on the data.

Thanks

0 Kudos
32 Replies
Arjen_Markus
Honored Contributor I
2,574 Views

As the author and main (but not only) contributor of xml-fortran, I am interested in the problems you are encountering. Could you explain what information you are missing? Note that there are more solutions out there - see http://fortranwiki.org/fortran/show/Libraries. For your information: xml-fortran comes with a tutorial and two articles I wrote for the Fortran Forum.

0 Kudos
GWats1
New Contributor I
2,574 Views

Thanks for the quick reply. As a little background, I'm a Structural Engineer and learned Fortran in 1968 or so and have not gone much past my old ways of programming. About 25 years ago I wrote several programs for designing steel poles and base plates. One of our new Engineers wanted me to get the old programs going again and I was able to recompile in the Visual Studio that I am trying to get used to. My old program runs as a Console that opens a small window where you type in the input file name and an output filename. The output was set to go to a line printer with 132 columns, so you see how old the code is.

The new commercial programs we use can output pole data in XML (I can barely understand what that is, but I can open them in MS Excel). I wanted to be able to read the XML files and store the data (shears and moments and axial loads) so I could calculate some member sizes out of tapered tubular 8 sided shapes that would work for the arms on the poles. So I was stumbling around trying to find a way to read the XML files in Fortran as my first big task.

I came across the XML-Fortran web site and was going to try to start reading and learning how to use it with my Visual Studio but I'm not sure I'm up to the task. Maybe over the Christmas holidays I'll try to learn it.

0 Kudos
Arjen_Markus
Honored Contributor I
2,574 Views

Okay, well, have a look at the two articles I mentioned. My library uses Fortran 90, so you may feel a bit uncomfortable there. But you could simply put the source code for the library into a single project and read the XML file bit by bit. I think I have an example on how to do that, otherwise I can help you with that ;). While there is a lot of magic surrounding XML files, you can safely ignore that. Just think of it as a file with keywords and comments that you need to interpret it and extract the useful information. (I learned FORTRAN 4 1.5 decades later by the way and slowly became acquainted with FORTRAN 77 and then Fortran 90, etc.)

0 Kudos
GWats1
New Contributor I
2,574 Views

Hello Arjen;

I did read the files included in the package and of course I am still a little confused on how to get it installed so my Fortran compiler can use it. I went to the folder ant typed "make" at the command prompt but Win7 tells me no such bat file exists or something like that. I have Visual Studio Community installed with Intel Fortran compiler Paraller Studio XE 2016. I did find ifort.exe located a few places on my HDD and one is here:

c:\Program Files (x86)\IntelSWTools\compilers_and_libraries\windows\bin\ia32\ifort.exe

Could you give me a hint on how to install and compile the /lib files? I have also attached a sample XML file that I would like to read in so I can save the shears and moments to process with a new Fortran program I would write once I figure out how to parse the input data.

EDIT...................

I did a little more reading from the Fortran compiler and came across some things about a makefile and I did find NMAKE.EXE in the executable area:

c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\link.exe
c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\nmake.exe
c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\xdcmake.exe

However if I go to the place where I copied your XML folders and type: NMAKE -f makefile

Win7 does not recognize NMAKE so it is not in my PATH. 

TIA

0 Kudos
andrew_4619
Honored Contributor II
2,574 Views

You are better working in Visual Studio  than command line. That source you downloaded has some old VS6 projects but they don't import /upgrade into VS2013 I tried.

Open VS2013.

File > New > Project

And create and empty console project ( I would call it XMLreader as it was before)

Then in solution explorer right click on the source files entry, select Add > Existing Item and then pick the xmlreader.f90 and xmlparse.f90 files.

for to menu's click build > solution 

and the job is done.

It looks like there are 2 other projects "test_write_prims" and "tstparse" that use other source files. 

 

 

 

 

 

 

0 Kudos
GWats1
New Contributor I
2,574 Views

app4619; Thanks for the tips. I vaguely remember building EXE's from the command line many years ago for 80286 or 80386 PC's. I found some of my old Fortran folders and there was a MAK file in it that had these commands:

POLYPOL.OBJ : POLYPOL.FOR ; FL  /Zi /Od  /Fs /4Yb /c POLYPOL.FOR
SPACE.OBJ : SPACE.FOR ; FL   /Zi /Od  /Fs /4Yb  /c SPACE.FOR
POLYPOL.EXE : POLYPOL.OBJ SPACE.OBJ ; FL  /FPi /Zi /Od /4Yb POLYPOL.OBJ SPACE.OBJ

I don't remember the compiler we used but I do remember I had to break the program into a few .FOR subroutines because of the limitations of the PC.

I'll try out your suggestion for building the solution in VS, although I am a rank amateur.

I did try just now and was able to build a solution which gave me a XMLREADER.EXE file. I tried to run it but it is looking for a file called xmlreader.inp, so I copied my XML file from my pole program into that name but it stops when I start debugging.

 

I'll have to do more reading to see what the reader should have done. The original ZIP file I got had a xmlreader.inp file in the \src\ directory but it is an empty file. Maybe Arjen will comment back on how I should have done the compile in Visual Studio? 

I'll try to attach a screen shot.

 

0 Kudos
Arjen_Markus
Honored Contributor I
2,574 Views

George,

the program xmlreader generates the source code for a module to read a particular type of XML-files. The description for the structure of the XML files in question forms the input to the program. See the tutorial PDF.

Note: XML files are supposed to adhere to some particular definition. There are XML tools to verify that that is indeed the case. The xmlreader program (and others) are meant to make it simpler to read such files.

I have abandoned the use of VS projects/solutions/workspaces - they depend heavily on the version of Visual Studio (previously Developer Studio) you use. I find makefiles or even simple batchfiles much easier to use. That said, it should be easy enough to build the library you need and insert it into the VS solution/project at the link step.

If you use a hand-crafted program to read the XML file, then the xmlparse.f90 file is all you need. The two commands:

ifort -c xmlparse.f90

link /lib xmlparse.obj

will give you a library "xmlparse.lib" that you can use in the linkstep.

If you use the xmlreader program generate a dedicated module, then you also need the source files xml_read_prims.f90 and xml_write_prims.f90 - they contain modules for reading and writing "typed" data. Note that they also use the .inc include files.

(Mental note to self: I should describe this process in some detail in a tutorial)

I will have a look at your example.

0 Kudos
andrew_4619
Honored Contributor II
2,574 Views

It looks like you built it OK. The break point will be a read error on unit 10. I would guess it did not find the file and open a new (empty) file.

The command lines in your old project look like MS Fortran, that brings back some memories.

 

0 Kudos
GWats1
New Contributor I
2,574 Views

The MS Fortran sounds about right for my old MAK .  From Arjen's comment it sounds like I might need to put the other 2 .F90 files into my VS project and let it build an EXE. I'll try to do some more reading when I get home tonight.

I do have one question for Arjen. The original compressed file I got from the host site had a file called xmlreader.inp in the \src\ folder that is zero bytes:

c:\Users\AppData\Local\Temp\_tc\xml-fortran-1.00.tar\xml-fortran\src\xmlreader.inp  /  0 b 01/23/06_15:05 -a--

In your xmlreader.F90 program, unit 10 is opened with that file name (xmlreader.inp) from which it reads fname and closes the unit. I had probably wrongly assumed that the XML file that I wanted to read and parse should be renamed as xmlreader.inp, but I guess I have a lot more reading and understanding to do. Here is a piece of the code where the file is opened and read.

 !
   ! Read the global options file, if present
   !
   strict      = .false.
   global_type = .false.
   dyn_strings = .true.
   call get_global_options( attribs, noattribs, strict, global_type, global_name, &
                            root_name, dyn_strings )

   !
   ! Open the input file and read the name of the template.
   ! Load the template into a tree and then generate it all
   ! in stages
   !
   open( 10, file = 'xmlreader.inp' )
   open( 20, file = 'xmlreader.out' )

   call xml_options( info, report_lun = 20, report_details = .true. )
   read( 10, '(a)' ) fname
   close( 10 )

   prolog_written = .false.
   !
   ! Set the defaults
   !
   global_type = .false.
   global_name = fname
   root_name   = fname

   ludef    = 21
   lusubs   = 22
   luinit   = 23
   luwritp  = 24
   luwrv    = luwritp
   open( ludef,   file = trim(fname)//'.f90' )
   open( lusubs,  status = 'scratch' )
   open( luinit,  status = 'scratch' )
   open( luwritp, status = 'scratch' )
   call open_tmp_files( 31 ) 

 

My end goal is to read the XML file and find a tag that contains some shear and moment values for the arms of my pole and then write some Fortran code to determine the best diameter and thickness to use.

0 Kudos
Arjen_Markus
Honored Contributor I
2,574 Views

Yes, that program simply reads that file for the name of the XML file that describes the ones you want to generate the code for. I am a bit surprised that the compressed file contains a zero-sized version of that file, I will have to correct that.

Here is a little overview:

xmlreader:

  • Reads an XML file which describes the structure of the XML files you want to process
  • Result: source code for a module that will read an entire XML file with that structure

generated source code:

  • Exports a derived type which reflects the structure of the XML file
  • Reads the entire XML file and fills in the various components of the derived type 
  • Requires: xml_parse.f90, read_xml_prims.f90, write_xml_prims.f90
  • To use: "use xml_data_NAME" and call read_xml_file_NAME (NAME = name of the description file)
  • Name of the variable: specified in the description file
0 Kudos
GWats1
New Contributor I
2,574 Views

OK, so I'm getting a little better picture. The xmlreader.inp file will contain one line which is the name of the XML file I want to read in (say GEORGE.XML). Your xmlreader.f90 program will produce a GEORGE.F90 source file that I can compile and should read the GEORGE.XML file and then it would be my task to find the tag I want to read.

 

I have attached a sample XML file zipped up.

0 Kudos
Arjen_Markus
Honored Contributor I
2,574 Views

Ah, not entirely. I will give a you an example:

The xmlreader program reads the name of the file containing the description of the structure. An example of such a file is:

<?xml version="1.0"?>
<items>
<typedef name="item_t">
   <component name="id" type="integer"></component>
   <component name="name" type="line" length="20"></component>
   <component name="item" type="line" length="80"></component>  <!-- To read the data inside <item>...</item> -->
</typedef>
<variable name="x" tag="item" type="item_t" dimension="1"/>
</items>


This means that the XML file has a root element (which is taken for granted) and that root element contains elements "item" - any number of them as the variable x (of derived type item_t) that will hold the data has been defined as an array. Each item is supposed to have elements "id", "name" and "item". The generated code would read a file like the following:

<?xml version="1.0"?>
<myroot>
<item id="1" name="test">
    2334.5  55.4    (two reals)
</item>
<item id="2" name="Test2"/>
<item id="3" name="test3">
    2334.5  55.4    (two reals)
</item>
<item id="4" name="Test4"/>
</myroot>

The generated module defines a variable x:

type item_t
   integer                   :: id
   character(len=20)  :: name
   character(len=80)  :: item
end type item_t
type(item_t), dimension(:), pointer :: x => null()

so you can access the data that were read as x(i)%id, x(i)%name and x(i)%item

 

0 Kudos
GWats1
New Contributor I
2,574 Views

OK, more reading to do.  I'll have to get with the people that wrote the XML file out to see if they have the structure somewhere that I can use.

0 Kudos
Arjen_Markus
Honored Contributor I
2,574 Views

I had a quick look at the XML file you posted. It is unusual (from my unauthorative point of view) in the sense that the contents of the "table" element changes - the table version seems to determine which contents to expect. The simplest way to deal with that is to define each and every version, which would yield a pretty large description.

An alternative would be to just scan the elements and select only those bits you really need. Hm, I will see if I can provide you with a small example to deal with such a solution.

0 Kudos
Arjen_Markus
Honored Contributor I
2,574 Views

I have written the attached program to show the principle of reading XML files via the so-called SAX approach. A few caveats:

  • I had to change the single quotes (') in the XML file to double quotes ("), as otherwise the parser would protest (or worse: get stuck, in a different version). This is something I will have to look into. I am not sure if single quotes are part of the XML standard. Quite likely though and that is an omission in the parser.
  • The more data you want to get out of the XML file, the more logic you will need to retrieve only the wanted information.

I now understand what is happening in this XML file, though. One of the attributes defines the element name (tag) that will follow. You could use that information to hand over the reading to a dedicated routine.

0 Kudos
GWats1
New Contributor I
2,574 Views

Yes, I kind of see your point. The XML structure is the same for most steel poles and for my immediate need is to find the data that starts with:

<table plsname='Detailed Tubular Davit Arm Usages'

after the </table> line and then I need to save the tags with the loads that go with one of the 8 arms on the pole. Here is a piece of the XML file with the tags:

</table>
<table plsname='Detailed Tubular Davit Arm Usages' tagname='detailed_tubular_davit_arm_usages' ncols='20' nrows='56' units='0' version='14' titledetail='NESC 250B NA+,I NA+ (59mph)'>
  <detailed_tubular_davit_arm_usages rownum='0'>
    <rowtext />
    <element_label>SARM-L</element_label>
    <joint_label>SARM-L:O</joint_label>
    <joint_position>Origin</joint_position>
    <rel_dist>0.00</rel_dist>
    <trans_defl>45.86</trans_defl>
    <long_defl>0.03</long_defl>
    <vert_defl>-0.33</vert_defl>
    <vert_mom>-1.10</vert_mom>
    <horz_mom>0.00</horz_mom>
    <tors_mom>0.0</tors_mom>
    <axial_force>-0.64</axial_force>
    <vert_shear>0.23</vert_shear>
    <horz_shear>-0.00</horz_shear>
    <p_a>-0.14</p_a>
    <m_s>1.54</m_s>
    <v_q>0.04</v_q>
    <t_r>0.00</t_r>
    <res>1.69</res>
    <max_usage>2.6</max_usage>
    <at_pt>2</at_pt>

 

 

0 Kudos
GWats1
New Contributor I
2,574 Views

Hello Arjen;

I didn't refresh my browser to see you had posted a program for me while I was typing and responding to your post this morning. I didn't mean for you to have to so much work on my problem. The example file you worked on had a wood pole and I had saved another ZIP file from a steel pole but the principles are the same and the tags are probably close since the original program that creates them handles wood and steel poles.

I'll look at the F90 program you did and see if I can figure it out for reading my XML and saving the tags I want.

Many thanks for all your effort.

I was going to try to upload a picture of a pole but it was too big.  Will try again.

0 Kudos
Arjen_Markus
Honored Contributor I
2,574 Views

No problem - in a way it is fun and a good exercise to see if my library can handle this type of XML files. It is amazing what variations you come across!

By the way, I checked the specification - single quotes are indeed allowed. So I will adjust my library to properly take care of them. And the set-up of the files you are dealing with have given me an idea for making it easier to use the SAX approach.

0 Kudos
GWats1
New Contributor I
2,574 Views

Thanks for all the help. If you ever need a transmission pole or lattice tower analyzed, let me know. I've been looking at them since 1973.

0 Kudos
Arjen_Markus
Honored Contributor I
2,205 Views

You're welcome. As for the offer: thanks - it is not quite my area of expertise (that is more like water quality modelling), but who knows :).

0 Kudos
Reply