Interesujący wydaje się temat wewnętrznego sposobu przechowywania danych przez serwer XML-a. Najpopularniejsze rozwiązania mają za podstawę system plików, bazę relacyjną (przechowującą dane w tekstowych polach LOB lub, po dekompozycji, w wielu tabelach) lub łączone źródła danych. Nie istnieje idealny sposób rozwiązania tego problemu, przede wszystkim ze względu na ogromną różnorodność form dokumentów XML-owych. Mimo to, daje się obecnie zauważyć tendencję do reprezentacji dokumentów traktowanych jako całość, gdzie rozbicie struktury postrzegane jest jako proces wyższego poziomu. Wiele ciekawych zagadnień z dziedziny możliwości reprezentacji danych XML-owych w bazach danych poruszają T. Traczyk i W. Macewicz w referacie Język XML w aplikacjach z bazami danych - możliwości zastosowania, pierwsze doświadczenia.

Nadrzędny problem reprezentacji struktur dokumentów ma wg nich dwa aspekty - złożoności dokumentów i podatności ich struktur na modyfikacje. Przechowywanie złożonych struktur w bazie relacyjnej w zdekomponowanej postaci jest trudne - próba przekształcenia hierarchii elementów do schematu bazy danych powoduje powstanie struktury nienaturalnej i trudnej do obróbki, zaś zmiana definicji typu dokumentu wymusza zmianę schematu bazy danych. Bazy relacyjno-obiektowe umożliwiają zapis złożonych struktur, lecz także nie pozwalają na uniezależnienie schematu bazy od DTD. Sugestię autorów, że najlepiej nadają się do reprezentacji dokumentów XML-owych bazy czysto obiektowe trzeba jednak traktować ostrożnie, gdyż rozbudowa DTD z wykorzystaniem mechanizmu dziedziczenia wydaje się rozwiązaniem dużo bardziej złożonym niż wyjątkowo prosta reprezentacja z użyciem CLOB-ów.

Zapis w postaci zdekomponowanej

Dostęp do wewnętrznych fragmentów znacznie ułatwia wstępna obróbka dokumentu podczas jego importu do repozytorium. W skrajnej postaci może ona polegać na całkowitym rozkładzie dokumentów o dobrze określonej strukturze na tabele bazy. W przypadku baz relacyjnych z dekompozycją typowy jest następujący schemat postępowania z dokumentami XML-owymi: Przed importem z definicji typu dokumentu generowany jest schemat tabel. Metod jest wiele - od tworzenia stałej liczby tabel osobno dla atrybutów, elementów, węzłów tekstowych i wiążących je zależności, aż po wyrafinowane techniki upraszczania DTD, zgodnie z założeniem, że warunkiem koniecznym jest jedynie zdolność do przechowania wszystkich zgodnych z nim dokumentów, a sama poprawność dokumentu będzie sprawdzona przez parser. Bardziej złożone rozwiązania umożliwiają automatyczne odwzorowanie hierarchii elementów do kilku tabel bazy. Warto ich jednak używać ostrożnie, gdyż w przypadku skomplikowanych zapytań wykonanie kwerend może być skrajnie nieefektywne (głównie z powodu zbyt dużej liczby złączeń).

Dokument XML-owy i przykład dekompozycji:

<produkt id="1280">
    <nazwa>Klawiatura</nazwa>
    <cena>15</cena> 
</produkt> 
<produkt id="1281">
   <nazwa>Mysz</nazwa>
   <cena>17</cena> 
</produkt>
PRODUKT ID        NAZWA       CENA
   1280        Klawiatura      15
   1281        Mysz            17

Zapis w postaci natywnej

Składanie dokumentów przy ich pobieraniu, będące efektem przechowywania XML-a w postaci zdekomponowanej, jest o wiele bardziej złożone niż pozyskiwanie z pól tekstowych całych dokumentów lub ich większych fragmentów. W wielu przypadkach warto zatem rozważyć rezygnację z rozbicia struktury na poziomie silnika persystencji. Jako że hierarchiczna struktura dokumentów XML-owych w ogólności staje w poprzek modelu relacyjnego, najprostszym, ale wykazującym wiele zalet pomysłem jest próba przechowywania dokumentów XML-owych w całości, bez rozkładania ich na fragmenty. Do tego celu nadają się doskonale pola LOB w relacyjnych bazach danych lub wpisy w systemie plików. Oba te rozwiązania, mimo że skrajnie różne technicznie, mogą wyrażać zapis "natywny", czyli, zgodnie z wprowadzaną terminologią, nie naruszający macierzystego formatu dokumentu. Oczywiście, odwołania do zawartości elementów składowych są w tym przypadku o wiele kosztowniejsze, gdy jednak dominują operacje pobierania i uaktualniania dokumentów w całości - jak np. w przypadku ich obróbki edytorem XML-owym ogólnego zastosowania, przesyłającym następnie cały blok tekstu do bazy - rozwiązanie to spisuje się znakomicie. W razie potrzeby sięgnięcia do wnętrza fragmentu, dokument przetwarzany jest parserem. Rozwiązania mieszane Oba opisane sposoby mogą być także udostępniane jednocześnie, na zasadzie częściowej strukturalizacji dokumentów. Struktury bazy modelują wówczas hierarchię elementów do określonej głębokości, poniżej której nie następuje już rozbicie (fragmenty tekstu przechowywane są w polach CLOB). Rozwiązanie to, choć kompromisowe, daje duże możliwości przeszukiwania dokumentów w części zdekomponowanej, przy zachowaniu możliwości rozbudowy struktury. Można też wyobrazić sobie sytuację, w której importowane do bazy teksty są filtrowane w celu wyszukania określonych wartości, zapisywanych następnie w osobnej tabeli w charakterze metadanych (zazwyczaj w celu przyspieszenia wyszukiwania). W skrajnym przypadku tekstowi przechowywanemu w polu CLOB może towarzyszyć relacyjny indeks struktury dokumentu (zapis relacji zawierania się elementów, wartości atrybutów itp.) Proces wyszukiwania nie musi wówczas angażować parsera.

Baza jako źródło dokumentów XML-owych

W opisanych powyżej przypadkach naturalnym rozszerzeniem mechanizmu importu dokumentów XML-owych do jednej ze struktur wewnętrznych będą zapewne odpowiadające im mechanizmy eksportujące. W podobną funkcjonalność mogą być też wyposażane bazy nie mające do tej pory z XML-em wiele wspólnego. Niezależnie od wewnętrznej reprezentacji danych bazy te mogą być wówczas traktowane jako źródła dokumentów XML-owych. Podejściem najprostszym, funkcjonującym do niedawna powszechnie, jest bezpośredni eksport danych tabelarycznych z użyciem znaczników pól i wierszy. Obecnie mamy już prawo wymagać od bazy danych o wiele więcej. Przykładowo, najnowsze narzędzie eksportujące wbudowane w Microsoft Access z pakietu Office XP, wykorzystuje nazwy pól do tworzenia nazw elementów i umożliwia zapis odwzorowującego schemat tabel opisu schematu danych do pliku XSD oraz generację pliku XSL. Rozwiązaniem idealnym jest zawsze udostępnienie bogatego API, umożliwiającego wykorzystywanie funkcjonalności bazy w aplikacjach.

Przegląd rozwiązań bazodanowych dla XML-a

Oracle9i

XML-owe możliwości najnowszej wersji Oracle'a zapewniane są z jednej strony przez zestaw narzędzi XDK, z drugiej - poprzez natywne wsparcie dla danych XML-owych, oferowane przez samą bazę. Dostępny dla Javy, JavaBeans, C, C++ i PL/SQL-a XML Developer's Kit (XDK) Oracle'a dostarcza wielu narzędzi XML-owych - m. in. parserów DOM i SAX, procesorów XSL i XML Schema. Oracle udostępnia także generator klas Javy z DTD lub schematu XML Schema (XML Class Generator) ułatwiający tworzenie aplikacji wymieniających dokumenty ustalonego typu i narzędzie XML SQL Utility w postaci zestawu klas Javy umożliwiających przekazywanie do bazy zapytań SQL-owych, pobieranie wyników w postaci dokumentów XML-owych oraz zapis danych XML-owych do bazy obiektowo-relacyjnej (elementy z zawartością tekstową zapisywane są w kolumnach tabel, elementy zawierające podelementy mapowane są do typów obiektowych, zaś dane nieustrukturalizowane przechowywane w polach CLOB). Ciekawie prezentuje się też serwlet XSQL, przetwarzający zapytania SQL-a osadzone w plikach XML-owych i tworzący na ich podstawie wynikowe dokumenty XML-owe. Wsparcie w samej bazie to przede wszystkim nowy, XML-owy typ danych - XMLType . Łączy on światy XML-a i SQL-a, umożliwiając m. in. wykonywanie SQL-owych operacji na zawartości XML-owej:

CREATE TABLE documents ( content SYS.XMLTYPE ); 
INSERT INTO documents VALUES ( sys.XMLType.createXML 
('<doc author="mog"><head>Simple sample</head><body>Test</body></doc>'));
SELECT content.extract ('//body/text()'). getStringVal () FROM documents
    WHERE content.existsNode ('/doc/body') = 1;

createXML(clob) - Tworzy instancję typu XMLType z wartości CLOB.

createXML(varchar2) - Tworzy instancję z napisu.

existsNode(varchar2) - Sprawdza, czy podane wyrażenie XPath zwróci jakieś węzły. Zwraca 0 lub 1.

extract(varchar2) - Stosuje do danych XML-owych wyrażenie XPath, zwraca wartość typu XMLType zawierającą wynik operacji.

getClobVal() - Pobiera fragment jako wartość CLOB.

getNumVal() - Pobiera dane tekstowe dokonując konwersji na liczbę.

getStringVal() - Pobiera fragment jako napis.

isFragment() - Sprawdza, czy wartość jest fragmentem, czy pełnym, poprawnym strukturalnie dokumentem. Daje w wyniku odpowiednio 1 lub 0.

Typu XMLType są też wartości zwracane przez nowe funkcje SQL, takie jak SYS_XMLGEN (umożliwiająca m. in. konwersję wartości skalarnych na XMLType ) czy SYS_XMLAGG (wspierająca grupowanie danych i łączenie fragmentów). Pakiet DBMS_XMLGEN umożliwia prezentację wyników dowolnych zapytań SQL-owych jako dokumentów XML-owych.

Microsoft SQL Server 2000

Możliwość pobrania danych z tabel bazy relacyjnej w formacie dokumentu XML-owego zapewnia klauzula FOR XML . Jej dodatkowy parametr określa tryb pobierania danych, co odpowiada określeniu kształtu drzewa elementów:

RAW - tryb standardowy, wynik w postaci dwupoziomowego dokumentu z elementem głównym <root> i podrzędnymi <row> (w atrybutach - zawartość pól NOT NULL pobieranych w zapytaniu),

AUTO - każda tabela reprezentowana jest w dokumencie wynikowym jako element, kolumny wybierane w klauzuli SELECT są mapowane na atrybuty lub podelementy,

EXPLICIT - wygląd drzewa może być określony dokładniej.

Przykład najprostszej kwerendy i postaci jej wyniku:

SELECT name, address FROM companies
     WHERE city = 'Warszawa' 
     FOR XML RAW <root>
       <row name="empolis Polska" address="Płocka 5a" /> </root>

Do tworzenia złożonej zawartości wynikowej SQL Server udostępnia szablony XML-owe - pliki XML-owe zawierające polecenia przetwarzania oraz dołączany do tworzonych dokumentów tekst statyczny. Szablony mogą być ponadto parametryzowane, ostatni etap przetwarzania może też realizować wskazany skrypt XSLT. Za pośrednictwem szablonów dostępny jest także mechanizm diagramów aktualizujących ( updategram ). Na podstawie podanych w treści szablonu wartości instancji XML-owej przed i po dokonaniu zmian generowane są odpowiednie kwerendy dołączające, aktualizujące lub usuwające:

<root xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
   <updg:sync mapping-schema="companies.xsd">
      <updg:before>
        <company ID="empolisPL">
          <address>Miedziana 10</address>
        </company>
      </updg:before>
      <updg:after>
         <company ID="empolisPL">
            <address>Płocka 5a</address> 
         </company>
      </updg:after>
  </updg:sync>
</root>