---
title: "Wykorzystaj wbudowane funkcje XPath"
date: "2011-07-12"
categories: 
  - "xpath"
tags: 
  - "altova-online-training"
  - "altova-xmlspy"
  - "data-mapping"
  - "education"
  - "learn-xml"
  - "xml-editor"
  - "xmlspy"
  - "xpath"
  - "xslt"
description: W tym artykule omówiono wykorzystanie funkcji XPath do efektywnego sortowania danych XML, ze szczególnym uwzględnieniem ekstrakcji nazwisk oraz obsługi przedimków w tytułach.
---
Status: #blog

Tags:  #altova-online-training #altova-xmlspy #data-mapping #education #learn-xml #xml-editor #xmlspy #xpath #xslt

Categories: [xpath+xquery](/blog/pl/category/xpathxquery.md)
# Wykorzystaj wbudowane funkcje XPath

Podczas opracowywania jednego z kursów online firmy [Altova](https://www.altova.com/pl/aot/online-training.aspx), 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").

![Wyświetl listę książek, posortowaną przy użyciu wyrażeń XPath](https://lh4.ggpht.com/-OBe9_xfjlpQ/TgD1tUSi6sI/AAAAAAAAAGw/nLwMwUDQTJ4/correct-sort-xsl2_thumb%25255B2%25255D.png?imgmax=800) 

Przyjrzyjmy się, jak stworzyliśmy ten kod XSLT. Artykuł został napisany przy użyciu platformy [XMLSpy](https://www.altova.com/pl/xmlspy.html), ale te same wyrażenia XPath można wykorzystać w programach [MapForce](https://www.altova.com/pl/mapforce.html) lub [StyleVision](https://www.altova.com/pl/stylevision.html), 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ł. 

[![Lista trzech książek](https://lh5.ggpht.com/-oP0T7tap1j8/TgD1qZFjeJI/AAAAAAAAAGI/Q9N1sefXpr8/book-list-xml2_thumb%25255B6%25255D.png?imgmax=800 "book_list.xml")](http://lh5.ggpht.com/-1XkQTBtjxgI/TgD1p7e9jRI/AAAAAAAAAGE/r5x-fYqrXB4/s1600-h/book-list-xml2%25255B8%25255D.png) 

Transformacja XSLT, która generuje listę książek, mogłaby wyglądać następująco:

[![Wyświetl listę książek bez sortowania](https://lh6.ggpht.com/-Xl2drxDYvWk/TgD1qyCS-tI/AAAAAAAAAGQ/XtlE-ha3aPY/no-sort-xsl2_thumb%25255B3%25255D.png?imgmax=800 "no_sort.xsl")](http://lh6.ggpht.com/-0QjJb5fadso/TgD1qitzcrI/AAAAAAAAAGM/ENp-px5_e1g/s1600-h/no-sort-xsl2%25255B7%25255D.png) 

To spowoduje wygenerowanie następującego wyniku: 

[![Lista książek (bez posortowana)](https://lh4.ggpht.com/-84ZeFnOVnX0/TgD1ruHFFII/AAAAAAAAAGY/rtui-dgtCUQ/no-sort-output_thumb%25255B2%25255D.png?imgmax=800 "Output from XSL with No Sort")](http://lh6.ggpht.com/-DcGmqHHaQi4/TgD1rJWB_GI/AAAAAAAAAGU/V9i4088XoKs/s1600-h/no-sort-output%25255B4%25255D.png) 

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. 

[![Wyświetl listę książek, posortowaną w sposób podstawowy](https://lh4.ggpht.com/-JX9qbo9fYjo/TgD1sKu_YVI/AAAAAAAAAGg/rtHXnh_x94o/sort-xsl2_thumb%25255B2%25255D.png?imgmax=800 "sort.xsl")](http://lh4.ggpht.com/-WEIuCC1NRNw/TgD1rzIgzPI/AAAAAAAAAGc/q79Va9UWMgo/s1600-h/sort-xsl2%25255B4%25255D.png) 

To spowoduje wygenerowanie listy posortowanej, ale nie posortowanej prawidłowo. 

[![Wynik działania transformacji XSL z użyciem podstawowego sortowania](https://lh3.ggpht.com/-kN0aSY1DhE8/TgD1spmsmLI/AAAAAAAAAGo/BsxQW6XYwWk/sort-output_thumb%25255B2%25255D.png?imgmax=800 "Output from XSL with Basic Sort")](http://lh3.ggpht.com/-2JAA_7dIt4o/TgD1sYIFl-I/AAAAAAAAAGk/M5g2B1vVC_M/s1600-h/sort-output%25255B4%25255D.png) 

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. 

[![Wyświetl listę książek, posortowaną przy użyciu wyrażeń XPath](https://lh4.ggpht.com/-OBe9_xfjlpQ/TgD1tUSi6sI/AAAAAAAAAGw/nLwMwUDQTJ4/correct-sort-xsl2_thumb%25255B2%25255D.png?imgmax=800 "correct_sort.xsl")](http://lh4.ggpht.com/-1797dSMl6G0/TgD1tIvfZnI/AAAAAAAAAGs/G8i7ztztp9Y/s1600-h/correct-sort-xsl2%25255B4%25255D.png) 

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. 

[![Wynik działania transformacji XSL z poprawnym sortowaniem](https://lh5.ggpht.com/-78G5M2Z81Ow/TgD1uRmfiQI/AAAAAAAAAG4/YStPJ1HRDj0/correct-sort-output_thumb%25255B2%25255D.png?imgmax=800 "Output from XSL with Corrected Sort")](http://lh3.ggpht.com/-h5AD7I5C60o/TgD1tsVI9fI/AAAAAAAAAG0/Nj8_cO10i2s/s1600-h/correct-sort-output%25255B4%25255D.png) 

„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](https://www.altova.com/pl/library/Using_XPath_Functions.zip).
