Programování

XSLT kvete s Javou

Už vás někdy zasáhl obtížný problém s transformací XML, který jste nemohli vyřešit pouze pomocí XSLT (Extensible Stylesheet Language Transformation)? Vezměte si například jednoduchou šablonu stylů filtru, která vybere pouze ty uzly datované dříve než před pěti dny. Slyšeli jste, že XSLT dokáže filtrovat dokumenty XML, takže zjistíte, že tento problém vyřešíte za chvilku. Prvním úkolem je získání dnešního data ze šablony stylů za předpokladu, že informace nejsou obsaženy v původním dokumentu XML. Bohužel nemůžete dokončit tento úkol pouze s XSLT. V takové situaci můžete svůj kód XSLT zjednodušit a problém vyřešit rychleji pomocí rozšíření Java.

Mnoho procesorů XSLT umožňuje určitý typ rozšiřujícího mechanismu; specifikace to vyžaduje. Ve světě Java a XML je nejpoužívanějším procesorem XSLT open source procesor Apache Xalan. Xalan, napsaný v Javě, umožňuje rozšíření v Javě. Mnoho vývojářů považuje rozšiřitelnost Xalan za výkonnou, protože jim umožňuje využívat své znalosti jazyka Java z kontextu šablony stylů. Zvažte způsob, jakým JSP (JavaServer Pages), skripty a vlastní značky přidávají sílu do HTML. Rozšíření Xalan přidávají sílu do stylů stejným způsobem: umožněním vývojářům prostředí Java přístup k jejich oblíbenému nástroji Java.

V tomto článku ukážu, jak můžete používat Javu v rámci šablony stylů XSLT. Nejprve použijeme rozšiřitelnost Xalan k vytvoření instance a použití existujících tříd v rámci JDK. Později vám ukážu, jak napsat funkci rozšíření XSLT, která trvá a Tětiva argument a vrátí fragment DOM (Document Object Model) do procesoru šablony stylů.

XSLT je důležité pro vývojáře J2EE (Java 2 Platform, Enterprise Edition), protože styling dokumentů XML se stal operací na straně serveru. Součástí specifikace J2EE (J2EE 2.6.11) se stal také JAXP (Java API pro zpracování XML), který zahrnuje podporu pro motory XSLT. V počátcích bylo XSLT určeno ke stylu XML na klientovi; většina aplikací však styl XML před odesláním klientovi. Pro vývojáře J2EE to znamená, že procesor XSLT bude s největší pravděpodobností spuštěn v rámci aplikačního serveru.

Než budete pokračovat v tomto článku, upozorňujeme, že používání rozšíření Java v šablonách stylů XSLT sníží jejich přenositelnost. Zatímco rozšíření jsou součástí specifikace XSLT, způsob jejich implementace není. Pokud vaše šablony stylů budou fungovat na jiných procesorech než Xalan, jako je například modul šablon stylů aplikace Internet Explorer, měli byste se vyhnout používání rozšíření za každou cenu.

Slabiny XSLT

Protože XSLT má některá slabá místa, ukážou se XSLT rozšíření docela užitečné. Neříkám, že XSLT je špatný; prostě nenabízí nejlepší nástroj pro zpracování všeho v dokumentu XML. Zvažte tuto část XML:

 XSLT není tak snadné, jak by si někteří přáli ... 

Předpokládejme, že vás šéf požádá o úpravu šablony stylů tak, aby konvertovala všechny výskyty „není“ na „není“ a lokalizovala běžné štítky. XSLT jistě poskytuje mechanismus, jak něco udělat v tomto duchu, že? Špatně. XSLT neposkytuje žádný snadný způsob, jak nahradit výskyt slova nebo vzoru v řetězci. Totéž platí pro lokalizaci. To neznamená, že to nelze provést se standardní syntaxí XSLT. Existují způsoby, ale nejsou zdaleka tak snadné, jak bychom si přáli. Pokud opravdu chcete psát funkce pro manipulaci s textem pomocí rekurzivních šablon, buďte mými hosty.

Hlavní slabinou XSLT je zpracování textu, což se zdá být rozumné, protože jeho účelem je vykreslení XML. Protože však obsah XML je pouze text, XSLT vyžaduje silnější zpracování textu. Není třeba říkat, že návrháři stylů čas od času vyžadují určitou rozšiřitelnost. S Xalanem poskytuje Java tuto rozšiřitelnost.

Používejte třídy JDK v rámci XSLT

Možná vás potěší, že nemusíte psát žádný kód Java, abyste mohli využít rozšiřitelnosti Xalanu. Když používáte Xalan, můžete vytvářet a vyvolávat metody téměř na jakémkoli objektu Java. Před použitím třídy Java musíte poskytnout XSLT jmenný prostor pro to. Tento příklad deklaruje "Jáva" jako obor názvů pro všechno v balíčku Java nebo pod ním (tj. celý JDK):

Nyní musíme něco udělat. Začněme malým dokumentem XML:

 Java může být módní J. Burke 30. 11. 1997 

Byli jste požádáni, abyste tento XML upravili, aby se nadpis zobrazoval velkými písmeny. Vývojář nový v XSLT by jednoduše otevřel odkaz XSLT a hledal toUpper () funkce; byla by však zklamaná, kdyby zjistila, že takové reference chybí. The přeložit() metoda je vaše nejlepší sázka, ale mám ještě lepší metodu: java.lang.String.toUpperCase (). Chcete-li použít tuto metodu, musíte vytvořit instanci a Tětiva objekt s obsahem nadpisu. Takto můžete vytvořit nový Tětiva instance s obsahem elementu title:

The název atribut určuje popisovač vašeho nového Tětiva instance. Konstruktor vyvoláte tak, že nejprve zadáte obor názvů spolu se zbývající cestou k Tětiva třída. Jak jste si možná všimli, Tětiva chybí a Nový() metoda. Používáš Nový() postavit objekt Java v Xalanu; odpovídá Java Nový klíčové slovo. Argumenty dané Nový() určit verzi konstruktoru, která bude volána. Nyní, když máte obsah titulu v prostředí Java Tětiva objekt, můžete použít toUpperCase () metoda, jako například:

To by na první pohled mohlo vypadat divně. Při použití metod Java na konkrétní instanci je prvním argumentem instance, na kterou chcete metodu vyvolat. Je zřejmé, že Xalan k zajištění této schopnosti používá introspekci.

Níže najdete další trik. Zde je ukázáno, jak můžete pomocí funkce generovat datum a čas kdekoli ve vaší šabloně stylů java.lang.Date:

Tady je něco, co umožní každému, kdo potřebuje lokalizovat obecnou šablonu stylů mezi dvěma nebo více jazyky. Můžeš použít java.util.ResourceBundle lokalizovat doslovný text v šabloně stylů. Protože vaše XML obsahuje autorskou značku, možná budete chtít tisknout "Autor:" vedle jména osoby.

Jednou z možností je vytvořit samostatný seznam stylů pro každé národní prostředí, tj. Jeden pro angličtinu, druhý pro čínštinu atd. Problémy spojené s tímto přístupem by měly být zřejmé. Udržovat konzistentní více verzí stylů je časově náročné. Musíte také upravit aplikaci tak, aby si vybrala správný styl podle národního prostředí uživatele.

Místo duplikování šablony stylů pro každý jazyk můžete využít výhod lokalizačních funkcí Java. Lokalizace pomocí a ResourceBundle dokazuje lepší přístup. V rámci XSLT načtěte ResourceBundle na začátku vašich seznamů stylů, například:

The ResourceBundle třída očekává, že najde soubor s názvem Obecné. Vlastnosti ve vašem CLASSPATH. Jakmile je balíček vytvořen, lze jej znovu použít v celé šabloně stylů. Tento příklad načte autor zdroj:

Všimněte si znovu podivného podpisu metody. Normálně, ResourceBundle.getString () trvá pouze jeden argument; v rámci XSLT však musíte také určit objekt, kterým chcete metodu vyvolat.

Napište vlastní rozšíření

V některých výjimečných situacích možná budete muset napsat vlastní příponu XSLT ve formě buď funkce rozšíření nebo prvku rozšíření. Budu diskutovat o vytvoření funkce rozšíření, což je koncept, který je poměrně snadno pochopitelný. Libovolná funkce rozšíření Xalan může brát řetězce jako vstupní a vracet řetězce do procesoru XSLT. Vaše rozšíření mohou také trvat NodeLists nebo Uzels jako argumenty a vrátit tyto typy do procesoru XSLT. Použitím Uzels nebo NodeLists znamená, že můžete přidat do původního dokumentu XML s funkcí rozšíření, což je to, co uděláme.

Jedním typem textové položky, se kterým se často setkáváme, je datum; poskytuje skvělou příležitost pro nové rozšíření XSLT. Naším úkolem je stylizovat prvek článku tak, aby se datum tisklo v následujícím formátu:

Pátek, 30. listopadu 200

Může standardní XSLT dokončit výše uvedené datum? XSLT může dokončit většinu úkolu. Stanovení skutečného dne je obtížná část. Jedním ze způsobů, jak tento problém rychle vyřešit, je použití java.text.SimpleDate format format within an extension function to return a string formatted as we wish. Ale počkejte: všimněte si, že se den zobrazí tučně. Tím se vracíme k původnímu problému. Důvod, proč dokonce uvažujeme o rozšiřující funkci, je ten, že původní dokument XML nedokázal strukturovat datum jako skupinu uzlů. Pokud naše funkce rozšíření vrátí řetězec, uděláme to ještě pořád je obtížné stylizovat pole dne jinak než zbytek řetězce data. Zde je užitečnější formát, alespoň z pohledu návrháře XSLT:

  11 30 2001  

Nyní vytvoříme funkci rozšíření XSLT, vezmeme řetězec jako argument a vrátíme uzel XML v tomto formátu:

  30. listopadu, pátek 2001 

Třída hostující naši funkci rozšíření nic neimplementuje ani nerozšiřuje; zavoláme třídu DateFormatter:

public class DateFormatter {public static Node format (String date) {} 

Páni, příliš snadné, hm? Na typ nebo rozhraní funkce rozšíření Xalan nejsou kladeny absolutně žádné požadavky. Obecně platí, že většina funkcí rozšíření bude mít a Tětiva jako argument a vrátit další Tětiva. Dalšími běžnými vzory jsou odesílání nebo přijímání org.w3c.dom.NodeLists nebo jednotlivec Uzels z funkce rozšíření, jak to uděláme. Podrobnosti o tom, jak se typy Java převádějí na typy XSLT, najdete v dokumentaci Xalan.

Ve fragmentu kódu výše formát() logika metody se dělí na dvě části. Nejprve musíme analyzovat řetězec data z původního dokumentu XML. Pak použijeme některé techniky programování DOM k vytvoření Uzel a vraťte jej do procesoru XSLT. Tělo našeho formát() implementace metody zní:

 Dokument doc = DocumentBuilderFactory.newInstance (). newDocumentBuilder (). newDocument (); Prvek dateNode = doc.createElement ("formatted-date"); SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance (DateFormat.SHORT, národní prostředí); df.setLenient (true); Datum d = df.parse (datum); df.applyPattern ("MMMM"); addChild (dateNode, "month", df.format (d)); df.applyPattern ("EEEE"); addChild (dateNode, "den v týdnu", df.format (d)); df.applyPattern ("rrrr"); dateNode.setAttribute ("year", df.format (d)); datum návratuNode; 

dateNode bude obsahovat naše formátované hodnoty data, které vrátíme do šablony stylů. Všimněte si, že jsme to využili java.text.SimpleDateFormat () analyzovat datum. To nám umožňuje plně využívat datovou podporu Java, včetně jejích lokalizačních funkcí. SimpleDateFormat zpracovává číselný převod data a vrací názvy měsíců a dnů, které odpovídají národnímu prostředí virtuálního počítače se spuštěnou naší aplikací.

Pamatujte: primárním účelem funkce rozšíření je jednoduše umožnit nám přístup ke stávajícím funkcím Java; napsat co nejméně kódu. Funkce rozšíření, stejně jako jakákoli metoda Java, může používat jiné metody ve stejné třídě. Pro zjednodušení formát() implementace jsem přesunul opakující se kód do malé metody nástroje:

private void addChild (Node parent, String name, String text) {Element child = parent.getOwnerDocument (). createElement (name); child.appendChild (parent.getOwnerDocument (). createTextNode (text)); parent.appendChild (dítě); } 

Použijte DateFormatter v šabloně stylů

Nyní, když jsme implementovali funkci rozšíření, můžeme ji volat zvnějšku stylů. Stejně jako předtím musíme deklarovat jmenný prostor pro naši funkci rozšíření:

Tentokrát jsme plně kvalifikovali cestu ke třídě hostující funkci rozšíření. To je volitelné a záleží na tom, zda budete používat jiné třídy v rámci stejného balíčku nebo jen jeden rozšiřující objekt. Můžete prohlásit celé CLASSPATH jako obor názvů nebo použijte balíček a určete třídu, kde je vyvolána funkce rozšíření. Zadáním úplného CLASSPATH, píšeme méně, když voláme funkci.

Chcete-li tuto funkci využít, jednoduše ji zavolejte zevnitř a vybrat značka, například: