XML/Wprowadzenie do XML DOM
DOM (Document Object Model) to po prostu pewien obiektowy model dokumentu, który jest najpopularniejszym standardem przetwarzania dokumentów XML. Sam w sobie nie ma zbyt wiele wspólnego z dokumentami XML jako takimi, ponieważ ich dotyczą zasady składni. Model danych jest bardziej abstrakcyjną formą opisu i zarówno istnieje w głowach inżynierów, jak i jest implementowany w programach komputerowych.
W kursie będzie używane kody źródłowe w przykładach, są one zbudowane w języku IDL (Interface Description Language - język opisu interfejsu). Jego składnia jest jednak taka sama jak standardu ECMAScript, więc i taka sama jak np. w Javascript czy Actionscript, a też bardzo podobna do PHP, C#, Java, C++. Tak więc przykłady będą proste do implementacji wprost w Javascript czy Actionscript, przy czym będzie potrzebne dopisanie funkcjonalności inicjującej. W przypadku języków z drugiej grupy, przepisanie kodu do postaci działającej (przy czym też będą potrzebne dodatki inicjujące) też nie powinno być trudne.
DOM to nie dokument XML!
edytujTakie modele danych jak DOM nie służą do edycji i przebudowywania dokumentów. A przynajmniej nie w głównym celu. Ten model dotyczy już załadowanego dokumentu do pamięci. Tu już nie ma żadnego XML-a - to już ciąg bitów w pamięci komputera, a w momencie jego używania operujemy programem. Obsługując DOM - pisze się już w języku programowania, nie zaglądając już w treść dokumentu XML.
W poniższym przykładzie kodu w języku Javascript realizowane jest wstawianie elementu. W pierwszej linii tworzony jest pomocniczy element nagłówka 1 poziomu. W drugiej linii są tworzone jego właściwości - w tym przypadku zawartość nagłówka. W obu przypadkach są tworzone jako pewne obiekty - zmienne, które są "oderwane" od dokumentu. W trzeciej linii właściwość jest dodawana do pomocniczego elementu nagłówka, a w ostatniej linii - ten uzupełniony już pomocniczy element jest dodany do drzewa DOM. W dalszej części programu pomocniczego elementu można wciąż używać (i wstawiać w inne miejsca) lub usunąć - jeśli już nie jest potrzebny.
heading = document.createElement("h1");
heading_text = document.createTextNode("Big Head!");
heading.appendChild(heading_text);
document.body.appendChild(heading);
Omówienie programowania obiektowego
edytujJak już wiesz, dokument XML składa się z elementów, które mają atrybuty i zawartość. Model danych XML określa takie encje, a oprócz nich encje jako odwołania znakowe oraz encje zewnętrzne, które mogą być różnego typu danymi. W programowaniu obiektowym strukturą odwzorowującą encję jest klasa, natomiast jej instancją, obiekt. Wszystkie wzorcowe dane mają taką samą budowę: składają się z pól - czyli zmiennych, które mogą być skalarne (jeśli język obsługuje) lub również obiektowe; oraz metod - czyli składowych obiektu, która działają jak funkcja. Mogą istnieć również tzw. callbacki, które są funkcjami, ale są polami, które są typu funkcyjnego.
Główny problem polega właśnie na rzutowaniu atrybutów i zawartości na pola i metody. Zapewne intuicja podpowiada już, że atrybuty i wartości mogą być odwzorowywane raczej jako pola. I tu jest 100% prawda. Do czego więc służą metody? Tak jak w powyższym przykładzie: do wykonywania pewnych czynności. Jest to o tyle lepsze od zwykłej funkcji, że metoda zawiera automatycznie wskaźnik na siebie i nie trzeba używać funkcji typu createElement(gdzie, co), lecz do obiektu jest przypisana metoda, która automatycznie wskazuje na obiekt i wystarczy wstawić coś: createElement(co). W przypadku wprowadzenia zdarzeń przypisywanych do obiektu, są one realizowane jako metody, co ma sens - przy zajściu zdarzenia przecież coś się wykonuje, obiekt musi jakoś zareagować.
DOM to także nie JavaScript
edytujDOM nadal najczęściej jest wykorzystywany do manipulowania dokumentami HTML, w tym XHTML, czyli dokumentami w serializacji XML. I właśnie JavaScript operuje obiektowym modelem dokumentu. Wszędzie można znaleźć kawałki kodu JS jako wzór, definicje, czy wreszcie gotowe fragmenty kodu do wykorzystania. Jednak JavaScript to po prostu jeden z języków, który wykorzystuje tę koncepcję. Inną tego typu koncepcją jest AJAX.
Natomiast właśnie kluczem w tych koncepcjach jest ich uniwersalność - popularne języki i frameworki poprawnie implementują ten standard, dzięki czemu nie trzeba się uczyć różnych sposobów na uzyskanie tego samego w różnych językach, wystarczy tylko znać różnice w składni. Wspomaga to znacznie uniwersalność formatów danych, takich jak XML, dzięki czemu nie tylko sama serializacja danych w dokumencie jest uniwersalna, ale także sposoby przetwarzania tych danych.
Oto przykład wykorzystania DOM w Pythonie[2]:
def from_xml(cls, src):
"""Generate instance of subclass from an XML string."""
dom = xml.dom.minidom.parseString(src)
# Make sure all of the necessary pieces are there. Fail if any
# required tags are missing
xc = cls()
for tag_name, default_or_type in xc.required_tags():
elem = dom.getElementsByTagName(tag_name)
if not elem:
raise ValueError("Missing XML tag: " + tag_name)
tag_type = (default_or_type
if isinstance(default_or_type, type)
else type(default_or_type))
xc[tag_name] = tag_type(cls._get_text(elem[0].childNodes))
return xc
Logika działania DOM
edytujJak działa DOM i czym się różni od innych modelów
edytujDOM nie jest jednak jedynym dla XML - istnieje wiele alternatywnych, takich jak SAX, który jest ciekawym rozwiązaniem - buduje struktury danych sekwencyjnie, gdzie wystąpienia elementów są zdarzeniami, czy SimpleXML, który jest rozszerzeniem PHP - w nim drzewo elementów XML jest niemal wprost odwzorowywane jako jeden wielki obiekt, który składa się z podobiektów będących właśnie podelementami korzenia, a każdy element jest również obiektem, który zawiera w sobie inne itd. W jaki więc sposób działa DOM? W DOM dokument traktujemy jako bazę, w której szukamy kolekcji elementów na żądanie - tylko takiej kolekcji elementów, która nas interesuje. I wyniki nie muszą mieć żadnego logicznego powiązania.
Do czego więc nadaje się ten dziwny DOM? Przecież ani nie odwzorowuje etapów przetwarzania dokumentu (jak SAX), ani nie odwzorowuje struktury. Jest to jakiś dziwny misz-masz tego, o co programista sam zażąda. Tracimy w nim "logikę" dokumentu. Tylko że właśnie w pewnych zastosowaniach to nie jest wada, a zaleta. A jakie one są? Między innymi - praca na dokumentach XML tworzących interfejs - na przykład w przeglądarkach internetowych; duże dokumenty XML (niekoniecznie ładowane z pliku), które są obiektowymi bazami danych. Czy wręcz - w ogóle nie musi to być dokument XML. Wiele silników obsługujących hierarchiczne bazy danych nie używa w ogóle XML-a do przechowywania danych a jedynie metody związane z XML-em, np. właśnie DOM.
Pokrewnym, nowszym - ale nie zastępującym, lecz uzupełniającym - modelem jest shadow DOM, co można przetłumaczyć jako cienisty DOM. Operuje na wycinku drzewa, który powstaje niezależnie od głównego drzewa dokumentu. Działa tak, jak np. kontrolki formularza definiowane jako pojedynczy element, a są realizowane przez cały ich zestaw. Dotyczy on raczej dokumentów definiujących widoki aplikacji, więc tym zagadnieniem nie będziemy się tu zajmować.
Odwzorowanie właściwości elementów na klasy DOM
edytujIstnieje kilka klas obiektów, w zależności od tego, czym one są. W poniższej analizie pominięte są typy obiektów występujące poza korzeniem (czyli np. prolog), oprócz dokumentu.
- Document - cały dokument
- DocumentFragment - fragment dokumentu będący właśnie wycinkiem shadow DOM
- Element - pełny element
- Attr- atrybut
Jak widać, nawet atrybut nie jest daną skalarną.
Najważniejsze składowe obiektu elementu (obiektu Element) są następujące:
- x.nodeName - nazwa elementu
- x.nodeValue - wartość elementu
- x.parentNode - referencja do rodzica
- x.childNodes - kolekcja dzieci
- x.attributes - kolekcja atrybutów
W zależności od języka, kolekcje mogą być realizowane zarówno jako tablice, jak i obiekty. W niektórych językach nawet jako oba naraz (możliwość odwołania się do elementów kolekcji zarówno przez tablicę, jak i obiekt).