История изменений
Исправление runtime, (текущая версия) :
Вдогонку, построение базы данных узлов и связей между ними в памяти, чтобы каждый раз не лазить вглубь дерева. Выдёргивалось кусками из существующего кода, поэтому работоспособность из коробки не гарантирую. Если что - дай знать, помогу.
/****************************
Building DB
****************************/
:- dynamic node/4. % node(id, name, attributes, value)
:- dynamic link/2. % link(id, parent_id)
clear_db :-
abolish(node/4),
abolish(link/2).
build_db(DOM) :-
build_db_aux(DOM, [-1], 0).
build_db_aux([], [], _).
build_db_aux(Elements, ParentIds, Id) :-
% add current element to DB, generate new id
Elements = [Element|Es],
ParentIds = [Parent|Ps],
add_to_db(Id, Element, Parent),
% get children, set current id as their parent
get_children(Element, Children),
length(Children, ChildCount),
length(ChildParentIds, ChildCount),
maplist('='(Id), ChildParentIds),
% process remaining elements
Id2 is Id+1,
append(Children, Es, Elements2),
append(ChildParentIds, Ps, ParentIds2),
build_db_aux(Elements2, ParentIds2, Id2).
add_to_db(Id, Elem, Parent) :-
assert(link(Id, Parent)),
(is_element(Elem) ->
get_name(Elem, Name),
get_attributes(Elem, Attributes),
assert(node(Id, Name, Attributes, []))
;
Value = Elem, % Elem itself represents node contents
assert(node(Id, [], [], Value))
).
/****************************
Node operations
****************************/
is_parent_of(Parent, Child) :-
Parent = element(_, _, Children),
member(Child, Children).
is_element(E) :-
E =.. [element|_].
get_attribute(E, Name, Value) :-
E = element(_, Attrs, _),
member(Name=Value, Attrs).
get_name(E, Name) :-
E = element(Name, _, _).
get_attributes(E, Attributes) :-
E = element(_, Attributes, _).
get_children(E, Children) :-
E = element(_, _, Children).
get_children(_, []) :- !.
Исходная версия runtime, :
Вдогонку, построение базы данных узлов и связей между ними в памяти, чтобы каждый раз не лазить вглубь дерева. Выдёргивалось кусками из существующего кода, поэтому работоспособность из коробки не гарантирую. Если что - дай знать, помогу.
/****************************
Building DB
****************************/
:- dynamic node/4. % node(id, name, attributes, value)
:- dynamic link/2. % link(id, parent_id)
clear_db :-
abolish(node/4),
abolish(link/2).
build_db(DOM) :-
build_db_aux(DOM, [-1], 0).
build_db_aux([], [], _).
build_db_aux(Elements, ParentIds, Id) :-
% add current element to DB, generate new id
Elements = [Element|Es],
ParentIds = [Parent|Ps],
add_to_db(Id, Element, Parent),
% get children, set current id as their parent
get_children(Element, Children),
length(Children, ChildCount),
length(ChildParentIds, ChildCount),
maplist('='(Id), ChildParentIds),
% process remaining elements
Id2 is Id+1,
append(Children, Es, Elements2),
append(ChildParentIds, Ps, ParentIds2),
build_db_aux(Elements2, ParentIds2, Id2).
add_to_db(Id, Elem, Parent) :-
assert(link(Id, Parent)),
%save_predicate(link(Id, Parent)),
(is_element(Elem) ->
get_name(Elem, Name),
get_attributes(Elem, Attributes),
%save_predicate(node(Id, Name, Attributes, _)),
assert(node(Id, Name, Attributes, []))
;
Value = Elem, % Elem itself represents node contents
assert(node(Id, [], [], Value))
).
/****************************
Node operations
****************************/
is_parent_of(Parent, Child) :-
Parent = element(_, _, Children),
member(Child, Children).
is_element(E) :-
E =.. [element|_].
get_attribute(E, Name, Value) :-
E = element(_, Attrs, _),
member(Name=Value, Attrs).
get_name(E, Name) :-
E = element(Name, _, _).
get_attributes(E, Attributes) :-
E = element(_, Attributes, _).
get_children(E, Children) :-
E = element(_, _, Children).
get_children(_, []) :- !.