XML – Zadanie zaliczeniowe nr 3 – komentarz

Najczęściej popełniane błędy

NullPointerException przy porównaniach napisów

Zamiast name.equals("lala") znacznie lepiej pisać "lala".equals(name). Jeśli name == null w pierwszym przypadku będzie wyjątek, w drugim otrzymamy false. Naprawdę warto nabrać nawyku i zawsze pisać w tej kolejności.

Jeśli mamy dwie zmienne, to zawsze equals wykonujmy na tej, o której wiemy, że nie jest nullem. Na przykład zamiast ns == null || node.getNamespaceURI().equals(ns) lepiej napisać ns == null || ns.equals(node.getNamespaceURI()).

QName zamiast LocalName

Wyraźnie napisałem, że przetwarzanie ma być namespace aware. W dodatku schemat deklarował elementy w przestrzeni nazw (co samo powinno wskazywać, że mamy uwzględniać przestrzenie nazw).

Około połowa z Was nie sprawdzała przestrzeni nazw. Przy poprawnej obsłudze insertContent to nie było konieczne (bo schemat zabraniał pojawiania się innych elementów), ale w przypadku braku lub błędnej implementacji, powodowało to interpretację zagnieżdżonych elementów jako operacji (nawet jeśli były z innej przestrzeni nazw).

Kilka osób (ok. 1/5) porównywała z nazwą operacji kwalifikowaną nazwę elementu, zamiast nazwy lokalnej. Powodowało to niedziałanie programu na pliku wejściowym z operacjami postaci op:readFromFile. Uznałem to za poważny błąd.

Operacja insertContent

Należało poprawnie obsłużyć sytuację, gdy elementy z przestrzeni nazw operacji, w tym sam insertContent, znajdowały się wewnątrz operacji. Należało je sparsować do tworzonego poddrzewa, a nie wykonywać. Aby nie kończyć zbyt szybko "trybu parsowania", można było liczyć głębokość (wszystkich lub tylko specjalnych elementów) lub tworzone elementy ustawiać na stosie i sprawdzać czy stos jest pusty.

Niektórzy z Was niepoprawnie dodawali do drzewa DOM atrybuty (to nie są dzieci!) lub węzły tekstowe.

moveLeft, moveRigth, moveUp i moveToChildren

Zmienna powinna wskazywać zawsze na jakiś element (nie węzeł tekstowy, nie węzeł dokumentu). W wielu rozwiązaniach operacje move... nie zachowywały tego niezmiennika.

Co więcej, czasami operacje jednocześnie zakładały, że zawsze jesteśmy w elemencie, co powodowało błędy na dokumentach z węzłami tekstowymi.

W moveToChildren niektórzy uwzględniali nie tylko elementy. Inni używali metody getElementsByTagNameNS(), która zwraca listę potomków a nie dzieci.

Element główny a węzeł dokumentu

Niektórzy pozwalali operacji moveUp na wejście do węzła dokumentu (#document) lub ustawiali wskaźnik nowych zmiennych na węzeł dokumentu. Czasami prowadziło to do błędów w innych operacjach (np. remove), poza tym w treści było napisane, że zmienna ma w tych sytuacjach powinna wskazywać na element główny (z dokumentu mżna go pobrać metodą getDocumentElement())..

Walidacja SAX

Należało walidować dokument z operacjami. W przypadku wykrycia błędu przerwać program. Niektórzy nie walidowali w ogóle, inni pisali na ekran komunikaty o błędzie, ale nie przerywali parsowania.


Valid XHTML 1.1Valid CSS