Wykorzystaj wbudowane funkcje XPath
Podczas opracowywania jednego z kursów online firmy Altova, musiałem posortować listę książek według autorów. Zauważyłem, że pole z imieniem autora zawierało pełne imię i nazwisko, więc książki były sortowane według pierwszej litery tego pełnego imienia i nazwiska, czyli według pierwszego imienia autora. Nie było to możliwe do naprawienia w ramach tego kursu, ale można łatwo wyodrębnić nazwisko z tego ciągu znaków i użyć go jako klucza sortowania, korzystając z funkcji XPath. Jeśli następnie użyję tytułów książek jako dodatkowego klucza sortowania, pojawia się problem z tytułami, które zaczynają się od słów "A", "An" lub "The". Chcę użyć tytułu jako dodatkowego klucza sortowania, ale pominąć początkowe określniki rodzajowe ("a", "an", "the").
![]()
Przyjrzyjmy się, jak stworzyliśmy ten kod XSLT. Artykuł został napisany przy użyciu platformy XMLSpy, ale te same wyrażenia XPath można wykorzystać w programach MapForce lub StyleVision, aby osiągnąć podobne rezultaty. Możemy zacząć od prostej listy książek w formacie XML. Mamy 4 książki, każda z węzłami zawierającymi autora i tytuł.
![]()
Transformacja XSLT, która generuje listę książek, mogłaby wyglądać następująco:
![]()
To spowoduje wygenerowanie następującego wyniku:
![]()
Książki są generowane w kolejności, w jakiej występują w oryginalnym pliku danych. Jeśli dodamy element xsl:sort do pętli xsl:for-each, możemy zorganizować wynik w inny sposób.
![]()
To spowoduje wygenerowanie listy posortowanej, ale nie posortowanej prawidłowo.
![]()
Sortowanie autorów jako ciąg znaków powoduje, że "Jules Verne" pojawia się przed "Mark Twain". Podobnie, "A Connecticut Yankee in King Arthur’s Court" pojawia się przed "Adventures of Huckleberry Finn". Chcemy zignorować nieokreślony rodzajnik "A", aby "Adventures of Huckleberry Finn" pojawiało się przed "A Connecticut Yankee in King Arthur’s Court". Możemy użyć wyrażeń XPath, aby wyodrębnić klucze sortowania, których potrzebujemy.
![]()
Zanim przejdziemy do analizy wyników, przyjrzyjmy się kodowi. Zastępujemy słowo „author” wyrażeniem „reverse(tokenize(author, ‘ ‘))[1]”. Funkcja tokenize dzieli łańcuch znaków reprezentującego autora na tokeny, używając pojedynczej spacji jako separatora. Zatem „Jules Verne” jest dzielone na „Jules” i „Verne”. Funkcja reverse odwraca kolejność tokenów, dając „Verne” i „Jules”. Element w nawiasach kwadratowych wybiera pierwszy element z listy, czyli „Verne”. To właśnie ta wartość jest używana w funkcji xsl:sort do sortowania książek. Nie jest to idealne rozwiązanie, ale działa w naszym przypadku. Tytuł może wydawać się skomplikowany, ale logika jest prosta. Wyrażenie „tokenize(title,’ ‘)[1]” wyodrębnia pierwsze słowo tytułu. Zatem pierwszy warunek if sprawdza, czy pierwsze słowo tytułu to „A”. Jeśli tak, zwracamy fragment tytułu, który zaczyna się od trzeciej litery, eliminując w ten sposób „A” i spację. Jeśli pierwsze słowo tytułu to nie „A”, musimy ponownie sprawdzić, czy pierwsze słowo to „The”. Jeśli tak, używamy fragmentu tytułu zaczynającego się od piątego znaku, eliminując w ten sposób „The” i spację. Jeśli obie te warunki są fałszywe, po prostu przekazujemy tytuł jako klucz sortowania. Możemy dodać kolejny test do naszego kodu, aby sprawdzić, czy pierwsze słowo to „An”, ale nie jest to konieczne dla tego zestawu danych. Wykonując ten ostatni transformator XSLT, otrzymujemy następujący wynik.
![]()
„Mark Twain” znajduje się teraz przed „Jules Verne”. „Przygody Hucka Finna” pojawia się przed „Słynnym żabią skocznią z hrabstwa Calaveras” oraz „Jankes z Connecticut na dworze króla Artura”. Problem w naszym podejściu do łańcucha znaków autora polega na tym, że chcemy, aby „Jules Verne” był traktowany jako „Verne, Jules” podczas sortowania, tak aby, gdybyśmy mieli książkę autorstwa „Jimmy Verne”, system traktował ich jako różnych autorów. Nasz kod tego nie robi. Użycie wyrażenia „concat(reverse(tokenize(author, ‘ ‘))[1], reverse(tokenize(author, ‘ ‘))[2])” poprawnie posortowałoby „Jules Verne” i „Jimmy Verne”, ale to rozwiązanie działałoby tylko w przypadku nazw składających się z dwóch słów. Jeśli autor miałby dodatek (np. „Martin Luther King, Jr.”) lub składałby się z wielu słów (np. „George Herbert Walker Bush”), kod zawiódłby. Istnieje wiele wyjątków od ogólnych zasad sortowania nazw, a kod, który uwzględniałby wszystkie warianty, wykraczałby daleko poza zakres tego artykułu. Chcieliśmy pokazać możliwość manipulowania danymi XML w czasie rzeczywistym za pomocą wyrażeń XPath. Nie zawsze mamy pełną kontrolę nad formatem naszych źródeł danych, ale dzięki mocy wyrażeń XPath możemy przekształcić dane w format, który jest nam potrzebny. Kopia plików użytych w tych przykładach jest dostępna tutaj.