The index
An xml_index holds the tags of a file (name, attributes, hierarchy, byte positions) but not their content, which is read from the file when you ask for it: the memory used does not depend on the data held in the file.
f90
call results%scan(filename='results.xml', iostat=iostat) ! tags and attributes only, no content
snapshots = results%find_all(path='results/snapshot')
print '(A,I0,A,I0,A)', 'indexed ', results%tags_number(), ' tags, ', size(snapshots), ' snapshots'| Method | Does |
|---|---|
scan(filename, [stop_at=], [chunk_size=], [iostat=], [iomsg=], [sanitize_attributes_value=]) | indexes a file read in chunks (default 64 KiB, smaller than the 1 MiB of parse, so a scan stopped early reads little beyond the stop); with stop_at, stops after the start tag of the first tag with that name; errors as xml_file%parse |
find, find_all, select, matching, children, attribute, attributes_number, attribute_name, tags_number, name, parent, level, prefix, local_name, namespace | the queries of xml_file (matching on names and attributes: the index holds no content) |
content(id, [iostat=], [iomsg=]) | reads the content of a tag from the file, as xml_file%content(id=); '' for a self-closing or unclosed tag; the file bytes, so a single byte encoded file (ISO-8859-1, ...) gives them unconverted |
get_content, get_attribute | the typed values; get_content reads from the file |
text_range(id, first, last) | the byte range of the text of a tag (up to its first child); last < first if empty |
content_range(id, first, last) | the byte range of the whole content (children included) |
stop_position() | the byte after the stop_at start tag, 0 if the scan did not stop |
free() | empties the index |
Encodings
The index reads the file bytes (its positions are file positions): a UTF-16 or UTF-32 file is refused with XML_MALFORMED, a single byte encoding (ISO-8859-1, ...) is read as UTF-8. Parse such files with xml_file or xml_handler, which convert them: see Encodings.
Stopping before raw data
f90
program index_stop
use foxy
implicit none
type(xml_index) :: idx
integer(I8P) :: start
call idx%scan(filename='appended.xml', stop_at='AppendedData') ! the binary data are not parsed
start = idx%stop_position() ! the byte after <AppendedData ...>
print '(A,I0,A,I0)', 'tags: ', idx%tags_number(), ', binary data from byte ', start + 1 ! after the new line of flush
print '(A)', 'encoding: '//idx%attribute(idx%find(name='AppendedData'), 'encoding')
endprogram index_stop$ index_stop
tags: 2, binary data from byte 43
encoding: rawA VTK file with appended raw data is the typical case: the XML header is indexed, the binary data after <AppendedData encoding="raw"> is never read by the scan, and stop_position() tells where it starts.
Next: Streaming parser.