我的配置文件的一部分如下:
<factFile name="Apps.xml">
<directory>/home/<account>/Werk/Divers/Prolog/XMLdata/</directory>
<field>apl_id</field>
<field>dns_id</field>
<field>apl_naam_kort</field>
</factFile>
<factFile name="Dienst.xml">
<directory>/home/<account>/Werk/Divers/Prolog/XMLdata/</directory>
<field>dns_id</field>
<field>dns_afkorting</field>
<field>dns_naam</field>
</factFile>
每个factFile都是由MySQL创建的(mysql -u username -p -X -e'使用schema; select-statement'&gt; Apps.xml)
factFiles的数量可以更改,字段数也是如此。 我想要的是将每个数据文件的内容(值)转换为事实。所以
<row>
<field name="apl_id">1</field>
<field name="dns_id">7</field>
<field name="apl_naam_kort">Risk</field>
</row>
应转换为
assertz(apps(1, 7, Risk)).
实现这一目标的最佳方法是什么?
答案 0 :(得分:1)
由于每行的字段数可能会发生变化并且您正在使用SWI-Prolog,我相信使用library record
(Wielemaker & O'Keefe)是一种很好的方法。它允许指定谓词参数的子集并执行类型检查,在早期捕获一些潜在的错误。
由于我不知道您的XML Schema,我已经指定了3个示例字段参数:
apl_id
类型integer
。dns_id
,默认值为0
,类型为非负整数(即nonneg
)。apl_naam_kort
类型atom
。使用其他字段名称扩展record/1
声明很容易。必须相应地提高dynamic/1
声明的范围。
由于SWI-Prolog带有非常好的Web标准支持(明智地选择使用SWI!),从文件(即load_xml/3
)加载XML DOM并匹配行和字段是很简单的使用类似XPath的语句(即xpath/3
)。
:- module(fact_file, [load_fact_file/1]).
:- use_module(library(record)).
:- use_module(library(sgml)).
:- use_module(library(xpath)).
:- record(apps(apl_id:integer, dns_id:nonneg=0, apl_naam_kort)).
:- dynamic(apps/3).
load_fact_file(File):-
load_xml(File, Dom, []),
forall(
xpath(Dom, //row, Row),
(
findall(
NVPair,
(
xpath(Row, //field(@name=Name,text), Value1),
value_conversion(Value1, Value2),
NVPair =.. [Name,Value2]
),
NVPairs
),
make_apps(NVPairs, Apps),
assertz(Apps)
)
).
value_conversion(Atom, Number):-
atom_number(Atom, Number), !.
value_conversion(Atom, Atom).
使用示例:
?- load_fact_file(<FILE-PATH>\test.xml').
true.
?- listing(apps).
:- dynamic fact_file:apps/3.
fact_file:apps(1, 7, 'Risk').
fact_file:apps(_, 0, 'Low Risk').
fact_file:apps(1, 7, _).
档案test.xml
的内容:
<table>
<row>
<field name="apl_id">1</field>
<field name="dns_id">7</field>
<field name="apl_naam_kort">Risk</field>
</row>
<row>
<field name="apl_naam_kort">Low Risk</field>
</row>
<row>
<field name="apl_id">1</field>
<field name="dns_id">7</field>
</row>
</table>
请注意,我们未指定默认值的缺失参数现在显示为未命名变量。这是因为Prolog没有null
值。
可能的改进w.r.t.上面的代码:
record
。record
)之外,允许以对符号(即Name-Value
或Name=Value
)指定库Name(Value)
中的字段。这样我们就可以省略代码行NVPair =.. [Name,Value2]
。record/1
声明。如果字段名称集非常大,事先不知道和/或随时间变化,则可能需要这样做。xsd:nonNegativeInteger
- &gt; nonneg
。