Uniwersytet Łódzki Wydział Matematyki i Informatyki, Katedra Analizy Nieliniowej Procesowanie dokumentów XML Programowanie w Javie 2 mgr inż. Michał Misiak
Cechy XML Sformalizowany zapis informacji restrykcyjne reguły Uniwersalność możliwość zapisania wszelkich informacji (MathXML, SVG, ) Rozszerzalność struktura informacji łatwa do rozszerzania z możliwością wykorzystania wcześniej zdefiniowanych struktur Czytelność dokumenty XML są czytelne dla człowieka, a jednocześnie łatwe w analizie dla maszyny Międzynarodowość możliwość korzystania z wielu stron kodowych lub UTF-8 Prostota łatwość zrozumienia tworzenia dokumentów
Cechy XML - wady Ograniczenia związane z hierarchiczną strukturą danych. Możliwość przedstawienia jednego typu relacji. W przypadku występowania większej liczby relacji trzeba korzystać z np. identyfikatorów Nadmiarowość informacji znaczny narzut na znaczniki przechowujące metainformacje Problemy z wydajnością przetwarzania ograniczenia pamięciowe dla dużych dokumentów Brak poprawnej implementacji standardów XML w aplikacjach
Przyczyny popularności Duża popularność i chęć używania języków znakowania (SGML, HTML powszechność) Sformalizowany sposób wymiany informacji Rozwój idei e-business (ebxml, XML nie wnosi nic nowego bo: Idea języków znakowania stosunkowo stara (SGML) Koncepcja hierarchicznych struktur danych również Sukces XML zaprezentował stare koncepcje w nowej zrozumiałej i powszechnej formie
Przetwarzanie dokumentów XML Wykorzystanie dokumentów XML w aplikacjach to: poznanie struktury pobranie zawartości poszczególnych elementów W celu optymalizacji czasu tworzenia aplikacji korzystających z XML większość języków definiuje własne API
Rodzaje API API do przetwarzania dokumentów w oparciu o: DOM Document Object Model tworzenie struktury dokumentu SAX (Simple API for XML) przetwarzanie dokumentu jako strumienia zdarzeń API zdefiniowane niezależnie od języka/platformy W przypadku języka Javy: Java API for XML Processing JAXP. JAXP pierwszy raz był wykorzystane na platformie J2EE
XML Parser XML Parser jest to procesor XML, który potrafi czytać strumień XML i przedstawić go w zrozumiałej formie dla aplikacji Aplikacja XML Parser XML XML API Dokument XML
Poprawność dokumentu Poprawność składniowa (well-formed): Zgodność z regułami składni XML gramatyka XML: Dokument niepoprawny składniowo nie może być przetworzony przez parser Brak możliwości wykorzystania zewnętrznych encji Poprawność strukturalna (valid) Zgodność z definicją dokumentu (XML Schema, DTD) gramatyka dokumentu Parsery walidujące W większości praserów można ustalić poziom sprawdzania poprawności dokumentów Różnica w wydajności pomiędzy trybami pracy
Parsery XML w Javie Wiele implementacji tego samego API przez różnych dostawców. Różnice w konfiguracji. http://java.sun.com/xml/jaxp - tutorial JAXP pozwala na integrację DOM API, SAX oraz procesorów XSLT JAXP oferuje mechanizm fabryki, który pozwala na wytworzenie instancji prasera o wymaganej konfiguracji Inne API dla XML w Javie: JAXB - Java API for XML Binding JAXR - Java API for XML Registries JAXM - Java API for XML Messaging JAX-RPC - Java API for XML-based RPC
Document Object Model (1) DOM interfejs do dokumentu XML, sposób na reprezentację struktury dokumentu Reprezentacja struktury dokumentu w postaci drzewa Rozwijany przez W3C od połowy lat 90, jak część specyfikacji HTML. Pierwsza specyfikacja DOM 1 1998 http://www.w3.org/dom/
Document Object Model (2) Specyfikacja podzielona jest na poziomy (Level) Nieoficjalny poziom 0 zaimplementowany we wszystkich przeglądarkach umożliwia dostęp do podstawowych elementów (formularzy, obrazków) Poziom 1 możliwość modyfikowania dołączania węzłów. Dostępny z poziomu JavaScript Poziom 2 obsługa zdarzeń i przestrzeni nazw Poziom 3 6 specyfikacji: Load and Save, XPath, Views & Formatting, Requirment, Validation
Model programistyczny dla DOM zapisywanie Dokument XML Parser DOM czytanie Tworzenie drzewa Kontakty Aplikacja Nawigacja & Edycja Kontakt 1 Kontakt 2 Imię Nawisko Adres
DOM w Javie Interfejsy dla DOM zostały zdefiniowane w pakiecie: org.w3c.dom Standardowy parser znajduje się w pakiecie: javax.xml.parsers Utworzenie instancji parsera: DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newdocumentbuilder(); Document mydoc = parser.parse(args[0]); Dokument DOM jest wyprowadzony i złożony z węzłów Node
Interfejs dla węzła java.lang.string getnodename() zwraca nazwę węzła short getnodetype() zwraca typ węzła np.: ATTRIBUTE_NODE, COMMENT_NODE, ELEMENT_NODE, TEXT_NODE. java.lang.string getprefix() zwraca prefiks przestrzeni nazw lub null w przypadku braku boolean haschildnodes() sprawdza, czy dany węzeł posiada dzieci NodeList getchildnotes() zwraca listę węzłów dzieci boolean hasattributes() sprawdza czy węzeł ma atrybuty NamedNodeMap getattributes() zwraca listę (dostęp po nazwach atrybutów) z atrybutami węzła java.lang.string getnodevalue() zwraca wartość węzła w zależności od jego typu dla TEXT_NODE zostanie zwrócony tekst.
Interfejs dla konkretnego typu węzła Obiekty odwzorowujące konkretny typ węzła: Element Document, Entity, Processing-Instruction Każdy z typów węzłów oferuje specyficzny interfejs, do którego dostęp uzyskujemy po prawidłowym zrzutowaniu węzła (zastosowanie metody getnodetype())
Pozostałe metody interfejsu dla DOM Node appendchild(node newchild) załącza nowy węzeł jako dziecko dla aktualnego węzła Node insertbefore(node newchild, Node refchild) wkleja nowy węzeł na miejsce wskazane przez węzeł referencyjny Node removechild(node oldchild) usuwa węzeł dziecko void setnodevalue(java.lang.string nodevalue) umożliwia ermöglicht es den Wert (=Text) eines Knotens zu ändern. o void setprefix(java.lang.string prefix) setzt den Namespace für den Knoten.
Simple API for XML Uproszone API do przetwarzania dokumentów XML Wykorzystuje koncepcję przetwarzania zdarzeniowego Zdefiniowano następujący zbiór podstawowych zdarzeń: Otwarcie znacznika Zamknięcie znacznika Wystąpienie PCDATA (Parsable Character Data) Wystąpienie CDATA (Character Data) Wystąpienie Processing Instruction Wystąpienie komentarza Wystąpienie deklaracji encji
Simple API for XML Wady SAX nie umożliwia nawigowania po dokumencie, a tym samym na jego modyfikacje Zalety Prostota implementacji Możliwość przetwarzania złożonych dokumentów: wczytywanie i walidowanie. Oszczędność pamięci.
Model programistyczny czytanie Parser DOM Dokument XML start Wystąpienie zdarzeń handler Aplikacja handler handler
SAX w Javie Wymagane pakiety: org.xml.sax.*; org.xml.sax.helpers.*; Zdarzenia są automatycznie przekazywane do Javy, która wywołuje wcześniej przygotowane metody tzw. Handlers Handlers muszą być wyprowadzone z klasy: org.xml.sax.helpers.defaulthandler
Najważniejsze metody DefaultHandler void startdocument() wołana na początku pracy parsera void enddocument() sygnalizuje, że koniec dokumentu został osiągnięty void startelement(java.lang.string uri,java.lang.string localname, java.lang.string qname, Attributes attributes) sygnalizuje pojawienie się określonego znacznika danego elementu. Parser przekazuje następujące informacje do aplikacji: Namespace (uri), Nazwa znacznika, prefiks (qname) jak również listę atrybutów
Najważniejsze metody DefaultHandler (2) void endelement( java.lang.string uri, java.lang.string localname, java.lang.string qname) sygnalizuje koniec znacznika dla danego elementu. Przekazywane są te same parametry co dla startelement() void characters(char[] ch, int start, int length) wywoływana w przypadku wystąpienia tesktu w dokumencie. Tekst zostaje umieszczony w tablicy char.
Konstrukcja parsera Właściwą instancją parsera jest: org.xml.sax.xmlreader. Jest to jedynie interfejs, którego metody należy zaimplementować Można skorzystać z fabryki: XMLReader Parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parse rs.saxparser"); Należy wskazać handlers za pomocą metody: setcontenthandler() Parser jest uruchamiany za pomocą metody parse(), która jako argument otrzymuje URI
SAX vs. DOM Brak konieczności tworzenia drzewa niesie za sobą ograniczone zasoby związane z dyskiem SAX dzięki temu może parsować bardzo duże dokumenty Dzięki modelowi zdarzeniowemu oraz braku konieczności korzystania z dysku możliwe jest parsowanie XML ze strumienia Bardzo prosty interfejs programistyczny DOM jest znacznie potężniejszy w funkcjonalności Nawigacja po dokumencie Przetwarzanie Tworzenie dokumentu DOM często wykorzystuje SAX do stworzenia modelu drzewa
SAX+DOM=SAXDOMIX Nowe powołany do życia projekt open-source łączący zalety i funkcjonalności obydwu parserów: Obiektowość DOM Szybkość i prostota SAX SAXDOMIX pozwala rozwiązywać np. problem zliczenia (SAX) i posortowania (DOM) danych SAX buduje minimalny DOM wymagany do posortowania danych Pozwala to na oszczędność miejsca oraz przechwycenie dodatkowych informacji podczas parsowania http://www.devsphere.com/xml/saxdomix/
Biblioteka JDOM Specjalnie zaprojektowany dla Javy model dokumentu Zdefiniowany w JSR 102 JDOM łączy w sobie zalety SAX i DOM Wspiera XSLT oraz XPath
Deferred Parsing Umożliwia parsowanie jedynie istotnych części dokumentu Podobny w działaniu do SAXDOMIX Celem projektu jest budowa uniwersalnego interfejsu do drzewa, który umożliwia również przetwarzanie dużych dokumentów Podejście takie oferuje parser xerces v2 http://xml.apache.org/xerces2-j/.
Pull Parsing Idea podobna do Deferred Parsing parsowanie jedynie tych części, które są konieczne Możliwość przeskakiwania części dokumentu XML w przeciwieństwie do SAX, który musi dokończyć parsowanie dokumentu Możliwość stworzenia dokumentu XML przy wykorzystaniu interfejsu, który nie jest kompatybilny z DOM http://www.extreme.indiana.edu/xgws/xsoap/xpp/
Podsumowanie Przykładowe porównanie dostawców parserów: http://xmlbench.sourceforge.net/index.php?page=results.php W pracy: porównano różnego rodzaju metody parsowania dla różnych scenariuszy. Dla małych dokumentów najefektywniejszy okazał się XPP. Mała biblioteka sprawia, że może być wykorzystywany w rozwiązaniach mobilnych Przetwarzanie olbrzymich dokumentów: SAX Edycja dokumentu oraz częste nawigowanie: DOM
Transformacje XSLT TransformerFactory static TransformerFactory newinstance() Transformer newtransformer() tworzy transformer kopiujący (np. do zapisu drzewa DOM do pliku) newtransformer(source src) tworzy transformer z arkuszem styli seterrorlistener(errorlistener el) Transformer void transform(source xmlsource, Result outputtarget) Przykład: import javax.xml.transform.*; import javax.xml.transform.stream.*; public class xslt1ex { public static void main(string[] args) throws Exception { TransformerFactory fact = TransformerFactory.newInstance(); Transformer trans = fact.newtransformer( new StreamSource("lenEx.xsl")); trans.transform(new StreamSource("lenEx.xml"), new StreamResult("lenEx.html")); } }
Dziękuje! Zapraszam na kolejne wykłady ;)