2014-10-15 3 views
1

부분은 다음과 같습니다변환 XMLDATA 내 설정 파일의

각 시설 항목은 MySQL이 생성
<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> 

(MySQL의 -u 사용자 이름 -p -X -e '를 사용 스키마를, 문을 선택'> Apps.xml)

사실 수는 필드 수와 마찬가지로 변경 될 수 있습니다. 내가 원하는 것은 각 데이터 파일의 내용 (값)을 사실로 변환하는 것입니다. 그래서

<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

필드 당 필드 수가 변경 될 수 있으며 SWI-Prolog를 사용하고 있으므로 library record (Wielemaker & O'Keefe)을 사용하면 좋은 접근 방법이라고 생각합니다. 술어 인수의 서브 세트를 지정하고 유형 점검을 수행하여 잠재적 인 오류를 조기에 발견합니다.

내가 여기 당신의 XML 스키마를 알 수 없기 때문에, 내가 지정한 3 샘플 필드 인수 : 유형 integer

  1. apl_id.
  2. dns_id이고 기본값은 0이며 음수가 아닌 정수 (예 : nonneg)입니다.
  3. apl_naam_kortatom입니다.

추가 필드 이름을 사용하여 record/1 선언을 쉽게 확장 할 수 있습니다. 그에 따라 dynamic/1 선언의 유효성을 높여야합니다.

SWI-Prolog는 매우 우수한 웹 표준 지원 (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). 

사용 예 : 파일 test.xml

?- 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, _). 

내용 : 우리는 디폴트 값을 지정하지 않았다 실종 인수가 이제 익명의 변수를 나타나는

<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. 위의 코드 :

  1. record 라이브러리로 값 변환을 통합하십시오.
  2. 라이브러리 record의 입력란을 술어 표기법 (예 : Name(Value)) 외에 쌍 표기법 (즉, Name-Value 또는 Name=Value)으로 지정할 수 있습니다. 이렇게하면 코드 행 NVPair =.. [Name,Value2]을 생략 할 수 있습니다.
  3. record/1 선언을 동적으로 업데이트 할 수 있습니다. 필드 이름 집합이 매우 커서 미리 알 수 없거나 시간이 지남에 따라 변경되는 경우이 작업이 필요할 수 있습니다.
  4. XSD (XML Schema Datatypes)를 사용하는 XML 스키마가 제공된 경우 값 변환은 자동으로 유도 될 수 있습니다 (예 : xsd:nonNegativeInteger ->nonneg).
+0

답장을 보내 주셔서 감사합니다. xpath-predicate에서 'content'인수를 사용하는 방법에 대한 또 다른 질문이 있습니다. 나는 당신의 사이트에이 질문을 던지려고했으나 contact-form은 오류와 함께 리턴한다. –