Minerva supports the manipulation (read/modify/write) of XML terms.
There exist four predicates for reading and writing XML terms.
There are also a couple of predicates for converting lowlevel XML terms to highlevel MINERVA terms and vice versa.
TypeDefinition =
MarkupName(AttributeAndSubElementType ...)
% example: addressbook(type=enum([private,business]), any * Address)
AttributeAndSubElementType =
AttributeType
AttributeAndSubElementType =
ElementType
AttributeType =
AttributeName = BasicType
% example: type = enum([private,business])
AttributeType =
AttributeName = opt(BasicType,DefaultValue)
% example: language = opt(atom, english)
ElementType =
(ElementType, ElementType)
% example: (title(-atom),author(firstname(-atom),name(-atom)),price(-number))
ElementType =
(ElementType; ElementType)
% example: (book(title(-atom),author(Autor));journal(title(-atom),volume(-integer)))
ElementType =
Count * ElementType
% example: book(title(-atom),author(Autor),(0,5)*coautor(Autor))
ElementType =
- BasicType
% example: year(-integer)
ElementType =
TypeDefinition
Count =
(Min,Max)
Count =
Integer
% "N * Type" is equivalent to "(N,N) * Type"
Count =
any
% "any * Type" is equivalent to "(0,inf) * Type"
Count =
opt
% "any * Type" is equivalent to "(0,1) * Type"
Count =
some
% "any * Type" is equivalent to "(1,inf) * Type"
Min =
NonNegativeInteger
Max =
NonNegativeInteger
Max =
inf
BasicType =
atom
BasicType =
integer
BasicType =
float
BasicType =
number
BasicType =
boolean
BasicType =
enum([Name, ...])
John 35 Henriette 27
Now you want to read the addressbook in MINERVA. Open the the XML file with open/3 and read the XML term with read_xml/2.
main([XmlFilename]) :-
open(XmlFilename, read, XmlStream),
read_xml(XmlStream, XmlTerm),
close(XmlStream),
writeq(XmlTerm),
nl.
When calling this program you will get the following output.
document([xml([version = '1.0'])],
element(addressbook,[],[
element(address,[telno = '1234567'],[
element(name,[],[chardata('John')]),
element(age,[],[chardata('35')])]),
element(address,[telno = '3456789',email = 'henriette@ifcomputer.com'],[
element(name,[],[chardata('Henriette')]),
element(age,[],[chardata('27')])])]),[])
So, you read the XML file and got the content of this file as MINERVA term. You can examine this term, manipulate it and write it back to another file. For example you may have two address books of the same format, one containing the addresses of your friends and the another containing the addresses of your business partners. You may decide to merge the two address books into one book.
main([Friends,BusinessPartner,NewAddrBook]) :-
read_xmlfile(Friends,Book_1),
read_xmlfile(BusinessPartner,Book_2),
merge_books(Book_1, Book_2, Book),
write_xmlfile(NewAddrBook, Book).
read_xmlfile(Filename, XmlTerm) :-
open(Filename, read, Stream),
read_xml(Stream, XmlTerm),
close(Stream).
merge_books(
document(_,Addr_1,_),
document(_,Addr_2,_),
document([xml([version = '1.0'])], Elements, [])) :-
append(Addr_1, Addr_2, Addr),
sort(Addr, Elements).
write_xmlfile(Filename, XmlTerm) :-
open(Filename, write, Stream),
write_xml(Stream, XmlTerm),
close(Stream).
Or you want to print all persons sortet by their age. You could do it as follows.
main([AddrBook,Person]) :-
read_xmlfile(AddrBook, Book),
findall(person(Age,Name), getperson(Book, Name, Age), List),
sort(List, SortedList),
writeq(SortedList),
nl.
read_xmlfile(Filename, XmlTerm) :-
open(Filename, read, Stream),
read_xml(Stream, XmlTerm),
close(Stream).
getperson(document(_,Elements,_), Name, Age) :-
member(Element, Elements),
Element = element(address,Attributes,[NameElem,AgeElem]),
AgeElem = element(age,_,[chardata(AgeString)]),
atom_number(AgeString, Age),
NameElem = element(name,_,[chardata(Name)]).
The last example showed that the manipulation of lowlevel terms is quite complex (see getperson/2). Therefore MINERVA offers some predicates to convert lowlevel XML terms in a more convenient format. Using these predicates the last example could be implemented as follows.
main([AddrBook,Person]) :-
read_xmlfile(AddrBook, XmlTerm),
booktype(BookType),
xmldoc2term(BookType, XmlTerm, Book),
findall(person(Age,Name), getperson(Book, Name, Age), List),
sort(List, SortedList),
writeq(SortedList),
nl.
booktype(addressbook(any * AddressType)) :-
AddressType = address(
telno=atom, % Attribute 'telno'
email=opt(atom,''), % Optional attribute 'email' (defaults to '')
name(-atom),
age(-integer))). % subelements 'name' and 'age'
read_xmlfile(Filename, XmlTerm) :-
open(Filename, read, Stream),
read_xml(Stream, XmlTerm),
close(Stream).
getperson(addressbook(AddressList), Name, Age) :-
member(address(_, _, name(Name), age(Age)), AddressList).
read_xml/2/3
write_xml/1/2
term2xml/3
term2xmldoc/3
xml2term/3
xmldoc2term/3
Up
read on...