我在使用setof/3
时遇到问题,但缺少一些结果。
背景信息:
我使用SWI-Prolog load_xml()加载一个xml文件来获取递归
list元素(参见示例中的testelement)。然后我想看看
此列表中的特定元素(在xml树中)
使用findall/3
与sort/2
结合使用,效果很好。但如果
我使用setof/3
,我错过了一个结果。我认为setof/3
有问题
在askElement/3
中进行递归调用以获取/保留元素?知道另一个人
解决方案从递归列表中获取元素?
我的测试代码:
testElement([element('recipeml',[version=0.5],
[element('recipe',[],
[element('head',[],
[element('title',[],['Spaghetti Bolognese']
)]
),
element('ing-div',[type=titled],
[element('title',[],['sauce']),
element('ingredients',[],
[element('ing',[],
[element('item',[],['hackfleisch']),
element('item',[],['fleischtomaten']),
element('item',[],['zwiebeln']),
element('item',[],['sellerie']
)]
)]
)]
)]
),
element('recipe',[],
[element('head',[],
[element('title',[],['Erbsensuppe']
)]
),
element('ing-div',[type=titled],
[element('title',[],['elementar']),
element('ingredients',[],
[element('ing',[],
[element('item',[],['sahne']),
element('item',[],['erbsen']),
element('item',[],['gemüsebrühe']
)]
)]
)]
)]
)]
)]).
askElement(Name, Child, Parent) :-
(
member( element(Name,_,Child),Parent)
;
member( element(_,_,NewParent),Parent),
[_|_] = NewParent,
askElement(Name, Child, NewParent)
).
allRecipes_findall(RecipeName) :-
testElement(Knot),
findall(TmpR,(askElement('head',HKnot,Knot),askElement('title',TmpR,HKnot)),Bag),
sort(Bag, RecipeName).
allRecipes_setof(RecipeName) :-
testElement(Knot),
setof(TmpR,(askElement('head',HKnot,Knot),askElement('title',TmpR,HKnot)),RecipeName).
我的输出:
3 ?- allRecipes_findall(X).
X = [['Erbsensuppe'], ['Spaghetti Bolognese']].
4 ?- allRecipes_setof(X).
X = [['Erbsensuppe']]
我预计在这两种情况下我都会得到
X = [['Erbsensuppe'], ['Spaghetti Bolognese']].
怎么了?
非常感谢提前!
PS:非常欢迎每次评论/评论我的(第一次尝试)Prolog代码:}
答案 0 :(得分:2)
Paulo已经就您当前的代码提供了大量建议。我在这里只建议在需要处理XML时利用库(xpath)。它确实需要一些练习,但是你会得到很多功能......对于你的例子:
?- [library(xpath)].
true.
?- testElement(E), xpath(E, //head//title(text), T).
...
T = 'Spaghetti Bolognese' ;
...
T = 'Erbsensuppe' ;
false.
答案 1 :(得分:1)
标准setof/3
谓词为每个目标中的自由变量的不同实例提供了解决方案。按原样使用您的代码:
?- allRecipes_findall(X).
X = [['Erbsensuppe'], ['Spaghetti Bolognese']].
?- allRecipes_setof(X).
X = [['Erbsensuppe']] ;
X = [['Spaghetti Bolognese']].
这是预期的结果。但是,您可以通过使用setof/3
运算符对它们进行存储量化来使^/2
忽略自由变量:
allRecipes_setof(RecipeName) :-
testElement(Knot),
setof(TmpR,HKnot^(askElement('head',HKnot,Knot),askElement('title',TmpR,HKnot)),RecipeName).
通过此更改,您将获得与findall/3
谓词相同的结果:
?- allRecipes_setof(X).
X = [['Erbsensuppe'], ['Spaghetti Bolognese']].
关于编程风格的注释,在 atoms 中使用下划线代替CamelCase以获取代码可读性。例如。 ask_element
代替askElement
。另一方面,对于变量,经常使用CamelCase。