====== Opis ====== __**Projekt zakończony**__ Maksymilian Imioło Translacja XTTML do innych formatów z użyciem Prologu. ====== Spotkania====== [[pl:miw:miw2008_xtt_xmlpro:spotkania|Spotkania]] ====== Projekt ====== ====== Sprawozdanie ====== ====Ogólny opis problemu==== Celem jest przetworzenie pliku xml produkowanego przez Varde [[hekate:hekate_case_thermostat|Thermostat]] do postaci, w której widzimy bezpośrednie zależności pomiedzy elementami. ====Varda wersja 0==== Wczytując plik wyprodukowany przez Varde "ard.xml" load_xml_file('ard.xml',X),A=..X,assertz(A),write(A) i otrzymuję: element(hml, [], [ , element(attribute_set, [], [ , element(att, [name=Thermostat], []), , element(att, [name=Time], []), , element(att, [name=Temperature], []), , element(att, [name=Date], []), , element(att, [name=Hour], []), , element(att, [name=season], []), , element(att, [name=operation], []), , element(att, [name=thermostat_settings], []), , element(att, [name=day], []), , element(att, [name=month], []), , element(att, [name=today], []), , element(att, [name=hour], []), ]), , element(property_set, [], [ , element(property, [pid=1], [ , element(attref, [name=Thermostat], []), ]), , element(property, [pid=2], [ , element(attref, [name=Time], []), , element(attref, [name=Temperature], []), ]), , element(property, [pid=3], [ , element(attref, [name=Time], []), ]), , element(property, [pid=4], [ , element(attref, [name=Temperature], []), ]), , element(property, [pid=5], [ , element(attref, [name=Date], []), , element(attref, [name=Hour], []), , element(attref, [name=season], []), , element(attref, [name=operation], []), ]), , element(property, [pid=6], [ , element(attref, [name=Date], []), , element(attref, [name=Hour], []), ]), , element(property, [pid=7], [ , element(attref, [name=season], []), , element(attref, [name=operation], []), ]), , element(property, [pid=8], [ , element(attref, [name=thermostat_settings], []), ]), , element(property, [pid=9], [ , element(attref, [name=season], []), ]), , element(property, [pid=10], [ , element(attref, [name=operation], []), ]), , element(property, [pid=11], [ , element(attref, [name=Date], []), ]), , element(property, [pid=12], [ , element(attref, [name=Hour], []), ]), , element(property, [pid=13], [ , element(attref, [name=day], []), , element(attref, [name=month], []), , element(attref, [name=today], []), ]), , element(property, [pid=14], [ , element(attref, [name=month], []), ]), , element(property, [pid=15], [ , element(attref, [name=day], []), , element(attref, [name=today], []), ]), , element(property, [pid=16], [ , element(attref, [name=day], []), ]), , element(property, [pid=17], [ , element(attref, [name=today], []), ]), , element(property, [pid=18], [ , element(attref, [name=hour], []), ]), ]), , element(tph, [], [ , element(trans, [src=1, dst=2], []), , element(trans, [src=2, dst=3], []), , element(trans, [src=2, dst=4], []), , element(trans, [src=3, dst=5], []), , element(trans, [src=5, dst=6], []), , element(trans, [src=5, dst=7], []), , element(trans, [src=4, dst=8], []), , element(trans, [src=7, dst=9], []), , element(trans, [src=7, dst=10], []), , element(trans, [src=6, dst=11], []), , element(trans, [src=6, dst=12], []), , element(trans, [src=11, dst=13], []), , element(trans, [src=13, dst=14], []), , element(trans, [src=13, dst=15], []), , element(trans, [src=15, dst=16], []), , element(trans, [src=15, dst=17], []), , element(trans, [src=12, dst=18], []), ]), , element(ard, [], [ , element(dep, [independent=9, dependent=8], []), , element(dep, [independent=10, dependent=8], []), , element(dep, [independent=14, dependent=9], []), , element(dep, [independent=16, dependent=17], []), , element(dep, [independent=17, dependent=10], []), , element(dep, [independent=18, dependent=10], []), ]), ]) Natomiast za pomocą element(hml,B,X) otrzymuję: B = [], X = ['\n ', element(attribute_set, [], ['\n ', element(att, [name='Thermostat'], []), '\n ', element(att, [... =...], []), '\n ', element(..., ..., ...)|...]), '\n ', element(property_set, [], ['\n ', element(property, [... =...], ['\n '|...]), '\n ', element(..., ..., ...)|...]), '\n ', element(tph, [], ['\n ', element(..., ..., ...)|...]), '\n ', element(ard, [], [...|...]), '\n'] Powyższe przykladu są generowane dla wersji zerowej Vardy. W poniższym kodzie rozkładam liste oraz tworze odpowiednik w prologu: %%%%%%%%%%%%%%%%%%%%% Load%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% a:- load_structure('ard.xml',X,[space(remove),dialect(xml)]),Z=..X,assertz(Z),element(hml,_,A), checkAtt(A),checkProp(A),checkHist(A),checkDepend(A),show,zapisz. %%%%%%%%%%%% Wyswietl%%%%%%%%%%%%%%% show:- listing(ard_att),listing(ard_property),listing(ard_hist),listing(ard_depend). %%%%%%%%%%%%%%%%%%%%%%%%%%% Zapis%%%%%%%%%%%%%%%%%%%%%% zapisz:- tell('ardII.xml'),write(''), listing(ard_att),listing(ard_property),listing(ard_hist), listing(ard_depend),told. %%%%%%%%%%%%%%%%%%%%% Attribute_set%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkAtt(A):- nalezy(element(attribute_set,_,L),A), dlugosc(L,Dl1),wyswietlAtt(L,Dl1,0). wyswietlAtt(Ll1,0,Dl). wyswietlAtt(Ll1,D1,Dl):- D1>0, NewDlu is D1-1, usun1(Dl,Ll1,element(att,[name=ZX],[])), assert(ard_att(ZX)), DlNew is Dl+1, wyswietlAtt(Ll1,NewDlu,DlNew). %%%%%%%%%%%%%%%%%%%%% Property_set%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkProp(A):- nalezy(element(property_set,_,L2),A), dlugosc(L2,D2), assert(zobacz(ListaGlob)), wyswietlProp(L2,D2,0). wyswietlProp(L2,0,Dl2). wyswietlProp(L2,D2,Dl2):- D2>0, NewDlu2 is D2-1, usun1(Dl2,L2,element(property,_,C)), dlugosc(C,CA), wypiszProp(CA,C,[]),pamiec(Lista),assert(ard_property(Lista)), zobacz(ListaGlob),dodaj(ListaGlob,Lista,ListaGlob2), retractall(zobacz(_)), assert(zobacz(ListaGlob2)), retractall(pamiec(_)), DlNew2 is Dl2+1, wyswietlProp(L2,NewDlu2,DlNew2). wypiszProp(0,L,Lista). wypiszProp(CA,[J1|L1],Lel):- CA>0, CNew is CA-1, pokazPierwszy(J1,element(attref, [name=Bb], [])), dodaj(Lel,Bb,Lista1), retractall(pamiec(_)), assert(pamiec(Lista1)), wypiszProp(CNew,L1,Lista1). pokazPierwszy(L,L). %%%%%%%%%%%%%%%%%%%%% Hist_set%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkHist(A):- nalezy(element(tph,_,L1),A), dlugosc(L1,D1),wyswietlHist(L1,D1,0). wyswietlHist(L1,0,Dl). wyswietlHist(L1,D1,Dl):- D1>0, NewDlu is D1-1, usun1(Dl,L1,element(trans,[src=Zrodlo,dst=Destination],[])), sprawdz(Zrodlo,Destination,Z,D),assert(ard_hist(Z,D)), DlNew is Dl+1, wyswietlHist(L1,NewDlu,DlNew). %%%%%%%%%%%%%% pobrac src i dest%%%%%%%%%% sprawdz(Zr,De,Zrod,Dest):- atom_number(Zr,Zrr), atom_number(De,Dee), zobacz(Wszystkie), wyswietlPropert(Wszystkie,Zrr,Zrod), wyswietlPropert(Wszystkie,Dee,Dest). wyswietlPropert(Wszystkie,1,Wyjscie):- usun1(0,Wszystkie,Wyjscie). wyswietlPropert(Wszystkie,Miejsce,Wyjscie):- usun1(Miejsce-1,Wszystkie,Wyjscie). %%%%%%%%%%%%%%%%%%%%% Depend_set%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkDepend(A):- nalezy(element(ard,_,L1),A), dlugosc(L1,D1),wyswietlDepe(L1,D1,0). wyswietlDepe(L1,0,Dl). wyswietlDepe(L1,D1,Dl):- D1>0, NewDlu is D1-1, usun1(Dl,L1,element(dep,[independent=Ind,dependent=Dep],[])), sprawdzDep(Ind,Dep,Indep,Depen),assert(ard_depend(Indep,Depen)), DlNew is Dl+1, wyswietlDepe(L1,NewDlu,DlNew). %%%%%%%%%%%%%% pobrac independent i dependent%%%%%%%%%%%%%% sprawdzDep(In,De,InOut,DeOut):- atom_number(In,Inn), atom_number(De,Depe), zobacz(Wszystkie), wyswietlDependent(Wszystkie,Inn,InOut), wyswietlDependent(Wszystkie,Depe,DeOut). wyswietlDependent(Wszystkie,1,Wyjscie):- usun1(0,Wszystkie,Wyjscie). wyswietlDependent(Wszystkie,Miejsce,Wyjscie):- usun1(Miejsce-1,Wszystkie,Wyjscie). %%%%%%%%%%%%%%%%%%%%%%%%%%% Pozostałe %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nalezy(X,[X|_]). nalezy(X,[_|Yogon]) :- nalezy(X,Yogon). dlugosc([],0). dlugosc([_|Ogon],Dlug) :- dlugosc(Ogon,X), Dlug is X+1. usun1(0,[F|_],F). usun1(Poz,[_|Xx],W):- Poz>0, PozNew is Poz-1, usun1(PozNew,Xx,W). dodaj([],X,[X]). dodaj([G|O],X,[G|R]):- dodaj(O,X,R). Plik do parsowania: {{:pl:miw:ard-vardy.xml|:pl:miw:ard-vardy.xml}} ====Varda wersja 1==== Translator można uruchomić na kilka sposobów: ===1=== Załadować plik źródłowy i wpisać : translate('Source.xml','Destination.xml'). Otrzymamy wydruk na ekranie monitora oraz, zapis do wskazanego pliku. ===2 === Załadować plik źródłowy i wpisać : translate('Source.xml'). Otrzymamy wydruk na ekranie monitora, jeśli będziemy chcieli zapisać do pliku to należy wpisać: save('Destination.xml'). === 3 === Można połączyć translator bezpośrednio z vardą umieszczając odpowiedni wpis w pliku "VARDA.pl", ":-ensure_loaded('varda_pl2xml').", dzięki temu no załadowaniu vardy i wygenerowaniu pliku przy pomocy axg, możemy bezpośrednio translatować xml. Poniżej znajdujesię kod translatora. %%%%%%%%%%%%%%%%%%%%% Load %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% translate(Source,Dest):- load_structure(Source,X,[space(remove),dialect(xml)]), %załadowanie pliku Z=..X,assertz(Z),element(hml,_,A), %wyciągnięcie elementu hml checkAtt(A), %analiza elementu "attribute_set" checkProperty(A), %analiza elementu "property_set" checkHistory(A), %analiza elementu "tph" checkDepend(A), %analiza elementu "ard" show, % wyświetlenie wyników save(Dest). %zapis wyniku translate(Source):- load_structure(Source,X,[space(remove),dialect(xml)]),Z=..X,assertz(Z),element(hml,_,A), checkAtt(A),checkProperty(A),checkHistory(A),checkDepend(A),show. %%%%%%%%%%%% Wyswietl%%%%%%%%%%%%%%% show:- listing(ard_att),listing(ard_property),listing(ard_hist),listing(ard_depend). %%%%%%%%%%%%%%%%%%%%%%%%%%% Save to file %%%%%%%%%%%%%%%%%%%%%% save(Dest):- tell(Dest),write(''), listing(ard_att),listing(ard_property),listing(ard_hist), listing(ard_depend),told. %%%%%%%%%%%%%%%%%%%%% Attribute_set%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkAtt(A):- include(element(attribute_set,_,Li),A), % sprawdzanie istnienia elementu leng(Li,Dl1), % wylicznie dlugości listy assert(viewList(_)), % deklarowanie pamięci showAtt(Li,Dl1,0). showAtt(_,0,_). showAtt(L,D1,Dl):- D1>0, NewDlu is D1-1, deleteOne(Dl,L,element(att,[name=ZX,_,_,_],[])), assert(memory(ZX)), memory(ZX), assert(ard_att(ZX)), viewList(LisGlob),add(LisGlob,ZX,LisGlob2), retractall(viewList(_)), assert(viewList(LisGlob2)), retractall(memory(_)), DlNew is Dl+1, showAtt(L,NewDlu,DlNew). %%%%%%%%%%%%%%%%%%%%% Property_set %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkProperty(A):- include(element(property_set,_,L),A), leng(L,D), assert(view(_)), showProp(L,D,0). showProp(_,0,_). showProp(L2,D2,Dl2):- D2>0, NewDlu2 is D2-1, deleteOne(Dl2,L2,element(property,_,C)), leng(C,CA), writeProp(CA,C,[]),memoryList(Lista),assert(ard_property(Lista)), view(ListaGlob),add(ListaGlob,Lista,ListaGlob2), retractall(view(_)), assert(view(ListaGlob2)), retractall(memoryList(_)), DlNew2 is Dl2+1, showProp(L2,NewDlu2,DlNew2). writeProp(0,_,_). writeProp(CA,[J1|L1],Lel):- CA>0, CNew is CA-1, showFirst(J1,element(attref, [ref=Bb], [])), string_length(Bb,L), LEEE is L-4, sub_string(Bb,4,LEEE,_,WYJ), checkProp(WYJ,Insert), add(Lel,Insert,Lista1), retractall(memoryList(_)), assert(memoryList(Lista1)), writeProp(CNew,L1,Lista1). showFirst(L,L). %%%%%%%%% checkProp(Output,Name):- atom_number(Output,Wyj), viewList(All), NWyj is Wyj+1, showName(All,NWyj,Name). showName(All,1,Name):- deleteOne(0,All,Name). showName(All,Wyj,Name):- deleteOne(Wyj-1,All,Name). %%%%%%%%%%%%%%%%%%%%% Hist_set %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkHistory(A):- include(element(tph,_,L1),A), leng(L1,D1),showlHist(L1,D1,0). showlHist(_,0,_). showlHist(L1,D1,Dl):- D1>0, NewDlu is D1-1, deleteOne(Dl,L1,element(trans,[src=Source,dst=Destination],[])), string_length(Source,L), LEEE is L-4, sub_string(Source,4,LEEE,_,WYJ), string_length(Destination,LG), LEEEE is LG-4, sub_string(Destination,4,LEEEE,_,Output), checkHist(WYJ,Output,Z,D),assert(ard_hist(Z,D)), DlNew is Dl+1, showlHist(L1,NewDlu,DlNew). %%%%%%%%%%%%%% Get src i des t%%%%%%%%%% checkHist(Zr,De,Zrod,Dest):- atom_number(Zr,Zrr), atom_number(De,Dee), view(All), NZrr is Zrr+1, NDee is Dee+1, showPropert(All,NZrr,Zrod), showPropert(All,NDee,Dest). showPropert(All,1,Output):- deleteOne(0,All,Output). showPropert(All,Position,Output):- deleteOne(Position-1,All,Output). %%%%%%%%%%%%%%%%%%%%% Depend_set %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% checkDepend(A):- include(element(ard,_,LisDep),A), leng(LisDep,DlDep),wyswietlDepe(LisDep,DlDep,0). wyswietlDepe(_,0,_). wyswietlDepe(L1,D1,Dl):- D1>0, NewDlu is D1-1, deleteOne(Dl,L1,element(dep,[independent=Ind,dependent=Dep],[])), string_length(Ind,L), LEEE is L-4, sub_string(Ind,4,LEEE,_,WYJ), string_length(Dep,LENG), LEE is LENG-4, sub_string(Dep,4,LEE,_,Output), checkDep(WYJ,Output,Indep,Depen),assert(ard_depend(Indep,Depen)), DlNew is Dl+1, wyswietlDepe(L1,NewDlu,DlNew). %%%%%%%%%%%%%% Get independent i dependent %%%%%%%%%%%%%% checkDep(In,De,InOut,DeOut):- atom_number(In,Inn), atom_number(De,Depe), view(All), NInn is Inn+1, NDepe is Depe+1, showDependent(All,NInn,InOut), showDependent(All,NDepe,DeOut). showDependent(All,1,Output):- deleteOne(0,All,Output). showDependent(All,Position,Output):- deleteOne(Position-1,All,Output). %%%%%%%%%%%%%%%%%%%%%%%%%%% Others %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % sprawdzanie istnienia elementów w liście include(X,[X|_]). include(X,[_|Tail]) :- include(X,Tail). % obliczanie długości listy leng([],0). leng([_|Tail],Dlug) :- leng(Tail,X), Dlug is X+1. % wyciąganie konkretnego elementu listy deleteOne(0,[F|_],F). deleteOne(Poz,[_|Xx],W):- Poz>0, PozNew is Poz-1, deleteOne(PozNew,Xx,W). % dodanie do listy add([],X,[X]). add([G|O],X,[G|R]):- add(O,X,R). {{:pl:miw:varda_pl2xml.pl|Translator}} {{:pl:miw:input.xml|Plik wejściowy}} {{:pl:miw:out.pl|Plik wyjściowy}} Dla potrzeb wyświetlenia wyników plik wyjściowy został powyżej dołączony z rozszerzeniem pl. ====Napotkane problemy==== ===Usunięcie białych znaków=== W pliku mamy znaczniki nowej lini np:('\n','\n ','\n ') bez ich usunięcia nie można dotrzeć do wnętrza pliku. Korzystajac z "usun" usun(X,[X|Reszta],Reszta). usun(X,[Y|Ogon],[Y|Reszta]) :- usun(X,Ogon,Reszta). nie daje oczekiwanych efektów. element(hml,X,C),usun('\n',C,B),write(B). nie usuwa wszystkich znaków lecz tylko ostatni. http://www.swi-prolog.org/packages/sgml2pl.html#sec:sec-3.1 http://www.swi-prolog.org/packages/sgml2pl.html#sec:space space(sgml) In SGML, newlines at the start and end of an element are removed.2 This is the default mode for the SGML dialect. space(default) In addition to sgml space-mode, all consequtive white-space is reduced to a single space-character. This mode canonises all white space. Za pomocą poniższego kodu ładuję plik usuwając spacje oraz znaczniki końca lini: load_structure('ard.xml',X,[space(remove),dialect(xml)]),Z=..X,assertz(Z). ===Sprawdzanie długości stringów=== W porównaniu z Varda w wersji 0, należało znależć i zastosować odpowiednie predykaty: string_lenht/2 oraz sub_string/4. string_length(Bb,L), LEEE is L-4, sub_string(Bb,4,LEEE,_,WYJ), ===Rzutowanie z stringa na inta=== atom_number(Zr,Zrr) ===Wyciąganie konkretnego elementu z listy=== Wyciąganie odpowiednich elementów z listy wykonywałem poniższym predykatem. deleteOne(0,[F|_],F). deleteOne(Poz,[_|Xx],W):- Poz>0, PozNew is Poz-1, deleteOne(PozNew,Xx,W). ===Przechowywanie listy w pamięci=== W pamięciu przechowwane sa wszystkie atrybuty. writeProp(CA,C,[]),memoryList(Lista),assert(ard_property(Lista)), view(ListaGlob),add(ListaGlob,Lista,ListaGlob2), retractall(view(_)), assert(view(ListaGlob2)), retractall(memoryList(_)), ===Podczas kompilacji=== Podczas kompilacji otrzymuję komunikat, który jednak nie ma wpływu na otrzymany wynik translacji. ERROR: SGML2PL(xml): input.xml:2: file ".\hml.dtd" does not exist Błąd ten dotyczy linijki, która pojawiła sie w wersji 1 Vardy. ====Otrzymany wynik translacji==== Otrzymujemy następujący efekt: :- dynamic ard_att/1. ard_att('Thermostat'). ard_att('Time'). ard_att('Temperature'). ard_att('Date'). ard_att('Hour'). ard_att(season). ard_att(operation). ard_att(thermostat_settings). ard_att(day). ard_att(month). ard_att(today). ard_att(hour). :- dynamic ard_property/1. ard_property(['Thermostat']). ard_property(['Time', 'Temperature']). ard_property(['Time']). ard_property(['Temperature']). ard_property(['Date', 'Hour', season, operation]). ard_property(['Date', 'Hour']). ard_property([season, operation]). ard_property([thermostat_settings]). ard_property([season]). ard_property([operation]). ard_property(['Date']). ard_property(['Hour']). ard_property([day, month, today]). ard_property([month]). ard_property([day, today]). ard_property([day]). ard_property([today]). ard_property([hour]). :- dynamic ard_hist/2. ard_hist(['Thermostat'], ['Time', 'Temperature']). ard_hist(['Time', 'Temperature'], ['Time']). ard_hist(['Time', 'Temperature'], ['Temperature']). ard_hist(['Time'], ['Date', 'Hour', season, operation]). ard_hist(['Date', 'Hour', season, operation], ['Date', 'Hour']). ard_hist(['Date', 'Hour', season, operation], [season, operation]). ard_hist(['Temperature'], [thermostat_settings]). ard_hist([season, operation], [season]). ard_hist([season, operation], [operation]). ard_hist(['Date', 'Hour'], ['Date']). ard_hist(['Date', 'Hour'], ['Hour']). ard_hist(['Date'], [day, month, today]). ard_hist([day, month, today], [month]). ard_hist([day, month, today], [day, today]). ard_hist([day, today], [day]). ard_hist([day, today], [today]). ard_hist(['Hour'], [hour]). :- dynamic ard_depend/2. ard_depend([season], [thermostat_settings]). ard_depend([operation], [thermostat_settings]). ard_depend([month], [season]). ard_depend([day], [today]). ard_depend([today], [operation]). ard_depend([hour], [operation]). ====XTT - RIF==== * [[pl:miw:miw08_xtt_rif|XTT i RIF]] [, element(xtt_table, [id=xtt_1], [ , element(schema, [], [ , element(independent, [], [ , element(attref, [ref=att_0], []), ]), , element(dependent, [], [ , element(attref, [ref=att_1], []), ]), ]), , element(rule, [id=rul_1], [ , element(condition, [], [ , element(logop, [name=in], [ , element(attref, [ref=att_0], []), , element(domain, [], [ , element(range, [from=1, to=5], []), , element(value, [], [8]), ]), ]), ]), , element(decision, [], [ , element(modop, [name=assign], [ , element(attref, [ref=att_1], []), , element(evalop, [name=add], [ , element(attref, [ref=att_0], []), , element(domain, [], [ , element(value, [], [1]), ]), ]), ]), , element(modop, [name=assign], [ , element(attref, [ref=att_1], []), , element(evalop, [name=add], [ , element(domain, [], [ , element(value, [], [5]), ]), , element(evalop, [name=sin], [ , element(attref, [ref=att_0], []), ]), ]), ]), ]), , element(link, [xtt=xtt_1], []), ]), ]), ] ====== Materiały ====== [[http://www.w3.org/Style/XSL/|XSLT]] (tutoriale): * [[http://zvon.org/xxl/XSLTutorial/Output/index.html|ZVON XSLT]] * [[http://w3schools.com/xsl/default.asp|W3S XSLT]] ==PROLOG== * [[http://eclipse.crosscoreop.com:8080/doc/bips/lib_public/xml/index.html|Library(xml)]] * [[http://www.zen37763.zen.co.uk/xml.pl.html|Parsing XML with Prolog]] * [[http://www.gprolog.org/manual/gprolog.html|GNU PROLOG]] * [[http://www.zen37763.zen.co.uk/xml_download.html|XML In Prolog]] ==GRAPHVIZ== * [[http://www.cs.bris.ac.uk/Teaching/Resources/COMS30106/graphviz/|Graphviz]] * [[http://www.graphviz.org/|Graphviz]] ==RIF== * [[http://www.w3.org/2005/rules/wg/charter.html|RIF]] * [[http://en.wikipedia.org/wiki/Rule_Interchange_Format|RIF- wikipedia]] * [[http://www.w3.org/TR/rif-bld/|RIF]] ==XML,XSD== * [[http://www.komputery-internet.net/xml/|XML, DTD, XSD, XSLT- wprowadzenie]] * [[http://www.codeguru.pl/article-319.aspx|Opis struktury schematu XML]]