Both sides previous revision
Poprzednia wersja
|
|
pl:miw:miw08_prolog_xml [2008/06/14 11:32] gjn |
pl:miw:miw08_prolog_xml [2019/06/27 15:50] (aktualna) |
| ====== Opis ====== |
| __**Projekt zakończony**__ |
| |
| Wojciech Szymański <wojtek.szym@gmail.com> |
| |
| Omówić metody parsowania, generowania i przetwarzania XML/SGML w Prologu. Należy również zająć się reprezentacjami pochodnymi opartymi na XML, np. RDF. |
| |
| Porównać dostępne rozwiązania i implementacje, np: |
| * SWI |
| * inne, np. YAP, Amzi. |
| |
| Wsparcie dla |
| * XSD |
| * namespaces |
| * XSL |
| * DOM |
| |
| |
| |
| ====== Spotkania ====== |
| [[pl:miw:miw08_prolog_xml:spotkania|Spotkania]] |
| |
| |
| |
| |
| |
| ====== Sprawozdanie ====== |
| |
| |
| ===== Wstęp - ogólne informacje ===== |
| |
| Celem projektu było omówienie metod parsowania, generowania oraz przetwarzania XML/SGML w Prologu. Należało porównać i przetestować dostępne rozwiązania oraz sprawdzić czy posiadają wsparcie dla DOM, XSD, XSL oraz namespaces. Istotną częścią projektu była implementacja własnego API przeznaczonego do tworzenia dokumentów XML w SWI-Prolog. Okazało się bowiem, że dostępne rozwiązania posiadają przede wszystkim dobre mechanizmy parsowania dokumentu (tworzenia postaci prologowej) oraz jego przetwarzania - zamiany postaci prologowej na dokument XML, natomiast nie posiadają wsparcia dla generowania XML opartego o standard DOM. |
| |
| |
| |
| |
| |
| |
| |
| ===== Parsowanie i przetwarzanie prostych dokumentów XML w prologu ===== |
| |
| Istnieje wiele implementacji prologu posiadających wsparcie dla generowania i przetwarzania dokumentów XML. Dostępne są zarówno wersje płatne, które można przetestować (np. 30-dniowe wersje) oraz wersje bezpłatne. |
| |
| W celu przetestowania parsowania oraz przetwarzania plików XML przygotowano następujący, prosty plik XML: |
| <code xml> |
| <CD> |
| <TITLE>Empire Burlesque</TITLE> |
| <ARTIST>Bob Dylan</ARTIST> |
| <COUNTRY>USA</COUNTRY> |
| <COMPANY>Columbia</COMPANY> |
| <PRICE>10.90</PRICE> |
| <YEAR>1985</YEAR> |
| <TITLE>Hide your heart</TITLE> |
| <ARTIST>Bonnie Tylor</ARTIST> |
| <COUNTRY>UK</COUNTRY> |
| <COMPANY>CBS Records</COMPANY> |
| <PRICE>9.90</PRICE> |
| <YEAR>1988</YEAR> |
| <TITLE>Greatest Hits</TITLE> |
| <ARTIST>Dolly Parton</ARTIST> |
| <COUNTRY>USA</COUNTRY> |
| <COMPANY>RCA</COMPANY> |
| <PRICE>9.90</PRICE> |
| <YEAR>1982</YEAR> |
| <TITLE>Still got the blues</TITLE> |
| <ARTIST>Gary More</ARTIST> |
| <COUNTRY>UK</COUNTRY> |
| <COMPANY>Virgin redords</COMPANY> |
| <PRICE>10.20</PRICE> |
| <YEAR>1990</YEAR> |
| </code> |
| |
| Przetestowano następujące implementacje prologu: SWI-Prolog, BProlog, Amzi! Prolog, MINERVA, JIProlog oraz YAP Prolog. |
| |
| |
| |
| |
| ==== SWI-Prolog ==== |
| |
| SWI-Prolog posiada pakiet //**sgml2pl**// - [[http://www.swi-prolog.org/packages/sgml2pl.html|SWI-Prolog SGML/XML parser]]. Pakiet ten posiada możliwości parsowania dokumentów XML wraz z namespaces oraz plików XML opartych o model DOM. Podstawowym predykatem służącym do parsowania jest: //**load_xml_file(+File,-ListOfContents)**//. Natomiast predykat służący do przetworzenia postaci prologowej na dokument XML ma postać: //**xml_write(+Stream, +Term, +Options)**//. |
| |
| Po wpisaniu w prologu: |
| <code prolog> |
| ?- load_xml_file('cd.xml',T). |
| </code> |
| otrzymano: |
| <code prolog> |
| T = [element('CD', [], [ |
| element('TITLE', [], ['Empire Burlesque']), |
| element('ARTIST', [], ['Bob Dylan']), |
| element('COUNTRY', [], ['USA']), |
| element('COMPANY', [], ['Columbia']), |
| element('PRICE', [], ['10.90']), |
| element('YEAR', [], [...]), |
| element(..., ..., ...)|...])] |
| </code> |
| W celu przetworzenia z powrotem postaci prologowej do postaci XML wpisujemy: |
| <code prolog> |
| ?- load_xml_file('cd.xml',L),tell('cd1.xml'),open('cd1.xml',write,S),xml_write(S,L,[]),told,close(S). |
| </code> |
| i otrzymujemy dokument XML o nazwie cd1 stanowiący kopię dokumentu cd.xml (Dokument został sparsowany, a następnie zapisany do pliku o nowej nazwie ). |
| |
| |
| |
| |
| |
| |
| ==== BProlog ==== |
| Implementacja BProlog posiada bibliotekę o nazwie //**xml.pl**//. Podstawowym predykatem do parsowania plików XML jest: //**xml2pl(Input,Output)**//. Jako parametr //Input// podajemy plik XML, a jako //Output// - plik, w którym chcemy zapisać prologową strukturę XML. |
| Poniżej przedstawiono kroki w celu otrzymania struktury XML: |
| - Komenda //**cd(Dir)**// ustala ścieżkę, w której pracujemy, np. //**cd('C:/BProlog/Tools')**//. Tam muszą więc znajdować sie zarówno pilik XML jak i plik biblioteki 'xml.pl'. |
| - Komenda //**cl(File)**// kompiluje i ładuje program, np. //**cl('xml.pl')**// kompiluje i ładuje bibliotekę 'xml.pl'. |
| - Dalej posługujemy się predykatem, np. //**xml2pl('cd.xml','nowy.pl')**// tworzy plik //nowy.pl// zawierający postać prologową pliku cd.xml. |
| |
| Poniżej przedstawiono wygenerowaną postać w prologu: |
| <code prolog> |
| xml( [version="1.0", encoding="ISO-8859-1", standalone="no"], |
| [ |
| doctype( 'CD', system( "cd.dtd" ) ), |
| element( 'CD', |
| [], |
| [ |
| element( 'TITLE',[],[pcdata("Empire Burlesque")] ), |
| element( 'ARTIST',[],[pcdata("Bob Dylan")] ), |
| element( 'COUNTRY',[],[pcdata("USA")] ), |
| element( 'COMPANY',[],[pcdata("Columbia")] ), |
| element( 'PRICE',[],[pcdata("10.90")] ), |
| element( 'YEAR',[],[pcdata("1985")] ), |
| element( 'TITLE',[],[pcdata("Hide your heart")] ), |
| element( 'ARTIST',[],[pcdata("Bonnie Tylor")] ), |
| element( 'COUNTRY',[],[pcdata("UK")] ), |
| element( 'COMPANY',[],[pcdata("CBS Records")] ), |
| element( 'PRICE',[],[pcdata("9.90")] ), |
| element( 'YEAR',[],[pcdata("1988")] ), |
| element( 'TITLE',[],[pcdata("Greatest Hits")] ), |
| element( 'ARTIST',[],[pcdata("Dolly Parton")] ), |
| element( 'COUNTRY',[],[pcdata("USA")] ), |
| element( 'COMPANY',[],[pcdata("RCA")] ), |
| element( 'PRICE',[],[pcdata("9.90")] ), |
| element( 'YEAR',[],[pcdata("1982")] ), |
| element( 'TITLE',[],[pcdata("Still got the blues")] ), |
| element( 'ARTIST',[],[pcdata("Gary More")] ), |
| element( 'COUNTRY',[],[pcdata("UK")] ), |
| element( 'COMPANY',[],[pcdata("Virgin redords")] ), |
| element( 'PRICE',[],[pcdata("10.20")] ), |
| element( 'YEAR',[],[pcdata("1990")] ) |
| ] ) |
| ] ). |
| </code> |
| Do przetworzenia postaci prologowej na dokument XML służy predykat: //**pl2xml(Document,Codes).**// |
| |
| |
| |
| ==== Amzi! Prolog ==== |
| Wersja prologu Amzi! jest możliwa do ściągnięcia jako wersja "Free (Never Expires)". Za inne wersje trzeba płacić. Amzi! Prolog posiada bibliotekę obsługującą pliki XML:[[http://www.amzi.com/manuals/amzi7/libs/xml.htm|XML.pro]]. |
| Niestety nie udało sie skorzystać z wyżej wymienionej biblioteki. |
| |
| |
| |
| |
| |
| |
| ==== MINERVA ==== |
| Minerva jest licencjonowanym produktem firmy IF Computer Japan. Jest możliwe posiadanie licencji ewaluacyjnej (wolnej od opłaty) ważnej na okres 2 miesięcy. Minerva może być nazwana jako Java Prolog ponieważ dostarcza funkcjonalności Prologu jako klasa Javy. |
| |
| Podstawowymi predykatami związanymi z parsowaniem i przetwarzaniem dokumentów XML są: |
| * //**read_xml(XmlStream, XmlTerm)**// - parsowanie pliku XML do postaci prologowej. |
| * //**write_xml(Stream, XmlTerm)**// - przetwarzanie postaci prologowej do pliku XML. |
| |
| Niestety nie przetestowano użycia wyżej wymienionych predykatów. Patrząc jednak na przykłady udostępnione na stronie domowej MINERVY funkcjonalności zaproponowane przez ten produkt nie różnią się od tych użytych np. w SWI-Prolog. |
| |
| Przykładem może być wygenerowana prologowa struktura dokumentu XML po sparsowaniu dokumentu korzystając z predykatu //**read_xml(XmlStream, XmlTerm)**//. |
| |
| <code prolog> |
| document([xml([version = '1.0'])], |
| element(addressbook,[],[ |
| element(address,[telno = '1234567'],[ |
| element(name,[],[chardata('John')]), |
| element(age,[],[chardata('35')])]), |
| element(address,[telno = '3456789',email = 'henriette@ifcomputer.com'],[ |
| element(name,[],[chardata('Henriette')]), |
| element(age,[],[chardata('27')])])]),[]) |
| </code> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| ==== JIProlog ==== |
| JIProlog jest bezpłatnym interpreterem prologu integrującym języki Java i Prolog. Podczas działania wyświetla się tylko napis informujący użytkownika, że posiada wersje shareware unregistered. JIProlog posiada bibliotekę //**jipxxml**// do obsługi plików XML zgodnych z modelem DOM. Podstawowymi predykatami służącymi do parsowania i przetwarzania plików XML są |
| * //**xml_read_document(X)**// - parsowanie dokumentu XML do postaci prologu |
| * //**xml_write_document(XMLDoc)**// - przetwarzanie postaci prologowej do pliku XML |
| |
| Aby sparsować dokument XML należy kolejno: |
| - Załadować bibliotekę do obsługi XML - //**load_library('jipxxml.jar').**// |
| - Załadować bibliotekę do obsługi input/output plików - //**load_library('jipxio.jar').**// |
| - Otworzyć dokument XML - //**see('cd.xml').**// |
| - Użyć predykatu: //**xml_read_document(X)**// |
| |
| Poniżej przedstawiono wygenerowany plik w postaci prologowej: |
| <code prolog> |
| X = xml_document([[version = 1.0, encoding = UTF-8], |
| xml_doctype(CD, [SYSTEM = cd.dtd], [])], |
| xml_element(CD, [], |
| [xml_element(TITLE, [], [xml_text(Empire Burlesque)]), |
| xml_element(ARTIST, [], [xml_text(Bob Dylan)]), |
| xml_element(COUNTRY, [], [xml_text(USA)]), |
| xml_element(COMPANY, [], [xml_text(Columbia)]), |
| xml_element(PRICE, [], [xml_text(10.90)]), |
| xml_element(YEAR, [], [xml_text(1985)]), |
| xml_element(TITLE, [], [xml_text(Hide your heart)]), |
| xml_element(ARTIST, [], [xml_text(Bonnie Tylor)]), |
| xml_element(COUNTRY, [], [xml_text(UK)]), |
| xml_element(COMPANY, [], [xml_text(CBS Records)]), |
| xml_element(PRICE, [], [xml_text(9.90)]), |
| xml_element(YEAR, [], [xml_text(1988)]), |
| xml_element(TITLE, [], [xml_text(Greatest Hits)]), |
| xml_element(ARTIST, [], [xml_text(Dolly Parton)]), |
| xml_element(COUNTRY, [], [xml_text(USA)]), |
| xml_element(COMPANY, [], [xml_text(RCA)]), |
| xml_element(PRICE, [], [xml_text(9.90)]), |
| xml_element(YEAR, [], [xml_text(1982)]), |
| xml_element(TITLE, [], [xml_text(Still got the blues)]), |
| xml_element(ARTIST, [], [xml_text(Gary More)]), |
| xml_element(COUNTRY, [], [xml_text(UK)]), |
| xml_element(COMPANY, [], [xml_text(Virgin redords)]), |
| xml_element(PRICE, [], [xml_text(10.20)]), |
| xml_element(YEAR, [], [xml_text(1990)]) |
| ])) |
| </code> |
| |
| JIProlog posiada również szereg predykatów związanych z budowaniem plików XML zgodnych z modelem DOM. Najważniejszymi predykatami są: |
| * //**xml_element(Name, Attributes, Children, ElementTerm)**// - tworzenie węzła, obiektu typu element |
| * //**xml_attribute(Name, Value, AttributeTerm)**// - tworzenie obiektu typu atrybut |
| * //**xml_text(Content, TextTerm)**// - tworzenie obiektu typu Text |
| * //**xml_append_child(Child, Element, NewElement)**// - dodawanie dziecka |
| * //**xml_append_attribute(Attribute, Element, NewElement)**// - dodawanie atrybutu |
| * //**xml_document(Version, Encoding, DocType, Root, DocumentTerm)**// - tworzenie obiektu typu Dokument XML |
| |
| Poniżej zamieszczono przykład budowania prostego pliku XML z użyciem wyżej wymienionych predykatów: |
| <code prolog> |
| create_xml_file(X):- |
| tell(X), |
| % create root element |
| xml_element('music_shop', [], [], Root), |
| % create child 1n |
| xml_element('cd', [], [], Cd1), |
| %create attributes |
| xml_attribute('artist', 'Bob Dylan', Att1), |
| xml_attribute('title', 'Empire Burlesque', Att2), |
| xml_attribute('price', '10.90', Att3), |
| % append attributes |
| xml_append_attribute(Att1, Cd1, Cd11), |
| xml_append_attribute(Att2, Cd11, Cd12), |
| xml_append_attribute(Att3, Cd12, Cd13), |
| % create child |
| xml_text('Music CD', Title1), |
| % append child |
| xml_append_child(Title1, Cd13, Cd14), |
| % append children to root |
| xml_append_child(Cd14, Root, Root1), |
| % create document |
| xml_document('1.0', [], [], Root1, Doc), |
| xml_write_document(Doc), |
| told. |
| </code> |
| |
| Z powyższego przykładu otrzymano następujący plik XML: |
| {{:pl:miw:music.xml|Plik XML}} |
| |
| |
| |
| |
| ==== YAP Prolog ==== |
| Wersja YAP Prolog jest bezpłatna w użyciu w środowiskach akademickich. YAP Prolog dysponuje biblioteką posiadającą możliwości związane z parsowaniem i przetwarzaniem plików XML/HTML [[http://www.clip.dia.fi.upm.es/Software/pillow/pillow.html|The PiLLoW Web Programming Library ]]. |
| |
| Wersje tej biblioteki są dostępne zarówno dla YAP Prolog jak i dla SWI Prolog oraz Ciao Prolog. |
| |
| Jeśli chodzi o predykaty związane z XML jest dostępny: //**xml2terms(String,Terms)**//[[http://www.clip.dia.fi.upm.es/Software/pillow/pillow_doc_html/pillow_doc_3.html#SEC5|xml2terms]] |
| |
| Predykat ten wykorzystuje się na dwa sposoby: |
| - translacja XML-term'u do kodu XML |
| - translacja kodu XML do strukturalnego termu XML'owego |
| |
| |
| ===== Porównanie prologowych postaci dokumentu XML ===== |
| |
| Porównanie przeprowadzono dla pliku XML wygenerowanego z systemu VARDA-M_1.{{:pl:miw:varda_thermostat.xml|Thermostat}} |
| |
| Do porównania zdecydowano się wykorzystać następujące wersje prologu. |
| |
| - SWI-Prolog - [[http://www.swi-prolog.org/packages/sgml2pl.html]] |
| - BProlog - [[http://www.probp.com/publib/xml.html]] |
| - JIProlog - [[http://www.ugosweb.com/jiprolog/index.aspx]] |
| |
| Wersje te nie posiadają żadnych ograniczeń w użyciu. |
| |
| Otrzymano następujące wyniki: |
| |
| ==== SWI-Prolog ==== |
| |
| |
| Plik XML po sparsowaniu w SWI Prologu za pomocą predykatu //load_xml_file('therm.xml',X)// jest w postaci listy, która składa się z zagnieżdżonych struktur typu //**element(Node_Name, [Value], [child_element])**//, gdzie argumentami są: |
| * //**Node_Name**// - nazwa węzła |
| * //**[Value]**// - lista atrybutów węzła |
| * //**[child_element]**// - lista kolejnych elementów - dzieci lub tekst węzła |
| |
| Poniżej przedstawiono sparsowany plik XML w SWI-Prolog: |
| <code prolog> |
| X = [element(hml, [], [ |
| , element(type_set, [], []), |
| , element(attribute_set, [], [ |
| , element(att, [name=Thermostat, id=att_0, value=single, class=ro], []), |
| , element(att, [name=Time, id=att_1, value=single, class=ro], []), |
| , element(att, [name=Temperature, id=att_2, value=single, class=ro], []), |
| , element(att, [name=Date, id=att_3, value=single, class=ro], []), |
| , element(att, [name=Hour, id=att_4, value=single, class=ro], []), |
| , element(att, [name=season, id=att_5, value=single, class=ro], []), |
| , element(att, [name=operation, id=att_6, value=single, class=ro], []), |
| , element(att, [name=thermostat_settings, id=att_7, value=single, class=ro], []), |
| , element(att, [name=day, id=att_8, value=single, class=ro], []), |
| , element(att, [name=month, id=att_9, value=single, class=ro], []), |
| , element(att, [name=today, id=att_10, value=single, class=ro], []), |
| , element(att, [name=hour, id=att_11, value=single, class=ro], []), |
| ]), |
| , element(property_set, [], [ |
| , element(property, [id=prp_0], [ |
| , element(attref, [ref=att_0], []), |
| ]), |
| , element(property, [id=prp_1], [ |
| , element(attref, [ref=att_1], []), |
| , element(attref, [ref=att_2], []), |
| ]), |
| , element(property, [id=prp_2], [ |
| , element(attref, [ref=att_1], []), |
| ]), |
| , element(property, [id=prp_3], [ |
| , element(attref, [ref=att_2], []), |
| ]), |
| , element(property, [id=prp_4], [ |
| , element(attref, [ref=att_3], []), |
| , element(attref, [ref=att_4], []), |
| , element(attref, [ref=att_5], []), |
| , element(attref, [ref=att_6], []), |
| ]), |
| , element(property, [id=prp_5], [ |
| , element(attref, [ref=att_3], []), |
| , element(attref, [ref=att_4], []), |
| ]), |
| , element(property, [id=prp_6], [ |
| , element(attref, [ref=att_5], []), |
| , element(attref, [ref=att_6], []), |
| ]), |
| , element(property, [id=prp_7], [ |
| , element(attref, [ref=att_7], []), |
| ]), |
| , element(property, [id=prp_8], [ |
| , element(attref, [ref=att_5], []), |
| ]), |
| , element(property, [id=prp_9], [ |
| , element(attref, [ref=att_6], []), |
| ]), |
| , element(property, [id=prp_10], [ |
| , element(attref, [ref=att_3], []), |
| ]), |
| , element(property, [id=prp_11], [ |
| , element(attref, [ref=att_4], []), |
| ]), |
| , element(property, [id=prp_12], [ |
| , element(attref, [ref=att_8], []), |
| , element(attref, [ref=att_9], []), |
| , element(attref, [ref=att_10], []), |
| ]), |
| , element(property, [id=prp_13], [ |
| , element(attref, [ref=att_9], []), |
| ]), |
| , element(property, [id=prp_14], [ |
| , element(attref, [ref=att_8], []), |
| , element(attref, [ref=att_10], []), |
| ]), |
| , element(property, [id=prp_15], [ |
| , element(attref, [ref=att_8], []), |
| ]), |
| , element(property, [id=prp_16], [ |
| , element(attref, [ref=att_10], []), |
| ]), |
| , element(property, [id=prp_17], [ |
| , element(attref, [ref=att_11], []), |
| ]), |
| ]), |
| , element(tph, [], [ |
| , element(trans, [src=prp_0, dst=prp_1], []), |
| , element(trans, [src=prp_1, dst=prp_2], []), |
| , element(trans, [src=prp_1, dst=prp_3], []), |
| , element(trans, [src=prp_2, dst=prp_4], []), |
| , element(trans, [src=prp_4, dst=prp_5], []), |
| , element(trans, [src=prp_4, dst=prp_6], []), |
| , element(trans, [src=prp_3, dst=prp_7], []), |
| , element(trans, [src=prp_6, dst=prp_8], []), |
| , element(trans, [src=prp_6, dst=prp_9], []), |
| , element(trans, [src=prp_5, dst=prp_10], []), |
| , element(trans, [src=prp_5, dst=prp_11], []), |
| , element(trans, [src=prp_10, dst=prp_12], []), |
| , element(trans, [src=prp_12, dst=prp_13], []), |
| , element(trans, [src=prp_12, dst=prp_14], []), |
| , element(trans, [src=prp_14, dst=prp_15], []), |
| , element(trans, [src=prp_14, dst=prp_16], []), |
| , element(trans, [src=prp_11, dst=prp_17], []), |
| ]), |
| , element(ard, [], [ |
| , element(dep, [independent=prp_8, dependent=prp_7], []), |
| , element(dep, [independent=prp_9, dependent=prp_7], []), |
| , element(dep, [independent=prp_13, dependent=prp_8], []), |
| , element(dep, [independent=prp_15, dependent=prp_16], []), |
| , element(dep, [independent=prp_16, dependent=prp_9], []), |
| , element(dep, [independent=prp_17, dependent=prp_9], []), |
| ]), |
| ])] |
| |
| </code> |
| |
| |
| ==== BProlog ==== |
| |
| |
| Dokumenty XML po sparsowaniu w BProlog'u posiadają strukturę w postaci termu: |
| |
| //**xml([version, encoding],[ element(...)])**// |
| |
| Argumentami są: |
| * //**[version, encoding]**// - lista zawierająca informacje dotyczące wersji oraz kodowania pliku XML |
| * //**[ element(...)]**// - lista termów o postaci: //**element(Node_Name, [Value], [child_element])**//, gdzie argumentami są: |
| * //**Node_Name**// - nazwa węzła |
| * //**[Value]**// - lista atrybutów węzła |
| * //**[child_element]**// - lista kolejnych elementów - dzieci |
| |
| Poniżej przedstawiono sparsowany plik XML w BProlog: |
| <code prolog> |
| |
| xml( [version="1.0", encoding="utf-8", standalone="no"],[ |
| doctype( hml, system( "hml.dtd" ) ), |
| element( hml,[],[ |
| element( type_set,[],[] ), |
| element( attribute_set,[],[ |
| element( att,[name="Thermostat", id="att_0", value="single", class="ro"],[] ), |
| element( att,[name="Time", id="att_1", value="single", class="ro"],[] ), |
| element( att,[name="Temperature", id="att_2", value="single", class="ro"],[] ), |
| element( att,[name="Date", id="att_3", value="single", class="ro"],[] ), |
| element( att,[name="Hour", id="att_4", value="single", class="ro"],[] ), |
| element( att,[name="season", id="att_5", value="single", class="ro"],[] ), |
| element( att,[name="operation", id="att_6", value="single", class="ro"],[] ), |
| element( att,[name="thermostat_settings", id="att_7", value="single", class="ro"],[] ), |
| element( att,[name="day", id="att_8", value="single", class="ro"],[] ), |
| element( att,[name="month", id="att_9", value="single", class="ro"],[] ), |
| element( att,[name="today", id="att_10", value="single", class="ro"],[] ), |
| element( att,[name="hour", id="att_11", value="single", class="ro"],[] ) |
| ] ), |
| element( property_set,[],[ |
| element( property,[id="prp_0"],[ |
| element( attref,[ref="att_0"],[] ) |
| ] ), |
| element( property,[id="prp_1"],[ |
| element( attref,[ref="att_1"],[] ), |
| element( attref,[ref="att_2"],[] ) |
| ] ), |
| element( property,[id="prp_2"],[ |
| element( attref,[ref="att_1"],[] ) |
| ] ), |
| element( property,[id="prp_3"],[ |
| element( attref,[ref="att_2"],[] ) |
| ] ), |
| element( property,[id="prp_4"],[ |
| element( attref,[ref="att_3"],[] ), |
| element( attref,[ref="att_4"],[] ), |
| element( attref,[ref="att_5"],[] ), |
| element( attref,[ref="att_6"],[] ) |
| ] ), |
| element( property,[id="prp_5"],[ |
| element( attref,[ref="att_3"],[] ), |
| element( attref,[ref="att_4"],[] ) |
| ] ), |
| element( property,[id="prp_6"],[ |
| element( attref,[ref="att_5"],[] ), |
| element( attref,[ref="att_6"],[] ) |
| ] ), |
| element( property,[id="prp_7"],[ |
| element( attref,[ref="att_7"],[] ) |
| ] ), |
| element( property,[id="prp_8"],[ |
| element( attref,[ref="att_5"],[] ) |
| ] ), |
| element( property,[id="prp_9"],[ |
| element( attref,[ref="att_6"],[] ) |
| ] ), |
| element( property,[id="prp_10"],[ |
| element( attref,[ref="att_3"],[] ) |
| ] ), |
| element( property,[id="prp_11"],[ |
| element( attref,[ref="att_4"],[] ) |
| ] ), |
| element( property,[id="prp_12"],[ |
| element( attref,[ref="att_8"],[] ), |
| element( attref,[ref="att_9"],[] ), |
| element( attref,[ref="att_10"],[] ) |
| ] ), |
| element( property,[id="prp_13"],[ |
| element( attref,[ref="att_9"],[] ) |
| ] ), |
| element( property,[id="prp_14"],[ |
| element( attref,[ref="att_8"],[] ), |
| element( attref,[ref="att_10"],[] ) |
| ] ), |
| element( property,[id="prp_15"],[ |
| element( attref,[ref="att_8"],[] ) |
| ] ), |
| element( property,[id="prp_16"],[ |
| element( attref,[ref="att_10"],[] ) |
| ] ), |
| element( property,[id="prp_17"],[ |
| element( attref,[ref="att_11"],[] ) |
| ] ) |
| ] ), |
| element( tph,[],[ |
| element( trans,[src="prp_0", dst="prp_1"],[] ), |
| element( trans,[src="prp_1", dst="prp_2"],[] ), |
| element( trans,[src="prp_1", dst="prp_3"],[] ), |
| element( trans,[src="prp_2", dst="prp_4"],[] ), |
| element( trans,[src="prp_4", dst="prp_5"],[] ), |
| element( trans,[src="prp_4", dst="prp_6"],[] ), |
| element( trans,[src="prp_3", dst="prp_7"],[] ), |
| element( trans,[src="prp_6", dst="prp_8"],[] ), |
| element( trans,[src="prp_6", dst="prp_9"],[] ), |
| element( trans,[src="prp_5", dst="prp_10"],[] ), |
| element( trans,[src="prp_5", dst="prp_11"],[] ), |
| element( trans,[src="prp_10", dst="prp_12"],[] ), |
| element( trans,[src="prp_12", dst="prp_13"],[] ), |
| element( trans,[src="prp_12", dst="prp_14"],[] ), |
| element( trans,[src="prp_14", dst="prp_15"],[] ), |
| element( trans,[src="prp_14", dst="prp_16"],[] ), |
| element( trans,[src="prp_11", dst="prp_17"],[] ) |
| ] ), |
| element( ard,[],[ |
| element( dep,[independent="prp_8", dependent="prp_7"],[] ), |
| element( dep,[independent="prp_9", dependent="prp_7"],[] ), |
| element( dep,[independent="prp_13", dependent="prp_8"],[] ), |
| element( dep,[independent="prp_15", dependent="prp_16"],[] ), |
| element( dep,[independent="prp_16", dependent="prp_9"],[] ), |
| element( dep,[independent="prp_17", dependent="prp_9"],[] ) |
| ] ) |
| ] ) |
| ] ). |
| </code> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| ==== JIProlog ==== |
| Dokument XML po sparsowaniu w JIProlog jest przedstawiony w postaci zagnieżdżonych termów zaczynając od //xml_document// i idąc wgłąb //xml_element//, //xml_attribute// oraz //xml_text//. |
| |
| Charakterystyczne dla postaci prologowej są: |
| * //**xml_document([ [version = Version, encoding = Encoding], DocType], Root).**//, gdzie argumentami są: |
| * //**[ [version = Version, encoding = Encoding], DocType]**// - lista składająca się z listy zawierającej informacje o kodowaniu i wersji pliku XML oraz z informacji o typie dokumentu |
| * //**Root**// - korzeń dokumentu XML |
| * //**xml_element(Name, Attributes, Children)**// - kolejne elementy pliku XML. Argumentami są: |
| * //**Name**// - nazwa węzła |
| * //**Attributes**// - lista atrybutów zawierająca termy postaci: //**xml_attribute(Name, Value)**//, gdzie argumentami są: |
| * //**Name**// - nazwa atrybutu |
| * //**Value**// - wartość atrybutu |
| * //**Children**// - lista kolejnych dzieci węzła, zawierająca ponownie termy //**xml_element(Name, Attributes, Children)**// oraz //**xml_text(Content)**// - tekst węzła |
| |
| Poniżej przedstawiono sparsowany plik XML w JIProlog: |
| <code prolog> |
| X=xml_document([version = 1.0, encoding = UTF-8], [], |
| xml_element(hml, [], [xml_text(), |
| xml_element(type_set, [], [xml_text()]), xml_text(), |
| xml_element(attribute_set, [], [xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_0), |
| xml_attribute(name, Thermostat), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_1), |
| xml_attribute(name, Time), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_2), |
| xml_attribute(name, Temperature), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_3), |
| xml_attribute(name, Date), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_4), |
| xml_attribute(name, Hour), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_5), |
| xml_attribute(name, season), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_6), |
| xml_attribute(name, operation), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_7), |
| xml_attribute(name, thermostat_settings), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_8), |
| xml_attribute(name, day), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_9), |
| xml_attribute(name, month), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_10), |
| xml_attribute(name, today), |
| xml_attribute(value, single)], |
| []), xml_text(), |
| xml_element(att, [ |
| xml_attribute(class, ro), |
| xml_attribute(id, att_11), |
| xml_attribute(name, hour), |
| xml_attribute(value, single)], |
| []), xml_text() |
| ]), xml_text(), |
| xml_element(property_set, [], [xml_text(), |
| xml_element(property, [xml_attribute(id, prp_0)],[xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_0)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_1)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_1)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_2)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_2)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_1)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_3)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_2)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_4)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_3)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_4)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_5)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_6)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_5)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_3)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_4)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_6)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_5)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_6)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_7)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_7)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_8)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_5)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_9)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_6)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_10)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_3)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_11)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_4)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_12)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_8)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_9)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_10)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_13)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_9)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_14)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_8)], []), xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_10)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_15)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_8)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_16)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_10)], []), xml_text() |
| ]), xml_text(), |
| xml_element(property, [xml_attribute(id, prp_17)], [xml_text(), |
| xml_element(attref, [xml_attribute(ref, att_11)], []), xml_text() |
| ]), xml_text() |
| ]), xml_text(), |
| xml_element(tph, [], [xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_1), xml_attribute(src, prp_0)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_2), xml_attribute(src, prp_1)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_3), xml_attribute(src, prp_1)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_4), xml_attribute(src, prp_2)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_5), xml_attribute(src, prp_4)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_6), xml_attribute(src, prp_4)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_7), xml_attribute(src, prp_3)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_8), xml_attribute(src, prp_6)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_9), xml_attribute(src, prp_6)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_10), xml_attribute(src, prp_5)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_11), xml_attribute(src, prp_5)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_12), xml_attribute(src, prp_10)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_13), xml_attribute(src, prp_12)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_14), xml_attribute(src, prp_12)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_15), xml_attribute(src, prp_14)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_16), xml_attribute(src, prp_14)], []), xml_text(), |
| xml_element(trans, [xml_attribute(dst, prp_17), xml_attribute(src, prp_11)], []), xml_text() |
| ]), xml_text(), |
| xml_element(ard, [], [xml_text(), |
| xml_element(dep, [xml_attribute(dependent, prp_7), xml_attribute(independent, prp_8)], []), xml_text(), |
| xml_element(dep, [xml_attribute(dependent, prp_7), xml_attribute(independent, prp_9)], []), xml_text(), |
| xml_element(dep, [xml_attribute(dependent, prp_8), xml_attribute(independent, prp_13)], []), xml_text(), |
| xml_element(dep, [xml_attribute(dependent, prp_16), xml_attribute(independent, prp_15)], []), xml_text(), |
| xml_element(dep, [xml_attribute(dependent, prp_9), xml_attribute(independent, prp_16)], []), xml_text(), |
| xml_element(dep, [xml_attribute(dependent, prp_9), xml_attribute(independent, prp_17)], []), xml_text() |
| ]) |
| ])) |
| </code> |
| |
| |
| |
| |
| |
| |
| |
| |
| ===== Implementacja API w SWI-Prolog ===== |
| Ogólnodostępne wersje prologu nie posiadają mechanizmów do generowania dokumentów XML-DOM. Jedynie JIProlog dysponuje takimi możliwościami. Predykaty pozwalające na budowę dokumentu XML w JIProlog zostały omówione w sekcji ([[pl:miw:miw08_prolog_xml#jiprolog|JIprolog]]) W związku z tym postanowiono zaimplementować własne API do budowania plików XML. Jako wersję prologu przyjęto SWI-Prolog. Zaimplementowano następujące główne predykaty: |
| - //**create_root/2**// - tworzenie korzenia dokumentu XML |
| - //**app_child/4**// - dodawanie dzieci |
| - //**add_attribute/3**// - dodawanie atrybutów |
| |
| Plik zawierający pełne API dostępny jest do pobrania {{:pl:miw:miw08_prolog_xml:xml_api.pl|tutaj}} |
| |
| W przyszłości funkcjonalności API można dalej rozszerzać, np. o predykaty umożliwiające usuwanie dzieci, usuwanie atrybutów, czy też zmianę nazwy atrybutu bądź jego wartości. |
| |
| |
| |
| |
| |
| |
| ===== Przykład użycia API ===== |
| W celu prezentacji działania API przygotowano przykład, w którym pokazane zostało generowanie dokumentu XML (budowanie dokumentu podobnego do pliku pochodzącego z systemu VARDA). |
| |
| Budowanie dokumentu XML rozpoczyna się od stworzenia korzenia. |
| |
| ==== Tworzenie korzenia ==== |
| Korzen dokumentu xml tworzymy wykorzystując predykat: |
| <code prolog> |
| create_root(Name,ID_name). |
| </code> |
| Jako parametry podajemy kolejno: |
| * nazwę korzenia |
| * prefiks id, np. podając **cd**, zostanie stworzony **id=cd_0** gdzie **0** będzie kolejno nadawaną liczbą, startując od zera. |
| |
| Po użyciu tego predykatu pojawi się nam główny element struktury prologowej stanowiący korzeń dokumentu xml. |
| |
| Przykład: |
| <code prolog> |
| ?- create_root(hml,hml). |
| |
| Yes |
| ?- listing(element). |
| |
| :- dynamic element/3. |
| |
| element(hml, [id=hml_0], []). |
| </code> |
| |
| Po stworzeniu korzenia dokumentu XML przechodzimy do dodawania kolejnych dzieci. |
| |
| |
| |
| |
| |
| |
| |
| ==== Dodawanie dzieci ==== |
| Dodawanie dzieci do korzenia dokumentu lub do istniejących rodziców wykonuje się za pomocą predykatu: |
| <code prolog> |
| app_child(Parent,P_id,Child,ChildIdName). |
| </code> |
| W predykacie tym jako argumenty podajemy kolejno: |
| * Nazwę rodzica |
| * Id rodzica - jeśli istnieje wiele elementów o tej samej nazwie, podajemy id rodzica, jeśli nie jest ważne do którego rodzica chcemy dodać dziecko wpisujemy "_" (dziecko zostanie dodane do pierwszego istniejącego rodzica) |
| |
| :!::!:**//UWAGA//**:!::!: |
| |
| Kiedy podajemy **id** rodzica, do którego chcemy przypisać dziecko, podajemy pełny tekst, np. **//id=prp_1//**. |
| * Nazwa dziecka |
| * prefiks id dziecka; Podając **ala** zostanie stworzony prefiks **ala_**, któremu automatycznie zostanie przydzielona kolejna liczba, np. **ala_1**. |
| |
| Dodanie dziecka o nazwie **//type_set//** i id **//typ_s//** do rodzica **//hml//** (korzeń) przedstawia poniższy kod: |
| <code prolog> |
| ?- app_child(hml,_,type_set,typ_s). |
| </code> |
| Powstaje następująca struktura, korzeń **//hml//** ma na liście dziecko **//type_set//** z id o podanym prefiksie i przydzielonym numerze. |
| <code prolog> |
| element(hml, [id=hml_0], [element(type_set, [id=typ_s_0], [])]). |
| </code> |
| |
| W podobny sposób dodajemy dzieci: |
| * attribute_set <code prolog> ?- app_child(hml,_,attribute_set,att_s). </code> |
| * property_set <code prolog> ?- app_child(hml,_,property_set,prp_s). </code> |
| * tph <code prolog> ?- app_child(hml,_,tph,tph). </code> |
| * ard <code prolog> ?- app_child(hml,_,ard,ard). </code> |
| |
| W celu dodania za jednym razem większej ilości dzieci używamy predykatu pochodnego: |
| <code prolog> |
| app_child(Parent,P_id,Child,ChildIdName,How_many). |
| </code> |
| Dodatkowym argumentem jest //**How_many**//, który oznacza ilość dodawanych dzieci. |
| |
| Jest to przydatne np, podczas dodawania wielu dzieci **//att//** do rodzica **//attribute_set//**. |
| Po użyciu predykatu: |
| <code prolog> |
| app_child(attribute_set,_,att,att,12). |
| </code> |
| zostanie dodanych dwanaście dzieci do rodzica **//attribute_set//**. |
| |
| Podobnie dodajemy: |
| * dzieci **//property//** do rodzica **//property_set//** <code prolog> ?- app_child(property_set,_,property,prp,18)</code> |
| * dzieci **//trans//** do rodzica **//tph//** <code prolog> ?- app_child(tph,_,trans,tr,17).</code> |
| * dzieci **//dep//** do rodzica **//ard//** <code prolog> ?- ?- app_child(ard,_,dep,dp,6).</code> |
| |
| Następnie pozostaje tylko dodanie odpowiednich dzieci **//attref//** do odpowiednich rodziców **//property//**. |
| Tu ponownie wykorzystujemy wyżej wymieniany predykat, ale już z podaniem ID rodzica. Przykładowo, po wpisaniu: |
| <code prolog> ?- app_child(property,id=prp_1,attref,att_r,2)</code> |
| dodane zostaną dwoje dzieci **//attref//** z id o prefiksie //**att_r_**// do rodzica **//property//** o id **//id=prp_1//**. |
| |
| ---- |
| :!::!:**//UWAGA//**:!::!: |
| |
| Kiedy podajemy **id** rodzica, do którego chcemy przypisać dziecko, podajemy pełny tekst, np. **//id=prp_1//**. |
| ---- |
| |
| |
| W ten sposób stworzono cały szkielet dokumentu XML o zadanym korzeniu oraz zadanych dzieciach. Każdy element posiada własne, unikalne id. Ostatnią rzeczą będzie dodawanie odpowiednich atrybutów. |
| |
| |
| |
| ==== Dodawanie atrybutów ==== |
| Atrybuty do wybranego elementu dodaje się przy użyciu predykatu, |
| <code prolog> |
| add_attribute(Parent,P_id,Attr). |
| </code> |
| gdzie jako argument podajemy kolejno: |
| * nazwę elementu, do którego chcemy dodać atrybut |
| * id elementu, do którego chcemy dodać atrybut |
| * atrybut (//nazwa=wartość//), który chcemy dodać |
| |
| ---- |
| |
| :!::!://**UWAGA**//:!::!: |
| |
| Kiedy podajemy **id** elementu, do którego chcemy dodać atrybut, podajemy pełny tekst, np. **//id=att_0//**. |
| |
| Podobnie jest w przypadku podawania atrybutu. Podajemy pełny tekst zawierający znak **//"="//** , np. **//name=thermostat//** |
| ---- |
| |
| Przykładowo użycie |
| <code prolog> |
| ?- add_attribute(att,id=att_0,name=thermostat). |
| </code> |
| spowoduje dodanie atrybutu **//name=thermostat//** do elementu **//att//** o id **//id=att_0//**. |
| |
| W ten sam sposób możemy dodać każdy atrybut do każdego istniejącego elementu w "prologowej" strukturze XML. |
| |
| |
| |
| |
| ==== Tworzenie pliku xml ==== |
| |
| Plik XML tworzymy przy użyciu predykatu |
| <code prolog> |
| prolog2xml(File). |
| </code> |
| Po wpisaniu: |
| <code prolog> |
| ?- prolog2xml('test.xml'). |
| </code> |
| zostanie utworzony plik XML o nazwie test. |
| |
| Możemy też skorzystać z predykatu |
| <code prolog> |
| save(File). |
| </code> |
| który zapisze w podanym pliku aktualną "prologową" strukturę XML oraz aktualny stan nadanych id, np. |
| <code prolog> |
| save('wiedza.pl'). |
| </code> |
| |
| Przykład dokumentu XML wygenerowanego z użyciem API znajduje się {{:pl:miw:test.xml|tutaj}}. |
| |
| ====== Projekt ====== |
| |
| Przebieg projektu znajduje się [[pl:miw:miw08_prolog_xml:projekt|tutaj]]. |
| |
| |
| |
| |
| |
| ====== Materiały ====== |
| |
| Wszelkie materiały dostępne: [[pl:miw:miw08_prolog_xml:materialy|tutaj]]. |