Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
Komentarz: w oryginale 12
Rozdział 9.
Java i SAX
Poprzedni rozdział w całości poświęciliśmy użyciu Javy do obsługi modelu DOM XML. Jednak
dla wielu osób użycie DOM jest zbyt skomplikowane, a traktowanie dokumentu jako drzewa
uważają za nadmiernie skomplikowane. Uważają, że to nie oni powinni przeszukiwać dokument,
ale to cały dokument powinien zostać im udostępniony. Takie właśnie głosy stały się
przyczynkiem powstania Prostego interfejsu API dla XML (SAX, Simple API for XML), któremu
poświęcimy cały ten rozdział. SAX jest znacznie prostszy w użyciu w przypadku wielu, a być
może nawet większości zastosowań XML.
Być może będziesz zaskoczony, jeśli się dowiesz, że myśl przewodnią twórców SAX-a
wcielaliśmy w życie w całym poprzednim rozdziale. Jak pamiętasz, do każdego węzła drzewa
DOM stosowaliśmy rekursywną metodę display, w tej metodzie używaliśmy z kolei instrukcji
switch. Poszczególne frazy case instrukcji switch obsługiwały różne rodzaje węzłów:
public static void display(Node node, String indent)
{
if(node == null) {
return;
}
int type = node.getNodeType();
switch (type) {
case Node.DOCUMENT_NODE: {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] +=
"";
numberDisplayLines++;
display(((Document)node).getDocumentElement(), "");
break;
}
case Node.ELEMENT_NODE: {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "<";
displayStrings[numberDisplayLines] += node.getNodeName();
int length = (node.getAttributes() != null) ?
node.getAttributes().getLength() : 0;
Attr attributes[] = new Attr[length];
for (int loopIndex = 0; loopIndex < length; loopIndex++){
attributes[loopIndex] =
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 1
2 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
(Attr)node.getAttributes().item(loopIndex);
}
}
.
.
.
Dalsze frazy case obsługiwały instrukcje przetwarzania i inne części dokumentu XML.
W zasadzie przetwarzanie dokumentów za pomocą SAX wygląda tak samo. Zamiast nawigować
sami po dokumencie, korzystamy z dokumentu opisując sposób obsługi poszczególnych
przypadków. SAX jest oparty na obsłudze zdarzeń, co oznacza, że kiedy parser SAX napotyka
element, traktuje to jako zdarzenie i wywołuje fragment kodu obsługujący elementy; kiedy
napotyka instrukcję przetwarzania, wywołuje znów inny fragment kodu, i tak dalej. W ten sposób
nie trzeba samemu po dokumencie nawigować to dokument sam się przetwarza , wystarczy
tylko odpowiednio reagować. To, że znakomita większość poprzednich przykładów na takiej
technice się opiera, wskazuje, jak użyteczna jest ta technika.
Komentarz: W.D.: AlphaWorks
Używany przez nas w poprzednim rozdziale pakiet XML for Java firmy alphaWorks obsługuje
to website IBM
także SAX. Oznacza to, że możemy użyć tych samych plików JAR, co w poprzednim rozdziale;
wystarczy tylko do zmiennej CLASSPATH dopisać na końcu ścieżki do tych plików (pamiętaj, że
wszystko ma być w jednym wierszu):
C:\SET CLASSPATH=%CLASSPATH%;C:\xmlparser\XML4J_3_0_1\xerces.jar;
C:\xmlparser\XML4J_3_0_1\xercesSamples.jar
Można też, tak jak poprzednio, użyć przełącznika -classpath:
%javac -classpath C:\xmlparser\XML4J_3_0_1\xerces.jar;
C:\xmlparser\XML4J_3_0_1\xercesSamples.jar browser.java
%java -classpath C:\xmlparser\XML4J_3_0_1\xerces.jar;
C:\xmlparser\XML4J_3_0_1\xercesSamples.jar browser
Praca z interfejsem SAX
Teraz przejdziemy do pierwszego przykładu zastosowania interfejsu SAX. Oczywiście, tak samo
jak poprzednio, zaczniemy od zliczania wystąpień elementu KLIENT w dokumencie
zamówienia.xml. Oto nasz plik roboczy XML:
Komentarz: ta sama uwaga, co
w poprzednim rozdziale jest to
plik orders.xml, a nie customer.xml
(także dalej)
Smith
Sam
15 pazdziernika 2001
Pomidory
8
5zł
Pomarańcze
24
9.98zł
2 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
Jones
Polly
20 pazdziernika 2001
Chleb
12
28.80zł
Jabłka
6
6.00zł
Weber
Bill
25 pazdziernika 2001
Asparagus
12
11.90zł
Sałata
6
31.50zł
Nasz nowy program oprzemy na nowej klasie FirstParserSAX. Będziemy potrzebować
obiektu tej klasy, aby przekazać go parserowi SAX, aby ten z kolei mógł wywoływać metody
przekazanego obiektu przy napotykaniu elementów, początku dokumentu, końca dokumentu i tak
dalej. Zaczniemy od utworzenia obiektu klasy FirstParserSAX o nazwie SAXHandler:
import org.xml.sax.*;
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX
{
public static void main(String[] args)
{
FirstParserSAX SAXHandler = new FirstParserSAX();
.
.
.
}
}
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 3
4 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Następnie tworzymy parser SAX, którego będziemy używać. Obiekt parsera jest obiektem klasy
org.apache.xerces.parsers.SAXParser (tak jak w poprzednim rozdziale parser DOM
był obiektem klasy org.apache.xerces.parsers.DOMParser). Aby użyć klasy
SAXParser, importujemy odpowiednie klasy z pakietu org.xml.sax i możemy utworzyć
nowy parser SAX o nazwie parser:
import org.xml.sax.*;
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX
{
public static void main(String[] args)
{
FirstParserSAX SAXHandler = new FirstParserSAX();
SAXParser parser = new SAXParser();
.
.
.
}
}
Klasa SAXParser pochodzi z klasy XMLParser, która z kolei pochodzi z klasy
java.lang.Object:
java.lang.Object
|
+--org.apache.xerces.framework.XMLParser
|
+--org.apache.xerces.parsers.SAXParser
Konstruktorem klasy SAXParser jest SAXParser(); metody klasy SAXParser zestawiono
w tabeli 9.1. Konstruktorem klasy XMLParser jest protectedXMLParser(). Komentarz: końcówka zdania
świadomie pominięta proszę
Tabela 9.1.
sprawdzić akapit Do Składacza
zaraz za tabelą 9.1.
Metody SAXParser
Metoda Opis
void attlistDecl(int
Metoda zwrotna deklaracji atrybutu.
elementTypeIndex, int
attrNameIndex, int
attType, java.lang.String
enumString, int
attDefaultType, int
attDefaultValue)
void characters(char[] Metoda zwrotna znaków z tablicy znakowej.
ch, int start, int
length)
void comment(int Metoda zwrotna komentarzy.
dataIndex)
void commentInDTD(int
Metoda zwrotna komentarzy występujących w DTD.
dataIndex)
void elementDecl(int
Metoda zwrotna deklaracji elementu.
elementTypeIndex,
4 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
XMLValidator.ContentSpec
contentSpec)
void endDATA()
Metoda zwrotna końca sekcji CDATA.
void endDocument()
Metoda zwrotna końca dokumentu.
void endDTD()
Wywoływana przy napotkaniu końca DTD.
void endElement(int
Metoda zwrotna końca elementów.
elementTypeIndex)
void
Metoda zwrotna końca odwołania do encji.
endEntityReference(int
entityName, int
entityType, int
entityContext)
void
Metoda zwrotna końca zakresu deklaracji przestrzeni
endNameSpaceDeclScope(int
nazw.
prefix)
void
Metoda zwrotna deklaracji parsowanej zewnętrznej encji
externalEntityDecl(int
parametrycznej.
entityName, int publicId,
int systemId)
void externalPEDecl(int
Metoda zwrotna deklaracji zewnętrznej encji
entityName, int publicId,
parametrycznej.
int systemId)
ContentHandler
Instrukcja pobierająca treść procedury obsługi zdarzenia.
getContentHandler()
protected DeclHandler
Instrukcja pobierająca procedurę obsługi zdarzenia
getDeclHandler()
deklaracji DTD.
DTDHandler
Instrukcja pobierająca bieżącą procedurę obsługi
getDTDHandler()
zdarzenia.
boolean
Pobiera bieżący stan wskazanej cechy parsera.
getFeature(java.lang.Stri
ng featureId)
java.lang.String[]
Pobiera listę cech rozpoznawanych przez parser.
getFeaturesRecognized()
protected LexicalHandler
Instrukcja pobierająca procedurę obsługi leksykalnej
getLexicalHandler()
parsera.
protected boolean
Instrukcja pobierająca wartość przedrostków przestrzeni
getNamespacePrefixes()
nazw.
java.lang.String[]
Pobiera listę właściwości rozpoznawanych przez parser.
getPropertiesRecognized()
java.lang.Object
Pobiera wartość właściwości parsera SAX2.
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 5
6 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
getProperty(java.lang.Str
ing propertyId)
void
Metoda zwrotna białych znaków, które można pominąć.
ignorableWhitespace(int
dataIndex)
protected void init()
Inicjalizuje parser na stan sprzed parsowania.
void
Metoda zwrotna deklaracji ogólnej encji wewnętrznej.
internalEntityDecl(int
entityName, int
entityValue)
void internalPEDecl(int
Metoda zwrotna deklaracji wewnętrznej encji
entityName, int
parametrycznej.
entityValue)
void internalSubset(int
Obsługa internalSubsets z DOM Level 2.
internalSubset)
void notationDecl(int
Metoda zwrotna deklaracji notacji.
notationName, int
publicId, int systemId)
void
Metoda zwrotna instrukcji przetwarzania.
processingInstruction(int
piTarget, int piData)
void
Metoda zwrotna instrukcji przetwarzania występującej
processingInstructionInDT
w DTD.
D(int piTarget, int
piData)
void
Instrukcja ustawiająca procedurę obsługi treści, co
setContentHandler(Content
umożliwia aplikacji obsługę zdarzeń SAX.
Handler handler)
protected void
Instrukcja ustawiająca procedurę obsługi deklaracji DTD.
setDeclHandler(DeclHandle
r handler)
void
Instrukcja ustawiająca procedurę obsługi dokumentu.
setDocumentHandler(Docume
ntHandler handler)
void
Instrukcja ustawiająca procedurę obsługi DTD.
setDTDHandler(DTDHandler
handler)
void
Ustawia stan dowolnej cechy parsera SAX2.
setFeature(java.lang.Stri
ng featureId, boolean
state)
protected void
Instrukcja ustawiająca procedurę obsługi leksykalnej.
6 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
setLexicalHandler(Lexical
Handler handler)
protected void
Określa, jak parser zgłasza nazwy prefiksowane oraz czy
setNamespacePrefixes(bool
zgłaszane są atrybuty xmlns.
ean process)
void
Ustawia wartość właściwości parsera SAX2.
setProperty(java.lang.Str
ing propertyId,
java.lang.Object value)
void startCDATA()
Metoda zwrotna początku sekcji CDATA.
void startDocument(int
Metoda zwrotna początku dokumentu.
versionIndex, int
encodingIndex, int
standAloneIndex)
void startDTD(int
Metoda zwrotna początku DTD.
rootElementType, int
publicId, int systemId)
void startElement(int
Metoda zwrotna początku elementu.
elementType, XMLAttrList
xmlAttrList, int
attrListIndex)
void Metoda zwrotna początku odwołania do encji.
startEntityReference(int
entityName, int
entityType, int
entityContext)
void
Metoda zwrotna początku zakresu deklaracji przestrzeni
startNamespaceDeclScope(i
nazw.
nt prefix, int uri)
void
Metoda zwrotna deklaracji encji nie parsowanej.
unparsedEntityDecl(int
entityName, int publicId,
int systemId, int
notationName)
Tabela 9.2 jest dokładny powtórzeniem tabeli 8.2, wobec czego nie widzę potrzeby
tutaj jej powtarzać z nowym numerem. Proponuję ją całkowicie pominąć, zamiast
niej wstawić akapit podany poniżej. W związku z tym oczywiście przenumerowuję
dalsze tabele tego rozdziału jeden numer w dół .
Metody klasy XMLParser były już przedstawione w poprzednim rozdziale i nie będą tutaj
powtarzane. W razie potrzeby zajrzyj do tabeli 8.2 z rozdziału 8.
Koniec proponowanego akapitu.
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 7
8 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Mamy już zatem obiekt SAXParser, pozostaje tylko powiązać obiekt SAXHandler z tym
obiektem, aby w przypadku wystąpienia poszczególnych zdarzeń parsowania takich jak początek
dokumentu, rozpoczęcie nowego elementu i tak dalej, wywoływane były metody obiektu
SAXHandler. Parsery SAX wywołują wiele metod, na przykład dla elementów, instrukcji
przetwarzania, deklaracji w DTD i tak dalej. Metody wywoływane przez parser SAX w celu
poinformowania o wystąpieniu jakiejś sytuacji nazywamy metodami zwrotnymi, muszą one być
w parserze SAX zarejestrowane.
Cztery podstawowe interfejsy SAX obsługują różne metody zwrotne:
" EntityResolver obsługuje specjalizowaną obsługę encji zewnętrznych.
" DTDHandler obsługuje zdarzenia związane z DTD.
" ContentHandler obsługuje treść dokumentu, na przykład elementy i instrukcje
przetwarzania.
" ErrorHandler obsługuje błędy powstające w trakcie parsowania.
Powyższe interfejsy zawierają wiele metod zwrotnych; jeśli chcesz używać danego interfejsu,
musisz zaimplementować jego wszystkie metody. Praca z pakietem XML for Java jest pod tym
względem łatwiejsza, gdyż tworzona jest klasa DefaultHandler zawierająca implementację
domyślną wszystkich potrzebnych metod zwrotnych. Konstruktorem klasy DefaultHandler
jest DefaultHandler(); metody tej klasy zestawiono w tabeli 9.2.
Komentarz: przesunięte
Tabela 9.2.
z numeru 9.3.
Metody DefaultHandler
Metoda Opis
void characters(char[] Metoda zwrotna danych znakowych z elementu.
ch, int start, int
length)
void endDocument()
Metoda zwrotna końca dokumentu.
void
Metoda zwrotna końca elementu.
endElement(java.lang.Stri
ng uri, java.lang.String
localName,
java.lang.String rawName)
void
Metoda zwrotna końca odwzorowania przestrzeni nazw.
endPrefixMapping(java.lan
g.String prefix
void
Metoda zwrotna błędu parsera, który to błąd może zostać
error(SAXParseException
naprawiony.
e)
void Metoda zwrotna błędu krytycznego parsowania XML.
fatalError(SAXParseExcept
ion e)
void
Metoda zwrotna pomijalnych białych znaków w treści
8 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
ignorableWhitespace(char[ elementu.
] ch, int start, int
length)
void
Metoda zwrotna deklaracji notacji.
notationDecl(java.lang.St
ring name,
java.lang.String
publicId,
java.lang.String
systemId)
void
Metoda zwrotna instrukcji przetwarzania.
processingInstruction(jav
a.lang.String target,
java.lang.String data)
InputSource
Metoda zwrotna encji zewnętrznej.
resolveEntity(java.lang.S
tring publicId,
java.lang.String
systemId)
void
Ustawia obiekt klasy Locator dla zdarzeń dokumentu.
setDocumentLocator(Locato
r locator)
void
Metoda zwrotna pominiętej encji.
skippedEntity(java.lang.S
tring name)
void startDocument()
Metoda zwrotna początku dokumentu.
void
Metoda zwrotna początku elementu.
startElement(java.lang.St
ring uri,
java.lang.String
localName,
java.lang.String rawName,
Attributes attributes)
void
Metoda zwrotna początku odwzorowania przestrzeni
startPrefixMapping(java.l
nazw.
ang.String prefix,
java.lang.String uri)
void
Metoda zwrotna deklaracji encji nieparsowanej.
unparsedEntityDecl(java.l
ang.String name,
java.lang.String
publicId,
java.lang.String
systemId,
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 9
10 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
java.lang.String
notationName)
void
Metoda zwrotna ostrzeżenia parsera.
warning(SAXParseException
e)
Jeśli swój program oprzesz na interfejsie DefaultHandler, musisz zaimplementować tylko
potrzebne Ci metody zwrotne, zatem główna klasa naszego programu, FirstParserSAX,
pochodzić będzie od interfejsu DefaultHandler, co zaznacza się słowem kluczowym
extends:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX extends DefaultHandler
{
public static void main(String[] args)
{
FirstParserSAX SAXHandler = new FirstParserSAX();
SAXParser parser = new SAXParser();
.
.
.
}
}
Teraz możemy już naszą klasę FirstParserSAX zarejestrować w parserze SAX. Nie będziemy
się martwić o obsługę DTD ani o rozwijanie encji zewnętrznych, ograniczymy się do obsługi treści
dokumentu i błędów metodami setContentHandler i setErrorHandler:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX extends DefaultHandler
{
public static void main(String[] args)
{
FirstParserSAX SAXHandler = new FirstParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler(SAXHandler);
parser.setErrorHandler(SAXHandler);
.
.
.
}
}
W ten sposób zarejestrowaliśmy obiekt SAXHandler, który będzie teraz odbierał zdarzenia SAX
treści dokumentu i błędów. Dodamy metody, które będą wywoływane po zakończeniu działania
metody main.
Do parsowania dokumentu XML użyjemy metody parse obiektu parser. Umożliwimy
użytkownikowi podanie nazwy parsowanego dokumentu w wierszu poleceń, jak args[0]
(pamiętaj, że nie musi to być nazwa pliku lokalnego, może to być także adres URL dokumentu
10 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
znajdującego się gdzieś w Internecie). Metoda parse może generować wyjątki, co oznacza, że
trzeba ją zamknąć w bloku try i dopisać odpowiadający mu blok catch:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX extends DefaultHandler
{
public static void main(String[] args)
{
try {
FirstParserSAX SAXHandler = new FirstParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler(SAXHandler);
parser.setErrorHandler(SAXHandler);
parser.parse(args[0]);
}
catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
W ten sposób przygotowaliśmy już metodę main, teraz trzeba dopisać metody wywoływane
podczas parsowania dokumentu XML. Naszym celem jest określenie liczby wystąpień elementu
KLIENT, wobec czego implementację metody startElement zaczniemy następująco:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX extends DefaultHandler
{
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
.
.
.
}
.
.
.
Komentarz: te kropki są zamiast
funkcji main(); powtarzanie
Metoda startElement wywoływana jest za każdym razem, kiedy parser SAX napotyka
za każdym razem main(), w której
początek elementu, natomiast metoda endElement jest wywoływana, kiedy parser napotyka
nic się nie zmienia, nie ma sensu;
to samo dotyczy następnych
koniec elementu.
wydruków.
Zwróć uwagę na to, że metoda startElement przetwarza dwie nazwy elementu: localName
i rawName. Podczas przetwarzania z przestrzeniami nazw używa się parametru localName,
gdyż zawiera on nazwę samego elementu, bez przedrostka przestrzeni nazw. Parametr rawName
zawiera pełną, kwalifikowaną nazwę elementu wraz z przedrostkiem.
Zamierzamy zliczać wystąpienia elementu KLIENT, wobec czego skorzystamy z parametru
rawName jeśli jego wartością będzie KLIENT , zwiększymy wartość zmiennej
customerCount:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 11
12 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX extends DefaultHandler
{
int customerCount = 0;
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if (rawName.equals("KLIENT")) {
customerCount++;
}
}
.
.
.
Skąd wiadomo, że dokument już się skończył i że nie ma już elementów KLIENT do zliczania?
Używa się metody endDocument wywoływanej przy napotkaniu końca dokumentu, w tej
metodzie wyświetlamy odpowiedz dla użytkownika:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class FirstParserSAX extends DefaultHandler
{
int customerCount = 0;
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if (rawName.equals("KLIENT")) {
customerCount++;
}
}
public void endDocument()
{
System.out.println("Dokument zawiera " +
customerCount + " element. KLIENT.");
}
public static void main(String[] args)
{
try {
FirstParserSAX SAXHandler = new FirstParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler(SAXHandler);
parser.setErrorHandler(SAXHandler);
parser.parse(args[0]);
}
catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
Teraz już program można skompilować i uruchomić:
%java FirstParserSAX zamówienia.xml
Dokument zawiera 3 element. KLIENT.
12 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
I tak oto zaczęliśmy naszą pracę z pakietem SAX.
Wyświetlanie całego dokumentu
W następnym przykładzie, jak w rozdziale poprzednim, napiszemy program parsujący
i wyświetlający cały dokument z wcięciami poszczególnych elementów, instrukcji przetwarzania
i tak dalej, a także pokazujący atrybuty i ich wartości. Tym razem jednak zamiast metod DOM
użyjemy metod SAX. Program nazwiemy IndentingParserSAX.java; jeśli przekażemy mu nazwę
pliku zamówienia.xml, wyświetlony zostanie cały dokument z odpowiednimi wcięciami.
Zaczynamy od umożliwienia użytkownikowi wskazania dokumentu który ma być parsowany,
następnie dokument parsujemy. Z metody main wywołamy nową metodę displayDocument,
która wypełni tablicę displayStrings sformatowanymi wierszami dokumentu, następnie
metoda main tę tablicę wyświetli:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class IndentingParserSAX
{
public static void displayDocument(String uri)
{
.
.
.
}
public static void main(String[] args)
{
displayDocument(args[0]);
for(int index = 0; index < numberDisplayLines; index++){
System.out.println(displayStrings[index]);
}
}
}
W metodzie displayDocument utworzymy parser SAX i zarejestrujemy obiekt głównej klasy
programu, aby SAX w odpowiedzi na zdarzenia wywoływał jego metody:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class IndentingParserSAX
{
public static void displayDocument(String uri)
{
try {
IndentingParserSAX SAXHandler = new IndentingParserSAX();
Komentarz: dodałem operator
SAXParser parser = new SAXParser();
rzutowania kod w postaci
parser.setContentHandler((ContentHandler) SAXHandler);
podanej przez Autora nie działa.
parser.setErrorHandler((ErrorHandler) SAXHandler);
parser.parse(uri);
Komentarz: jak wyżej
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 13
14 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public static void main(String[] args)
{
displayDocument(args[0]);
for(int index = 0; index < numberDisplayLines; index++){
System.out.println(displayStrings[index]);
}
}
}
Teraz pozostało już tylko utworzyć różne metody wywoływane w odpowiedzi na zdarzenia
generowane przez SAX, zaczniemy od początku dokumentu.
Obsługa początku dokumentu
Kiedy parser SAX napotyka początek parsowanego dokumentu, wywołuje metodę
startDocument. Metoda ta nie otrzymuje żadnych parametrów, zatem wystarczy w niej
wyświetlić deklarację XML. Tak jak w poprzednim rozdziale, wszystkie gotowe fragmenty
dokumentu będziemy zapisywać w tablicy displayStrings obiektów String, a bieżącą
pozycję będziemy zapisywać w zmiennej numberDisplayLines. Aktualne wcięcie będziemy
zapisywać w obiekcie indent klasy String. Użycie tablicy napisów ułatwi przekształcenie
programu tak, aby mógł wyświetlać dane w oknie Javy.
Oto kod obsługujący wyświetlenie deklaracji XML na początku dokumentu:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class IndentingParserSAX
{
static String displayStrings[] = new String[1000];
static int numberDisplayLines = 0;
static String indent = "";
public static void displayDocument(String uri)
{
try {
IndentingParserSAX SAXHandler = new IndentingParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler((ContentHandler) SAXHandler);
parser.setErrorHandler((ErrorHandler) SAXHandler);
parser.parse(uri);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public void startDocument()
{
14 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] +=
"";
numberDisplayLines++;
}
.
.
.
public static void main(String[] args)
{
displayDocument(args[0]);
for(int index = 0; index < numberDisplayLines; index++){
System.out.println(displayStrings[index]);
}
}
}
Następnie zajmiemy się instrukcjami przetwarzania.
Obsługa instrukcji przetwarzania
Obsługę instrukcji przetwarzania umożliwia metoda zwrotna processingInstruction.
Wywoływana jest z dwoma parametrami: samą instrukcją przetwarzania i jej danymi. Jeśli
na przykład cała instrukcja przetwarzania w dokumencie ma postać type="text/css" href="style.css"?>, sama instrukcja to xml-stylesheet, a jej
dane to type="text/css" href="style.css".
Poniżej pokazano kod metody processingInstruction, która obsługuje te metody; zwróć
uwagę na to, że przed dodaniem danych instrukcji sprawdzamy, czy instrukcja w ogóle jakieś dane
ma:
Komentarz: w tym i następnych
public void processingInstruction(String target, String data)
punktach pomijam powtarzającą
{
się definicję klasy pozostawiam
displayStrings[numberDisplayLines] = indent;
tylko nowy fragment (metodę);
displayStrings[numberDisplayLines] += "";
jako że jest on jedyną częścią
displayStrings[numberDisplayLines] += target;
listingu, nie wyszarzam go.
if(data != null && data.length() > 0) {
displayStrings[numberDisplayLines] += data;
}
displayStrings[numberDisplayLines] += "?>";
numberDisplayLines++;
}
Obsługa początku elementu
Początek elementu można obsłużyć metodą startElement. Skoro mamy do czynienia
z nowym elementem, dodajemy do wcięcia cztery spacje (będą używane przy przetwarzaniu
potomków bieżącego elementu), następnie wyświetlamy nazwę używając parametru rawName:
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
displayStrings[numberDisplayLines] = indent;
indent += " ";
displayStrings[numberDisplayLines] += "<";
displayStrings[numberDisplayLines] += rawName;
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 15
16 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
displayStrings[numberDisplayLines] += ">";
numberDisplayLines++;
}
Powyższy kod wystarczy do wyświetlenia znacznika początkowego elementu, ale co z elementami
mającymi atrybuty?
Obsługa atrybutów
Jednym z argumentów przekazywanych metodzie startElement jest obiekt odpowiadający
interfejsowi Attributes:
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
.
.
.
}
Obiekt ten udostępnia atrybuty elementu, jego metody zestawiono w tabeli 9.3. Do atrybutów
opisanych w tym interfejsie można dostać się korzystając ze wskaznika, nazwy lub nazwy
kwalifikowanej przestrzenią nazw.
Komentarz: przesunięto
Tabela 9.3.
z numeru 9.4.
Metody interfejsu Attributes
Metoda Opis
int
Pobiera wskaznik atrybutu wskazanego nazwą bez przestrzeni
getIndex(java.lang.S
nazw.
tring rawName)
int
Pobiera wskaznik atrybutu na podstawie przestrzeni nazw i nazwy
getIndex(java.lang.S
lokalnej.
tring uri,
java.lang.String
localPart
int getLength()
Pobiera liczbę atrybutów z listy.
java.lang.String
Pobiera nazwę lokalną atrybutu o podanym indeksie.
getLocalName(int
index)
java.lang.String Pobiera nazwę atrybutu o podanym indeksie.
getRawName(int
index)
java.lang.String
Pobiera typ atrybutu o podanym indeksie.
getType(int index)
java.lang.String
Pobiera typ atrybutu według samej nazwy.
getType(java.lang.St
ring rawName)
java.lang.String Pobiera typ atrybutu według przestrzeni nazw i nazwy lokalnej.
16 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
getType(java.lang.St
ring uri,
java.lang.String
localName)
java.lang.String
Pobiera adres URI przestrzeni nazw atrybutu według indeksu tego
getURI(int index)
atrybutu.
java.lang.String
Pobiera wartość atrybutu o podanym indeksie.
getValue(int index)
java.lang.String
Pobiera wartość atrybutu według jego nazwy.
getValue(java.lang.S
tring rawName)
java.lang.String
Pobiera wartość atrybutu według przestrzeni nazw i nazwy
getValue(java.lang.S
lokalnej.
tring uri,
java.lang.String
localName)
Liczbę atrybutów określamy metodą getLength obiektu Attributes, następnie nazwy
i wartości kolejnych atrybutów pobieramy za pomocą metod getRawName i getValue,
do poszczególnych atrybutów odwołujemy się za pomocą indeksów. Zwróć uwagę, że zaczynamy
od sprawdzenia, czy element ma w ogóle jakieś atrybuty sprawdzamy, czy wartość parametru
attributes jest różna od null:
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
displayStrings[numberDisplayLines] = indent;
indent += " ";
displayStrings[numberDisplayLines] += "<";
displayStrings[numberDisplayLines] += rawName;
if (attributes != null) {
int numberAttributes = attributes.getLength();
for (int loopIndex = 0; loopIndex < numberAttributes;
loopIndex++) {
displayStrings[numberDisplayLines] += ' ';
displayStrings[numberDisplayLines] +=
attributes.getRawName(loopIndex);
displayStrings[numberDisplayLines] += "=\"";
displayStrings[numberDisplayLines] +=
attributes.getValue(loopIndex);
displayStrings[numberDisplayLines] += '"';
}
}
displayStrings[numberDisplayLines] += ">";
numberDisplayLines++;
}
I to tyle, jeśli chodzi o atrybuty.
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 17
18 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Obsługa tekstu
Wiele elementów dokumentu zamówienia.xml zawiera tekst: IMI, NAZWISKO i inne.
Do wyświetlania tekstu używamy metody zwrotnej characters.
Metoda ta jest wywoływana z trzema argumentami: tablicą elementów typu char zawierającą
tekst, wskaznikiem początkowym tablicy oraz długością tekstu. Jeśli element zawiera tylko węzeł
tekstowy, wskaznik początkowy jest zawsze równy 0.
Żeby obsłużyć tekst znajdujący się wewnątrz elementów, zaimplementujemy metodę
characters konwertującą tablicę znakową na obiekt String o nazwie characterData
zwróć uwagę na metodę trim klasy String używaną do usunięcia spacji wiodących
i końcowych:
public void characters(char characters[], int start, int length)
{
String characterData = (new String(characters, start,
length)).trim();
.
.
.
}
Aby usunąć tekst odpowiadający wcięciom, czyli spacjom początkowym występującym
w dokumencie zamówienia.xml, dodamy instrukcję if i dopiero potem będziemy dodawać sam
tekst do wyniku:
public void characters(char characters[], int start, int length)
{
String characterData = (new String(characters, start,
length)).trim();
if(characterData.indexOf("\n") < 0 && characterData.length() >
0) {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += characterData;;
numberDisplayLines++;
}
}
Zatem z tekstem już sobie poradziliśmy. Domyślnie parser SAX przetwarza także białe znaki
z dokumentu użyte do wizualizacji wcięć.
Obsługa pomijalnych białych znaków
Jak zatem można nakazać pominięcie zbędnych białych znaków? W przypadku parsera SAX jest
to prostsze niż w parserze DOM. Parser SAX musi wiedzieć, jaki tekst ma być pomijany, zatem
trzeba podać mu gramatykę dokumentu zamówienia.xml na przykład w postaci DTD:
18 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
]>
Smith
Sam
15 pazdziernika 2001
Pomidory
8
5zł
Pomarańcze
24
9.98zł
Jones
Polly
20 pazdziernika 2001
Chleb
12
28.80zł
Jabłka
6
6.00zł
Weber
Bill
25 pazdziernika 2001
Asparagus
12
11.90zł
Sałata
6
31.50zł
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 19
20 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Teraz przy napotkaniu pomijalnych znaków białych (takich jak spacje tworzące wcięcia
elementów) nie będzie wywoływał metody zwrotnej characters, natomiast wywoła w takiej
sytuacji metodę ignorableWhitespace. Oznacza to, że można wykomentować instrukcję if
użytą uprzednio do odrzucania pomijalnych białych znaków:
public void characters(char characters[], int start, int length)
{
String characterData = (new String(characters, start,
length)).trim();
//if(characterData.indexOf("\n") < 0 && characterData.length()
> 0) {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += characterData;;
numberDisplayLines++;
//}
}
Jeśli zatem chcesz, aby zbędne białe znaki były pomijane, wystarczy poinformować parser SAX,
które z nich są faktycznie zbędne; zrobić to można za pomocą DTD.
Zwróć uwagę na to, że możesz zapisać tak metodę ignorableWhitespace, aby traktowała
pomijane białe znaki tak, jak jest to akurat potrzebne. Można ich wcale nie pomijać, jeśli się je
przekaże metodzie zwrotnej characters:
public void ignorableWhitespace(char characters[], int start, int
length)
{
characters(characters, start, length);
}
Domykanie znaczników
Jak dotąd obsłużyliśmy już początki wszystkich elementów za każdym razem zwiększając
wcięcie, aby prawidłowo wyświetlone zostały elementy potomne. Musimy jeszcze wyświetlić
znaczniki końcowe tym razem zmniejszając wielkość wcięcia. Robimy to stosując metodę zwrotną
endElement, która jest wywoływana za każdym razem, kiedy parser SAX znajduje koniec
elementu:
public void endElement(String uri, String localName, String
rawName)
{
indent = indent.substring(0, indent.length() - 4);
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += rawName;
displayStrings[numberDisplayLines] += '>';
numberDisplayLines++;
}
Na koniec zostało nam już tylko jedno: obsługa błędów i ostrzeżeń.
20 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
Obsługa błędów i ostrzeżeń
Interfejs DefaultHandler definiuje kilka metod zwrotnych pozwalających obsłużyć
ostrzeżenia i błędy generowane przez parser. Metody te to warning do obsługi ostrzeżeń,
error do obsługi błędów parsera oraz fatalError do obsługi błędów krytycznych tak
poważnych, że parser nie może kontynuować swojego działania.
Każda z tych metod otrzymuje jako parametr obiekt klasy SAXParseException zawierający
metodę getMessage zwracającą komunikat ostrzeżenia lub błędu. Komunikaty te będziemy
wyświetlać przy pomocy metody System.err.println, która wypisuje dane do strumienia
błędów Javy, który domyślnie odpowiada konsoli:
public void warning(SAXParseException exception)
{
System.err.println("OSTRZEŻENIE! " +
exception.getMessage());
}
public void error(SAXParseException exception)
{
System.err.println("BAD! " +
exception.getMessage());
}
public void fatalError(SAXParseException exception)
{
System.err.println("BAD KRYTYCZNY! " +
exception.getMessage());
}
I to już wszystko, czego potrzebujemy. Wyniki parsowania dokumentu zamówienia.xml pokazano
na rysunku 9.1. Dodatkowo użyto filtru more, aby zatrzymać wyświetlanie po każdym ekranie.
Program działa, a cały jego kod znajdziesz na wydruku 9.1.
Rysunek 9.1.
Parsowanie
dokumentu XML
parserem SAX.
Wydruk 9.1.
IndentingParserSAX.java
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class IndentingParserSAX extends DefaultHandler
{
static String displayStrings[] = new String[1000];
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 21
22 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
static int numberDisplayLines = 0;
static String indent = "";
public static void displayDocument(String uri)
{
try {
IndentingParserSAX SAXHandler = new IndentingParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler((ContentHandler) SAXHandler);
parser.setErrorHandler((ErrorHandler) SAXHandler);
parser.parse(uri);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public void startDocument()
{
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] +=
"";
numberDisplayLines++;
}
public void processingInstruction(String target, String data)
{
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += target;
if(data != null && data.length() > 0) {
displayStrings[numberDisplayLines] += data;
}
displayStrings[numberDisplayLines] += "?>";
numberDisplayLines++;
}
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
displayStrings[numberDisplayLines] = indent;
indent += " ";
displayStrings[numberDisplayLines] += "<";
displayStrings[numberDisplayLines] += rawName;
if (attributes != null) {
int numberAttributes = attributes.getLength();
for (int loopIndex = 0; loopIndex < numberAttributes;
loopIndex++) {
displayStrings[numberDisplayLines] += ' ';
displayStrings[numberDisplayLines] +=
attributes.getRawName(loopIndex);
displayStrings[numberDisplayLines] += "=\"";
displayStrings[numberDisplayLines] +=
attributes.getValue(loopIndex);
displayStrings[numberDisplayLines] += '"';
}
}
displayStrings[numberDisplayLines] += ">";
22 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
numberDisplayLines++;
}
public void characters(char characters[], int start, int length)
{
String characterData = (new String(characters, start,
length)).trim();
if(characterData.indexOf("\n") < 0 && characterData.length() >
0) {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += characterData;;
numberDisplayLines++;
}
}
public void ignorableWhitespace(char characters[], int start, int
length)
{
//characters(characters, start, length);
}
public void endElement(String uri, String localName, String
rawName)
{
indent = indent.substring(0, indent.length() - 4);
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += rawName;
displayStrings[numberDisplayLines] += '>';
numberDisplayLines++;
}
public void warning(SAXParseException exception)
{
System.err.println("OSTRZEŻENIE! " +
exception.getMessage());
}
public void error(SAXParseException exception)
{
System.err.println("BAD! " +
exception.getMessage());
}
public void fatalError(SAXParseException exception)
{
System.err.println("BAD KRYTYCZNY! " +
exception.getMessage());
}
public static void main(String[] args)
{
displayDocument(args[0]);
for(int index = 0; index < numberDisplayLines; index++){
System.out.println(displayStrings[index]);
}
}
}
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 23
24 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Filtrowanie dokumentów XML
W poprzednim przykładzie wyświetlaliśmy cały dokument, jednak w procesie filtrowania można
uzyskać tylko wybraną część dokumentu. Filtrowanie pozwala wybrać z dokumentu tylko te
elementy, które są w danej chwili istotne.
Oto przykład nazwany searcherSAX.java. Umożliwiamy użytkownikowi wskazać przeszukiwany
dokument i wskazać elementy, które mają być wybrane oto jak wybrać elementy POZYCJA
z dokumentu zamówienia.xml:
Komentarz: uwaga
%java searcherSAX zamówienia.xml POZYCJA
do przykładu taka, jak poprzednio
w tym rozdziale.
Program taki nie będzie skomplikowany, szczególnie kiedy już mamy parser wzbogacający
dokument o stosowne wcięcia. Pamiętaj jednak, że tym razem musimy wybrać nie tylko elementy
wskazane przez użytkownika, ale także ich elementy potomne. Nowy program, searcherSAX.java,
utworzymy na podstawie IndentingParserSAX.java. Wystarczy jedynie dodać kontrolę, kiedy
element ma być pokazywany, a kiedy nie. Jeśli bieżący element jest elementem wybranym
przez użytkownika, zmiennej logicznej printFlag przypiszemy wartość true:
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if (rawName.equals(searchFor)) {
printFlag = true;
}
.
.
.
}
Teraz można już sprawdzać, czy zmienna printFlag ma wartość true; jeśli tak, bieżący
element wraz z atrybutami ma być wyświetlony:
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if (rawName.equals(searchFor)) {
printFlag = true;
}
if (printFlag) {
displayStrings[numberDisplayLines] = indent;
indent += " ";
displayStrings[numberDisplayLines] += "<";
displayStrings[numberDisplayLines] += rawName;
if (attributes != null) {
int numberAttributes = attributes.getLength();
for (int loopIndex = 0; loopIndex < numberAttributes;
loopIndex++) {
displayStrings[numberDisplayLines] += ' ';
displayStrings[numberDisplayLines] +=
attributes.getRawName(loopIndex);
displayStrings[numberDisplayLines] += "=\"";
displayStrings[numberDisplayLines] +=
attributes.getValue(loopIndex);
displayStrings[numberDisplayLines] += '"';
}
}
24 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
displayStrings[numberDisplayLines] += ">";
numberDisplayLines++;
}
}
To samo możemy zrobić z metodą zwrotną dodającą tekst, character:
public void characters(char characters[], int start, int length)
{
if (printFlag) {
String characterData = (new String(characters, start,
length)).trim();
if(characterData.indexOf("\n") < 0 && characterData.length()
> 0) {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += characterData;;
numberDisplayLines++;
}
}
}
Zwróć uwagę, że wartości zmiennej printFlag nie zmieniamy na false póki nie skończy się
poszukiwany element, kiedy wyświetlony jest już on i jego elementy potomne. Dopiero
po zakończeniu takiego elementu zerujemy zmienną printFlag:
public void endElement(String uri, String localName, String
rawName)
{
if (printFlag) {
indent = indent.substring(0, indent.length() - 4);
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += rawName;
displayStrings[numberDisplayLines] += '>';
numberDisplayLines++;
}
if (rawName.equals(searchFor)) {
printFlag = false;
}
}
Na tym nasza praca się kończy. Poniższe wywołanie wyszukuje elementy POZYCJA
w dokumencie zamówienia.xml:
%java searcherSAX zamówienia.xml POZYCJA | more
Wyniki pokazano na rysunku 9.2., zaś cały program na wydruku 9.2.
Rysunek 9.2.
Filtrowanie
dokumentu XML
przy użyciu
parsera SAX
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 25
26 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Wydruk 9.2.
searcherSAX.java
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class searcherSAX extends DefaultHandler
{
static String displayStrings[] = new String[1000];
static int numberDisplayLines = 0;
static String indent = "";
static boolean printFlag;
static String searchFor;
public static void displayDocument(String uri)
{
try {
IndentingParserSAX SAXHandler = new IndentingParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler((ContentHandler) SAXHandler);
parser.setErrorHandler((ErrorHandler) SAXHandler);
parser.parse(uri);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public void startDocument()
{
if(printFlag){
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] +=
"";
numberDisplayLines++;
}
}
public void processingInstruction(String target, String data)
{
if(printFlag){
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += target;
if(data != null && data.length() > 0) {
displayStrings[numberDisplayLines] += data;
}
displayStrings[numberDisplayLines] += "?>";
numberDisplayLines++;
}
}
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if (rawName.equals(searchFor)) {
printFlag = true;
}
if (printFlag) {
26 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
displayStrings[numberDisplayLines] = indent;
indent += " ";
displayStrings[numberDisplayLines] += "<";
displayStrings[numberDisplayLines] += rawName;
if (attributes != null) {
int numberAttributes = attributes.getLength();
for (int loopIndex = 0; loopIndex < numberAttributes;
loopIndex++) {
displayStrings[numberDisplayLines] += ' ';
displayStrings[numberDisplayLines] +=
attributes.getRawName(loopIndex);
displayStrings[numberDisplayLines] += "=\"";
displayStrings[numberDisplayLines] +=
attributes.getValue(loopIndex);
displayStrings[numberDisplayLines] += '"';
}
}
displayStrings[numberDisplayLines] += ">";
numberDisplayLines++;
}
}
public void characters(char characters[], int start, int length)
{
if (printFlag) {
String characterData = (new String(characters, start,
length)).trim();
if(characterData.indexOf("\n") < 0 && characterData.length()
> 0) {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += characterData;;
numberDisplayLines++;
}
}
}
public void ignorableWhitespace(char characters[], int start, int
length)
{
if(printFlag){
//characters(characters, start, length);
}
}
public void endElement(String uri, String localName, String
rawName)
{
if (printFlag) {
indent = indent.substring(0, indent.length() - 4);
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += rawName;
displayStrings[numberDisplayLines] += '>';
numberDisplayLines++;
}
if (rawName.equals(searchFor)) {
printFlag = false;
}
}
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 27
28 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
public void warning(SAXParseException exception)
{
System.err.println("OSTRZEŻENIE! " +
exception.getMessage());
}
public void error(SAXParseException exception)
{
System.err.println("BAD! " +
exception.getMessage());
}
public void fatalError(SAXParseException exception)
{
System.err.println("BAD KRYTYCZNY! " +
exception.getMessage());
}
public static void main(String[] args)
{
String arg = args[0];
searchFor = args[1];
displayDocument(args[0]);
for(int index = 0; index < numberDisplayLines; index++){
System.out.println(displayStrings[index]);
}
}
}
Tworzone dotąd przykłady dawały wyniki w postaci tekstu wyprowadzanego metodą
System.out.println. Jednak jak już wspomniano w poprzednim rozdziale, dzisiaj niewiele
przeglądarek działa w ten sposób teraz zajmiemy się tworzeniem przeglądarek posiadających
własne okienka.
Tworzenie przeglądarki okienkowej
Napisaliśmy już parser realizujący wcięcia, który wyświetlany tekst zapisywał w tablicy
displayStrings, zatem łatwo będzie teraz wyświetlić ten tekst w oknie Javy, tak samo, jak to
robiliśmy w poprzednim rozdziale. Utworzymy nowy przykład o nazwie browserSAX.java.
Utworzymy tam obiekt nowej klasy AppFrame, jego konstruktorowi przekażemy
displayStrings oraz liczbę wierszy do wyświetlenia, następnie wywołamy jego metodę
show pokazującą nowe okno:
import java.awt.*;
import java.awt.event.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class browserSAX extends DefaultHandler
{
.
.
.
28 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
public static void main(String[] args)
{
displayDocument(args[0]);
AppFrame f = new AppFrame(displayStrings, numberDisplayLines);
f.setSize(300, 500);
f.addWindowListener(new WindowAdapter() { public void
windowClosing(WindowEvent e) {System.exit(0);}});
f.show();
}
}
Klasa AppFrame pochodzi od klasy Frame Javy, wyświetla przekazany jej tekst:
class AppFrame extends Frame
{
String displayStrings[];
int numberDisplayLines;
public AppFrame(String[] d, int n)
{
displayStrings = d;
numberDisplayLines = n;
}
public void paint(Graphics g)
{
Font font;
font = new Font("Courier", Font.PLAIN, 12);
g.setFont(font);
FontMetrics fontmetrics = g.getFontMetrics(getFont());
int y = fontmetrics.getHeight();
for(int index = 0; index < numberDisplayLines; index++) {
y += fontmetrics.getHeight();
g.drawString(displayStrings[index], 5, y);
}
}
}
Działanie programu browserSAX pokazano na rysunku 9.3, gdzie w okienku Javy wyświetlony
został plik zamówienia.xml. Całość kodu pokazano na wydruku 9.3.
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 29
30 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Rysunek 8.3.
Przeglądarka
graficzna
stworzona
przy użyciu
parsera SAX
Wydruk 9.3.
browserSAX.java
import java.awt.*;
import java.awt.event.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class browserSAX extends DefaultHandler
{
static String displayStrings[] = new String[1000];
static int numberDisplayLines = 0;
static String indent = "";
public static void displayDocument(String uri)
{
try {
IndentingParserSAX SAXHandler = new IndentingParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler((ContentHandler) SAXHandler);
parser.setErrorHandler((ErrorHandler) SAXHandler);
parser.parse(uri);
} catch (Exception e) {
e.printStackTrace(System.err);
}
30 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
}
public void startDocument()
{
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] +=
"";
numberDisplayLines++;
}
public void processingInstruction(String target, String data)
{
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += target;
if(data != null && data.length() > 0) {
displayStrings[numberDisplayLines] += data;
}
displayStrings[numberDisplayLines] += "?>";
numberDisplayLines++;
}
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
displayStrings[numberDisplayLines] = indent;
indent += " ";
displayStrings[numberDisplayLines] += "<";
displayStrings[numberDisplayLines] += rawName;
if (attributes != null) {
int numberAttributes = attributes.getLength();
for (int loopIndex = 0; loopIndex < numberAttributes;
loopIndex++) {
displayStrings[numberDisplayLines] += ' ';
displayStrings[numberDisplayLines] +=
attributes.getRawName(loopIndex);
displayStrings[numberDisplayLines] += "=\"";
displayStrings[numberDisplayLines] +=
attributes.getValue(loopIndex);
displayStrings[numberDisplayLines] += '"';
}
}
displayStrings[numberDisplayLines] += ">";
numberDisplayLines++;
}
public void characters(char characters[], int start, int length)
{
String characterData = (new String(characters, start,
length)).trim();
if(characterData.indexOf("\n") < 0 && characterData.length() >
0) {
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += characterData;;
numberDisplayLines++;
}
}
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 31
32 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
public void ignorableWhitespace(char characters[], int start, int
length)
{
//characters(characters, start, length);
}
public void endElement(String uri, String localName, String
rawName)
{
indent = indent.substring(0, indent.length() - 4);
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += rawName;
displayStrings[numberDisplayLines] += '>';
numberDisplayLines++;
}
public void warning(SAXParseException exception)
{
System.err.println("OSTRZEŻENIE! " +
exception.getMessage());
}
public void error(SAXParseException exception)
{
System.err.println("BAD! " +
exception.getMessage());
}
public void fatalError(SAXParseException exception)
{
System.err.println("BAD KRYTYCZNY! " +
exception.getMessage());
}
public static void main(String[] args)
{
displayDocument(args[0]);
AppFrame f = new AppFrame(displayStrings, numberDisplayLines);
f.setSize(300, 500);
f.addWindowListener(new WindowAdapter() { public void
windowClosing(WindowEvent e) {System.exit(0);}});
f.show();
}
}
class AppFrame extends Frame
{
String displayStrings[];
int numberDisplayLines;
public AppFrame(String[] d, int n)
{
displayStrings = d;
numberDisplayLines = n;
}
public void paint(Graphics g)
32 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
{
Font font;
font = new Font("Courier", Font.PLAIN, 12);
g.setFont(font);
FontMetrics fontmetrics = g.getFontMetrics(getFont());
int y = fontmetrics.getHeight();
for(int index = 0; index < numberDisplayLines; index++) {
y += fontmetrics.getHeight();
g.drawString(displayStrings[index], 5, y);
}
}
}
Teraz, kiedy potrafimy już dokumenty XML parsować i wyświetlać w odrębnym oknie, równie
dobrze możemy zacząć używać zwykłej grafiki. W następnym przykładzie utworzymy
przeglądarkę graficzną, która nie będzie w ogóle pokazywała danych tekstowych, ale na podstawie
dokumentu XML utworzy rysunek.
Tworzenie przeglądarki graficznej
W poprzednim rozdziale stosując parser DOM utworzyliśmy przeglądarkę wyświetlającą kółka.
Pouczające będzie zrobienie tego samego przy wykorzystaniu parsera SAX, gdyż w ten sposób
zobaczysz, jak pobrać tylko wartości potrzebnych atrybutów. Tym razem utworzymy przeglądarkę
circlesSAX.java, która będzie potrafiła odczytywać dokumenty XML takie, jak pokazany
poniżej kółka.xml, zawierające opis środków i promieni okręgów w atrybutach elementów OKRG:
X CDATA #IMPLIED
Y CDATA #IMPLIED
PROMIEC CDATA #IMPLIED>
X CDATA #IMPLIED
Y CDATA #IMPLIED
SZEROKOŚĆ CDATA #IMPLIED
WYSOKOŚĆ CDATA #IMPLIED>
]>
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 33
34 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
Tym razem cała sztuczka będzie polegała na pobraniu wartości atrybutów X, Y oraz PROMIEC.
Wartości te zapisywać będziemy w tablicach odpowiednio x, y i radius. Pobieranie wartości
atrybutów elementu w parserze SAX jest prostsze niż w parserze DOM. Metoda startElement
otrzymuje jako parametr obiekt Attributes, wystarczy tylko użyć jego metody getValue
podając nazwę potrzebnego parametru:
import java.awt.*;
import java.awt.event.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class circlesSAX extends DefaultHandler
{
static int numberFigures = 0;
static int x[] = new int[100];
static int y[] = new int[100];
static int radius[] = new int[100];
.
.
.
public void startElement(String uri, String localName,
String rawName, Attributes attrs)
{
if (rawName.equals("OKRG")) {
x[numberFigures] = Integer.parseInt(attrs.getValue("X"));
y[numberFigures] = Integer.parseInt(attrs.getValue("Y"));
radius[numberFigures] =
Integer.parseInt(attrs.getValue("PROMIEC"));
numberFigures++;
}
}
.
.
.
public static void main(String[] args)
{
displayDocument(args[0]);
AppFrame f = new AppFrame(numberFigures, x, y, radius);
f.setSize(400, 400);
f.addWindowListener(new WindowAdapter() {public void
windowClosing(WindowEvent e) {System.exit(0);}});
f.show();
}
}
Mamy zatem już dane o okręgach, teraz należy wyświetlić w klasie AppFrame tak samo, jak
robiliśmy to w poprzednim rozdziale:
class AppFrame extends Frame
{
int numberFigures;
int[] xValues;
int[] yValues;
34 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
int[] radiusValues;
public AppFrame(int number, int[] x, int[] y, int[] radius)
{
numberFigures = number;
xValues = x;
yValues = y;
radiusValues = radius;
}
public void paint(Graphics g)
{
for(int loopIndex = 0; loopIndex < numberFigures; loopIndex++){
g.drawOval(xValues[loopIndex], yValues[loopIndex],
radiusValues[loopIndex], radiusValues[loopIndex]);
}
}
}
To już wszystko; wyniki pokazano na rysunku 9.4 wyświetlony został plik kółka.xml. Cały kod
programu pokazano na wydruku 9.4.
Rysunek 8.4.
Graficzna
przeglądarka XML
zrealizowana
przy użyciu
parsera SAX
Wydruk 9.4.
circlesSAX.java
import java.awt.*;
import java.awt.event.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class circlesSAX extends DefaultHandler
{
static int numberFigures = 0;
static int x[] = new int[100];
static int y[] = new int[100];
static int radius[] = new int[100];
public static void displayDocument(String uri)
{
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 35
36 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
try {
IndentingParserSAX SAXHandler = new IndentingParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler((ContentHandler) SAXHandler);
parser.setErrorHandler((ErrorHandler) SAXHandler);
parser.parse(uri);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public void startElement(String uri, String localName,
String rawName, Attributes attrs)
{
if (rawName.equals("OKRG")) {
x[numberFigures] = Integer.parseInt(attrs.getValue("X"));
y[numberFigures] = Integer.parseInt(attrs.getValue("Y"));
radius[numberFigures] =
Integer.parseInt(attrs.getValue("PROMIEC"));
numberFigures++;
}
}
public void warning(SAXParseException exception)
{
System.err.println("OSTRZEŻENIE! " +
exception.getMessage());
}
public void error(SAXParseException exception)
{
System.err.println("BAD! " +
exception.getMessage());
}
public void fatalError(SAXParseException exception)
{
System.err.println("BAD KRYTYCZNY! " +
exception.getMessage());
}
public static void main(String[] args)
{
displayDocument(args[0]);
AppFrame f = new AppFrame(numberFigures, x, y, radius);
f.setSize(400, 400);
f.addWindowListener(new WindowAdapter() {public void
windowClosing(WindowEvent e) {System.exit(0);}});
f.show();
}
}
class AppFrame extends Frame
{
int numberFigures;
int[] xValues;
int[] yValues;
36 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
int[] radiusValues;
public AppFrame(int number, int[] x, int[] y, int[] radius)
{
numberFigures = number;
xValues = x;
yValues = y;
radiusValues = radius;
}
public void paint(Graphics g)
{
for(int loopIndex = 0; loopIndex < numberFigures; loopIndex++){
g.drawOval(xValues[loopIndex], yValues[loopIndex],
radiusValues[loopIndex], radiusValues[loopIndex]);
}
}
}
Nawigacja po dokumentach XML
Interfejs Node dostępny w parserze DOM zawiera wszystkie standardowe metody DOM W3C
pozwalające nawigować po dokumencie: getPreviousSibling, getFirstChild,
getLastChild i getParent. W przypadku parsera SAX rzecz wygląda inaczej, gdyż parser
nie tworzy drzewa węzłów, zatem metody wyliczone powyżej nie mają zastosowania.
Jeśli chcesz znalezć konkretny element, musisz zrobić to sam. W poprzednim rozdziale
znajdowaliśmy nazwisko trzeciej osoby z pliku spotkania.xml:
Ted Bond
XML w praktycznych zastosowaniach
2079
XML
6/1/2002
Edward
Samson
Ernestyna
Johnson
Betty
Richardson
Nietrudno jest zrobić to samo stosując parser SAX, wymaga jednak to nieco więcej kodowania.
Zaczniemy od odnalezienia trzeciego elementu OSOBA i ustawienia zmiennej
thirdPersonFlag na true, kiedy taki element zostanie znaleziony:
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 37
38 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if(rawName.equals("OSOBA")) {
personCount++;
}
if(personCount == 3) {
thirdPersonFlag = true;
}
.
.
.
}
Kiedy parser SAX parsuje element IMI trzeciej osoby, ustawiamy na true zmienną
firstNameFlag; podczas parsowania elementu NAZWISKO trzeciej osoby ustawiamy na true
zmienną lastNameFlag:
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if(rawName.equals("OSOBA")) {
personCount++;
}
if(personCount == 3) {
thirdPersonFlag = true;
}
if(rawName.equals("IMI") && thirdPersonFlag) {
firstNameFlag = true;
}
if(rawName.equals("NAZWISKO") && thirdPersonFlag) {
firstNameFlag = false;
lastNameFlag = true;
}
}
Sprawdzając wartości zmiennych firstNameFlag i lastNameFlag możemy zapisać imię
i nazwisko trzeciej osoby w metodzie zwrotnej character:
public void characters(char characters[], int start, int length)
{
String characterData = (new String(characters, start,
length)).trim();
if(characterData.indexOf("\n") < 0 && characterData.length() >
0) {
if(firstNameFlag) {
firstName = characterData;
}
if(lastNameFlag) {
lastName = characterData;
}
}
}
Kiedy parser SAX zakończy pracę z trzecim elementem OSOBA, wyświetlimy nazwisko trzeciej
osoby:
public void endElement(String uri, String localName, String
rawName)
38 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
{
if(thirdPersonFlag && lastNameFlag){
System.out.println("Trzecia osoba: " + firstName + " " +
lastName);
thirdPersonFlag = false;
firstNameFlag = false;
lastNameFlag = false;
}
}
W ten właśnie sposób wybiera się w parserze SAX konkretne elementy z dokumentu trzeba
po prostu poczekać, aż parser do odpowiedniego elementu dotrze. Oto wyniki działania naszego
programu:
%java navSAX spotkania.xml
Trzecia osoba: Betty Richardson
Cały kod programu navSAX.java pokazano na wydruku 9.5.
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class navSAX extends DefaultHandler
{
int personCount;
boolean thirdPersonFlag = false;
boolean firstNameFlag = false, lastNameFlag = false;
String firstName, lastName;
public static void displayDocument(String uri)
{
try {
IndentingParserSAX SAXHandler = new IndentingParserSAX();
SAXParser parser = new SAXParser();
parser.setContentHandler((ContentHandler) SAXHandler);
parser.setErrorHandler((ErrorHandler) SAXHandler);
parser.parse(uri);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public void startElement(String uri, String localName,
String rawName, Attributes attributes)
{
if(rawName.equals("OSOBA")) {
personCount++;
}
if(personCount == 3) {
thirdPersonFlag = true;
}
if(rawName.equals("IMI") && thirdPersonFlag) {
firstNameFlag = true;
}
if(rawName.equals("NAZWISKO") && thirdPersonFlag) {
firstNameFlag = false;
lastNameFlag = true;
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 39
40 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
}
}
public void characters(char characters[], int start, int length)
{
String characterData = (new String(characters, start,
length)).trim();
if(characterData.indexOf("\n") < 0 && characterData.length() >
0) {
if(firstNameFlag) {
firstName = characterData;
}
if(lastNameFlag) {
lastName = characterData;
}
}
}
public void endElement(String uri, String localName, String
rawName)
{
if(thirdPersonFlag && lastNameFlag){
System.out.println("Trzecia osoba: " + firstName + " " +
lastName);
thirdPersonFlag = false;
firstNameFlag = false;
lastNameFlag = false;
}
}
public void warning(SAXParseException exception)
{
System.err.println("OSTRZEŻENIE! " +
exception.getMessage());
}
public void error(SAXParseException exception)
{
System.err.println("BAD! " +
exception.getMessage());
}
public void fatalError(SAXParseException exception)
{
System.err.println("BAD KRYTYCZNY! " +
exception.getMessage());
}
public static void main(String[] args)
{
displayDocument(args[0]);
}
}
Modyfikowanie dokumentów XML
W poprzednim rozdziale pokazano, że parser DOM pakietu XML for Java zawiera metody
umożliwiające modyfikowanie dokumentu rezydującego w pamięci, takie jak insertBefore
40 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
czy addChild. Parser SAX nie udostępnia od razu całego drzewa dokumentu, wobec czego
nie ma w nim podobnych metod.
Postać dokumentu XML można jednak modyfikować także w parserze SAX należy w tym celu
samemu wywoływać różne metody zwrotne. Poprzednio zmodyfikowaliśmy dokument
zamówienia.xml tworząc zamówienia2.xml do każdego elementu OSOBA dodając element
DRUGIE_IMI o treści XML. Bez problemu możemy zrobić to samo stosując metody parsera
SAX. Wystarczy poczekać na element IMI i wtedy utworzyć nowy element wywołując metody
zwrotne startElement, characters i endElement:
public void endElement(String uri, String localName, String
rawName)
{
indent = indent.substring(0, indent.length() - 4);
displayStrings[numberDisplayLines] = indent;
displayStrings[numberDisplayLines] += "";
displayStrings[numberDisplayLines] += rawName;
displayStrings[numberDisplayLines] += '>';
numberDisplayLines++;
if (rawName.equals("IMI")) {
startElement("", "DRUGIE_IMI", "DRUGIE_IMI", null);
characters("XML".toCharArray(), 0, "XML".length());
endElement("", "DRUGIE_IMI", "DRUGIE_IMI");
}
}
W metodzie main zapiszemy zmodyfikowany dokument pod nową nazwą:
public static void main(String args[])
{
displayDocument(args[0]);
try {
FileWriter filewriter = new FileWriter("zamówienia2.xml");
for(int loopIndex = 0; loopIndex < numberDisplayLines;
loopIndex++){
filewriter.write(displayStrings[loopIndex].toCharArray());
filewriter.write('\n');
}
filewriter.close();
}
catch (Exception e) {
e.printStackTrace(System.err);
}
}
W wyniku otrzymamy nowy plik zamówienia2.xml z dodanymi elementami DRUGIE_IMI:
Smith
Sam
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 41
42 Część I f& Podstawy obsługi systemu WhizBang (Nagłówek strony)
XML
15 pazdziernika 2001
Pomidory
8
5zł
Pomarańcze
24
9.98zł
Jones
Polly
XML
20 pazdziernika 2001
Chleb
12
28.80zł
Jabłka
42 C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc
Rozdział 1 f& Pierwsze kroki (Nagłówek strony)
6
6.00zł
Weber
Bill
XML
25 pazdziernika 2001
Asparagus
12
11.90zł
Sałata
6
31.50zł
W ten sposób skończyliśmy pracę z pakietem XML for Java i w ogóle chwilowo skończyliśmy
pracę z Javą. Teraz zajmiemy się łączami i wskaznikami XML: XLinks i XPointers.
C:\do przegrania\Książki w txt lub doc\xml - vademecum profesjonalisty\r09-01.doc 43
Wyszukiwarka
Podobne podstrony:
r09 01r09 01 (2)t informatyk12[01] 02 101r11 012570 01introligators4[02] z2 01 nBiuletyn 01 12 2014beetelvoiceXL?? 01012007 01 Web Building the Aptana Free Developer Environment for Ajaxwięcej podobnych podstron