Plan Przetwarzanie dokumentów XML i zaawansowane techniki WWW Wykład 05 T. Romańczukiewicz Jagiellonian University 2009/2010
Plan Plan 1 DOM 2 DOM w innych językach 3 Podsumowanie
Plan DOM DOM w innych językach Podsumowanie Przypomnienie Wstęp Węzły Metody XMLHttpRequest HTML DOM 1 DOM Przypomnienie Wstęp Węzły Metody XMLHttpRequest HTML DOM 2 DOM w innych językach 3 Podsumowanie
XML, poprawnie sformuowanie Sposoby opisu XML DTD XML Schema XPATH Sposoby prezentacji CSS XSLT
DOM DOM DOM w innych językach Podsumowanie Przypomnienie Wstęp Węzły Metody XMLHttpRequest HTML DOM DOM DOM W3C Document Object Model jest niezależnym od języka i platformy interfejsem pozwalajacym programom i skryptom na dostęp i zmiany w dokumentach XML. Możliwość użycia w JavaScript, Java, C++, PHP,... DOM Core DOM XML DOM HTML DOM DOM i SAX SAX (ang. Simple API for XML czyli Proste API dla XML-a) interfejs programistyczny do sekwencyjnego parsowania dokumentów XML. Jest to jeden z mechanizmów, który pozwala odczytywać dane zapisane w dokumentach XML. Parser, który implementuje SAX, działa jako parser strumieniowy sterowany zdarzeniami. Przetwarzanie z użyciem SAX jest jednokierunkowe - wcześniej przetworzone dane nie moga być ponownie odczytane bez ponownego uruchomienia całej procedury. korzystanie z modelu DOM wymaga wczytania całego dokumentu XML do pamięci i przechowywania go tam w postaci struktury drzewiastej o tym trzeba koniecznie pamiętać! należy uważać na DOM przy przetwarzaniu dużych ilości danych
W przeciwieństwie do interfejsu SAX, obiektowy model dokumentu wywodzi się z kręgów konsorcjum W3C. SAX to oprogramowanie będace własnościa publiczna. DOM jest samym w sobie standardem, tak jak XML. DOM nie został również opracowany wyłacznie dla Javy; jego zadaniem jest reprezentacja zawartości i modeli dokumentów we wszystkich językach i narzędziach programistycznych. Istnieja interfejsy DOM dla JavaScriptu, Javy, CORBA i innych języków. Jest to więc specyfikacja neutralna językowo i platformowo. Danych nie można użyć, dopóki cały dokument nie zostanie przetworzony i dodany do wyjściowej struktury drzewiastej. Dane wyjściowe z procesu przetwarzania, które maja zostać wykorzystane przez interfejsy DOM, maja postać obiektu org.w3c.dom.document. Obiekt ten działa jako procedura obsługi drzewa, w którym znajduja się nasze dane XML; z punktu widzenia hierarchii elementów obiekt ten znajduje się jeden poziom ponad elementem głównym dokumentu XML. Każdy element naszego wejściowego dokumentu XML jest bezpośrednio lub pośrednio potomny względem niego.
Węzły DOM Cały dokument jest węzłem dokumentu Każdy element jest węzłem elementu Każdy tekst jest węzłem tekstowym (!) Węzeł atrybutu Węzeł komentarza Uwaga: każdy tekst przechowywany jest w osobnym węźle: <year>2005</year> - węzeł elementu <year> zawiera węzeł tekstowy 2005
Węzeł Document Ponieważ Document to część samego węzła Node, możemy używać go wymiennie z innymi typami węzłów. Stanowi on jednak swoisty przypadek specjalny, ponieważ zawiera element główny i definicję DTD dokumentu oraz szereg innych specjalnych informacji nie należacych do hierarchii elementów XML. Dlatego przetwarzajac ten węzeł, musimy uzyskać element główny i przekazać go funkcji wyświetlajacej. Elementy DOM najbardziej typowym zadaniem wykonywanym w aplikacji będzie pobranie węzła DOM Element i wyświetlenie jego nazwy, atrybutów i wartości, a następnie jego elementów potomnych. Najpierw pobieramy nazwę elementu (metoda getnodename()) i wyświetlamy ja. Węzły tekstowe Parser XML postrzega wszystkie dane jako tekst i że to aplikacja dokonuje w razie potrzeby konwersji typów. Tak więc aby wyświetlić wartości elementów w DOM-ie, należy skupić uwagę na interfejsach Text i CDATASection. Wyświetlanie wartości jest całkiem proste korzystamy ze znanej już metody getnodevalue() interfejsu DOM Node.
Ładowanie pliku XML Listing 1: Przykład1.js 1 if (window.xmlhttprequest) 2 { 3 xhttp=new XMLHttpRequest(); 4 } 5 else / / I n t e r n e t E x p l o r e r 5 / 6 6 { 7 xhttp=new ActiveXObject("Microsoft.XMLHTTP"); 8 } 9 xhttp.open("get","books.xml",false); 10 xhttp.send(""); 11 xmldoc=xhttp.responsexml; Utworzenie obiektu XMLHTTP Otworzenie objektu XMLHTTP Wysłanie zapytania XML HTTP do serwera Przekazanie odpowiedzi jako objekt XML DOM Ze względów bezpieczeństwa plik XML musi się znajdować na tym samym serwerze co strona www.
Listing 2: Przykład1.js 1 function loadxmlstring(txt) 2 { 3 if (window.domparser) 4 { 5 parser=new DOMParser(); 6 xmldoc=parser.parsefromstring(txt,"text/xml"); 7 } 8 else / / I n t e r n e t E x p l o r e r 9 { 10 xmldoc=new ActiveXObject("Microsoft.XMLDOM"); 11 xmldoc.async="false"; 12 xmldoc.loadxml(txt); 13 } 14 return xmldoc; 15 } Uwaga na IE: Internet Explorer białe znaki nie traktuje jak węzły tekstowe inne przegladari tak
Ładowanie tekstuxml Listing 3: Przykład1.html 1 <html> 2 <head> 3 <script type="text/javascript" src="loadxmlstring.js"></script> 4 </head> 5 <body> 6 <script type="text/javascript"> 7 text="<bookstore><book>"; 8 text=text+"<title>everyday Italian</title>"; 9 text=text+"<author>giada De Laurentiis</author>"; 10 text=text+"<year>2005</year>"; 11 text=text+"</book></bookstore>"; 12 13 xmldoc=loadxmlstring(text); 14 15 document.write(xmldoc.getelementsbytagname("title")[0].childnodes[0]. nodevalue); 16 document.write("<br />"); 17 document.write(xmldoc.getelementsbytagname("author")[0].childnodes[0]. nodevalue); 18 document.write("<br />"); 19 document.write(xmldoc.getelementsbytagname("year")[0].childnodes[0]. nodevalue); 20 </script> 21 </body> 22 </html>
Interfejs prgoramistyczny DOM Własności x.nodename - nazwa węzła x x.nodevalue - Wartość x x.parentnode - Rodzic x x.childnodes - Potomek węzła x x.attributes - atrybuty x Metody x.getelementsbytagname(name) - zwróć wszystkie elementy o podanej nazwie x.appendchild(node) - Dodaj potomka do węzła x x.removechild(node) - Usuń potomka z węzła x Przykładowe wywołanie w JavaScript: txt=xmldoc.getelementsbytagname("title")[0].childnodes[0].nodevalue xmldoc - obiekt DOM utworzony przez parser getelementsbytagname("title")[0] - pierwszy element <title> childnodes[0] - pierwszy potomek elementu <title> (węzeł tekstowy) nodevalue - wartość tego elementu (sam tekst)
Listing 4: Node List wypisanie wszystkich elementów 1 xmldoc=loadxmldoc("books.xml"); 2 x=xmldoc.getelementsbytagname("title"); 3 4 for (i=0;i<x.length;i++) { 5 document.write(x[i].childnodes[0].nodevalue); 6 document.write("<br />"); 7 } Metoda node.getelementsbytagname("tagname"); zwraca listę elementów o podanej nazwie. Listing 5: Wypisanie tylko węzłów elementu nodetype 1 xmldoc=loadxmldoc("books.xml"); 2 x=xmldoc.documentelement.childnodes; 3 4 for (i=0;i<x.length;i++) { 5 if (x[i].nodetype==1) document.write(x[i].nodename); 6 document.write("<br />"); 7 } 8 }
Listing 6: Wypisanie nazw elementu book 1 xmldoc=loadxmldoc("books.xml"); 2 3 x=xmldoc.getelementsbytagname("book")[0].childnodes; 4 y=xmldoc.getelementsbytagname("book")[0].firstchild; 5 6 for (i=0;i<x.length;i++) 7 { 8 if (y.nodetype==1) 9 { / / P r o c e s s o n l y e l e m e n t nodes ( t y p e 1) 10 document.write(y.nodename + "<br />"); 11 } 12 y=y.nextsibling; 13 } Listing 7: Wydruk 1 title 2 author 3 year 4 price Załadowanie pliku "books.xml" do obiektu xmldoc; wczytanie węzłów potomnych pierwszego elementu book; Ustawinenie zmiennej "y" na childnodes[0]; dla każdego węzła potomka "y" sprawdzenie typu, jeśli typ 1 (czyli węzeł elementu) to wypisanie elementu przejście do następnego elementu rodzeństwa
Typy węzłów 1 ELEMENT_NODE 2 ATTRIBUTE_NODE 3 TEXT_NODE 4 CDATA_SECTION_NODE 5 ENTITY_REFERENCE_NODE 6 ENTITY_NODE 7 PROCESSING_INSTRUCTION_NODE 8 COMMENT_NODE 9 DOCUMENT_NODE 10 DOCUMENT_TYPE_NODE 11 DOCUMENT_FRAGMENT_NODE 12 NOTATION_NODE
Trawersowanie węzłów drzewa Przechodzenie po wszystkich węzłach Listing 8: Trawersowanie.html 1 <html><head> 2 <script type="text/javascript" src="loadxmlstring.js"></script> 3 </head> 4 <body> 5 <script type="text/javascript"> 6 text="<book>"; 7 text=text+"<title>everyday Italian</title>"; 8 text=text+"<author>giada De Laurentiis</author>"; 9 text=text+"<year>2005</year>"; 10 text=text+"</book>"; 11 12 xmldoc=loadxmlstring(text); 13 14 // documentelement always represents the root node 15 x=xmldoc.documentelement.childnodes; 16 for (i=0;i<x.length;i++) 17 { 18 document.write(x[i].nodename); 19 document.write(": "); 20 document.write(x[i].childnodes[0].nodevalue); 21 document.write("<br />"); 22 } 23 </script> 24 </body> 25 </html> loadxmlstring() ładuje ci ag znaków do xmldoc pobranie węzła dziecka z węzła korzenia
Nawigacja Nawigacja Poruszanie się po drzewie wykorzysujac relacje pomiędzy węzłami childnodes firstchild lastchild nextsibling previoussibling
W DOM wszystko jest węzłem. Każdy tekst wewnatrz elementu reprezentowany jest jako osobny węzeł tekstowy. Dostęp do niego można uzyskać poprzez węzeł potomka danego elementu. 1 x=xmldoc.getelementsbytagname("title")[0]; 2 y=x.childnodes[0]; 3 txt=y.nodevalue; W przeciwieństwie do elementów w DOMie atrybuty posiadaja wartość i można ja odczytać poprzez metodę getattribute() albo bezpośrednio poprzez własność nodevalue 1 xmldoc=loadxmldoc("books.xml"); 2 txt=xmldoc.getelementsbytagname("title")[0].getattribute("lang");
Zmiana wartości elementu i atruybutu Listing 9: Zmiana wartości 1 xmldoc=loadxmldoc("books.xml"); 2 3 x=xmldoc.getelementsbytagname("title")[0].childnodes[0]; 4 x.nodevalue="easy Cooking"; 5 xmldoc=loadxmldoc("books.xml"); 6 7 x=xmldoc.getelementsbytagname("book")[0] 8 y=x.getattributenode("category"); 9 y.nodevalue="food"; Listing 10: Usuwanie elementu 1 xmldoc=loadxmldoc("books.xml"); 2 y=xmldoc.getelementsbytagname("book")[0]; 3 4 xmldoc.documentelement.removechild(y); 5 y.parentnode.removechild(x); 6 7 x=xmldoc.getelementsbytagname("title")[0]; 8 y=x.childnodes[0]; 9 x.removechild(y);
Zamiana DOM DOM w innych językach Podsumowanie Przypomnienie Wstęp Węzły Metody XMLHttpRequest HTML DOM Listing 11: Zamiana wartości 1 xmldoc=loadxmldoc("books.xml"); 2 3 x=xmldoc.documentelement; 4 5 / / c r e a t e a book element, t i t l e e l e m e n t and a t e x t node 6 newnode=xmldoc.createelement("book"); 7 newtitle=xmldoc.createelement("title"); 8 newtext=xmldoc.createtextnode("a Notebook"); 9 10 / / add t h e t e x t node t o t h e t i t l e node, 11 newtitle.appendchild(newtext); 12 / / add t h e t i t l e node t o t h e book node 13 newnode.appendchild(newtitle); 14 15 y=xmldoc.getelementsbytagname("book")[0] 16 / / replace the f i r s t book node with the new node 17 x.replacechild(newnode,y);
Inne przydatne metody: createelement() tworzy nowy element appendchild() dodaje nowy element createattribute() tworzy nowy atrrybut setattributenode() dodaje nowy atrybut setattribute() Ustawia wartości atrybutu lub go tworzy gdy go nie ma Listing 12: Przykład 1 xmldoc=loadxmldoc("books.xml"); 2 newel=xmldoc.createelement("edition"); 3 x=xmldoc.getelementsbytagname("book")[0]; 4 x.appendchild(newel); 5 6 newatt=xmldoc.createattribute("edition"); 7 newatt.nodevalue="first"; 8 x=xmldoc.getelementsbytagname("title"); 9 x[0].setattributenode(newatt);
Inne przydatne metody cd: createtextnode() tworzy element tekstowy createcdatasection() tworzy sekcję CDATA createcomment() (no comments) insertbefore() umieszcza węzeł przed podanym potomkiem insertdata(offset, string) umieszcza dane clonenode() kopiuje węzeł Listing 13: Przykład 1 xmldoc=loadxmldoc("books.xml"); 2 3 newel=xmldoc.createelement("edition"); 4 newtext=xmldoc.createtextnode("first"); 5 newel.appendchild(newtext); 6 7 x=xmldoc.getelementsbytagname("book")[0]; 8 x.appendchild(newel); 9 10 newcdata=xmldoc.createcdatasection("special Offer & Book Sale"); 11 12 x=xmldoc.getelementsbytagname("book")[0]; 13 x.appendchild(newcdata); 14 15 newcomment=xmldoc.createcomment("revised March 2008"); 16 17 x=xmldoc.getelementsbytagname("book")[0]; 18 x.appendchild(newcomment);
Własności DOM Document Listing 14: Przykład 1 async, childnodes, doctype, documentelement, documenturi, domconfig, firstchild, 2 implementation, inputencoding, lastchild, nodename, nodetype, nodevalue, 3 stricterrorchecking, text, xml, xmlencoding, xmlstandalone, xmlversion Własności DOM Node Listing 15: Przykład 1 baseuri, childnodes, firstchild, lastchild, localname, namespaceuri, 2 nextsibling, nodename, nodetype, nodevalue, ownerdocument, parentnode, prefix, 3 previoussibling, textcontent, text, xml
Tworzenie obiektu XMLHttpRequest Dzięki obiektowi XMLHttpRequest można uaktualniać stronę bez jej przeładowania wysyłać zapyatania do serwera po załadowaniu strony odczytywać dane z serwera wysyłać dane na serwer w tle Listing 16: Przykłady 1 var xmlhttp; 2 function loadxmldoc(url) { 3 xmlhttp=null; 4 if (window.xmlhttprequest) xmlhttp=new XMLHttpRequest(); / / code for a l l new b r o w s e r s 5 else if (window.activexobject) xmlhttp=new ActiveXObject("Microsoft.XMLHTTP") ; 6 7 if (xmlhttp!=null){ 8 xmlhttp.onreadystatechange=state_change; 9 xmlhttp.open("get",url,true); 10 xmlhttp.send(null); 11 } 12 else alert("your browser does not support XMLHTTP."); 13 }
Listing 17: Przykład cd. 1 function state_change() 2 { 3 if (xmlhttp.readystate==4) 4 { / / 4 = " l o a ded " 5 if (xmlhttp.status==200) 6 { / / 200 = "OK" 7 document.getelementbyid( A1 ).innerhtml=xmlhttp.status; 8 document.getelementbyid( A2 ).innerhtml=xmlhttp.statustext; 9 document.getelementbyid( A3 ).innerhtml=xmlhttp.responsetext; 10 } 11 else 12 alert("problem retrieving XML data:" + xmlhttp.statustext); 13 } 14 }
Własności XMLHttpRequest onreadystatechange przechwytywanie zdarzenia każdorazowej zmiany stanu readystate zwraca wartość stanu 0 = uninitialized 1 = loading 3 = interactive 4 = complete responsetext zwraca tekst odpowiedzi responsexml zwraca obiekt XML, który jest przetwarzany przy pomocy DOM status zwraca numer statusu (np. 404 Ńot Found", 200 dla ÓK") statustext zwraca tekst statusu
HTML DOM HTML DOM Własności x.nodename - nazwa węzła x x.nodevalue - wartość x x.parentnode - Rodzic x x.childnodes - Potomek węzła x x.attributes - atrybuty x x.innerhtml - textowa zawartość węzła x Metody x.getelementbyid(id) - zwróć wszystkie elementy o podanym ID x.getelementsbytagname(name) - zwróć wszystkie elementy o podanej nazwie x.appendchild(node) - Dodaj potomka do węzła x x.removechild(node) - Usuń potomka z węzła x Przykładowe wywołanie w JavaScript: txt=xmldoc.getelementsbytagname("title")[0].childnodes[0].nodevalue xmldoc - obiekt DOM utworzony przez parser getelementsbytagname("title")[0] - pierwszy element <title> childnodes[0] - pierwszy potomek elementu <title> (węzeł tekstowy) nodevalue - wartość tego elementu (sam tekst)
Plan DOM DOM w innych językach Podsumowanie 1 DOM 2 DOM w innych językach 3 Podsumowanie
DOM DOM w innych językach Podsumowanie Model DOM jest niezależny od platformy i języka programowania. Standard W3C DOM definiuje zespół klas i interfejsów, pozwalajacych na dostęp do struktury dokumentów oraz jej modyfikację poprzez tworzenie, usuwanie i modyfikację tzw. węzłów (ang. nodes). Dla większości języków programowania istnieja biblioteki obsługujace DOM dla plików XML Apache Xerces libxml (C++, gnome, PHP) MSXML Apache Xerces (rodzina pakietów : C++, Java, Perl) JAXP (Java API for XML Processing) JDOM VTD-XML Virtual Token Descriptor for extensible Markup Language (A " Document-Centric" XML parser) Standard W3C definiuje interfejsy DOM tylko dla języków JavaScript i Java.
DOM DOM w innych językach Podsumowanie Listing 18: PHP Example 1 function getlinks($link) 2 { 3 / r e t u r n a r r a y / 4 $ret = array(); 5 6 / a new dom o b j e c t / 7 $dom = new domdocument; 8 9 / g et t he HTML ( s upp re ss e r r o r s ) / 10 @$dom->loadhtml(file_get_contents($link)); 11 12 / remove s i l l y white space / 13 $dom->preservewhitespace = false; 14 15 / get the l i n k s from the HTML / 16 $links = $dom->getelementsbytagname( a ); 17 18 / loop over the l i n k s / 19 foreach ($links as $tag) 20 { 21 $ret[$tag->getattribute( href )] = $tag->childnodes->item(0)-> nodevalue; 22 } 23 return $ret; 24 } Przykładowa funkcja zwraca tablicę linków z podanej strony. Jest to podejście znacznie wygodniejsze niż używanie wyrażeń regularnych np w Perlu.
DOM DOM w innych językach Podsumowanie Listing 19: Java Example 1 import org.w3c.dom.*; 2 import org.apache.xerces.parsers.domparser; 3 import java.io.*; 4 5 public class SearchElement{ 6 public static void main(string[] args) { 7 try{ 8 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 9 System.out.print("Enter file name: "); 10 String str = bf.readline(); 11 File file = new File(str); 12 if (file.exists()){ 13 DOMParser parser = new DOMParser(); 14 parser.parse(str); 15 Document doc = parser.getdocument(); 16 System.out.print("Enter element that have to count: "); 17 String ele = bf.readline(); 18 NodeList list = doc.getelementsbytagname(ele); 19 if(list.getlength() == 0) 20 System.out.println("Element doesn t exist in the " + str + " Document. "); 21 else 22 System.out.println("Element occurrs " + list.getlength() + " times in the " + str); 23 } 24 else { System.out.println("File not found!"); } 25 } 26 catch (Exception e) { e.getmessage(); } 27 }
Plan DOM DOM w innych językach Podsumowanie 1 DOM 2 DOM w innych językach 3 Podsumowanie
DOM DOM w innych językach Podsumowanie DOM jest modelem pozwalajacym na dostęp (czytanie i modyfikowanie) dokumentów XML poprzez strukturę drzewa Jest niezależny od platformy i języka programowania Całe drzewo XML jest wczytywane od razu w przeciwieństwie do SAX, co może być problemem przy dużych plikach XML Każdy element, atrybut, komentarz itp jest reprezentowany przez węzeł. Dane - węzeł tekstowy DOM udostępnie szereg metod pozwalajacych na porusznie się w strukturze drzewa (nawigacja, trawersowanie) oraz tworzenie usuwanie czytanie węzłów Ponieważ DOM jest niezależny od języka programowania, może być wykorzystywany w wielu językach poprzez odpowiednie API Standard W3C definiuje interfejsy DOM tylko dla języków JavaScript i Java.