Zobrazují se příspěvky se štítkemxml. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemxml. Zobrazit všechny příspěvky

pondělí 12. listopadu 2007

JAXB 2 a JAXBElement

JAXB (Java Architecture for XML Binding) je technologie, pomocí které se Java objekt převede do XML a naopak. Pokud máme už hotové XML Schema zamýšlených XML dokumentů, je vhodné si pomocí nástroje XJC vygenerovat odpovídající javovské třídy.
XJC ale někdy vygeneruje jako atributy třídy typu JAXBElement, do kterých je zabalen výsledný typ:
protected JAXBElement<String> pokus;
místo prostého
protected String pokus;
Odpověď je nutné hledat v XML schématu, které obsahuje definici
<xs:element name="pokus" minoccurs="0" nillable="true" type="xs:string" />
Pak totiž v příslušném XML mohou nastat tři situace:
  1. element pokus se v dokumentu (normálně) vyskytuje
  2. element pokus se v dokumentu nevyskytuje (minOccurs="0")
  3. element pokus se v dokumentu vyskytuje, ale má nastaveno xsi:nil="true" (nillable="true")
K tomu, aby JAXB rozlišil mezi druhými dvěma případy, které oba reprezentují prázdnou hodnotu, zabalí si atribut do pomocného objektu JAXBElement.
Řešení je snadné: reprezentovat prázdnou hodnotu jen jedním způsobem, ale dá se použít jen v případě, že schéma můžete upravovat...

pondělí 5. listopadu 2007

XSLT a výstup do více souborů

Před nedávnem psal Štěpán o tom, jak pomocí XSLT zpracovat vstup z více souborů a jí se dnes přidám s řešením opačného problému.
XSLT (Extensible Stylesheet Language Transformations) je způsob, jak pomocí XML šablony z jednoho XML dokumentu vyrobit jiný (nejčastěji taky XML) dokument. Ale co když potřebujeme ze zdojového souboru vyrobit dva a víc výsledných souborů?

XSLT 2.0
Pokud náš XSL procesor podporuje normu XSLT 2.0, máme vyhráno. Kouzelný příkaz se jmenuje xsl:result-document a atributem href se určí jméno souboru do kterého bude směřovat výstup. Více v článku Create multiple files in XSLT 2.0 na DeveloperWorks.

XSLT 1.0/1.1
Ve starší normě výstup do více souborů standardizován není, ale snad každý procesor nabízí své rozšíření, pomocí kterého toho jde dosáhnout. Nevýhodou ale je, že takový způsob není samozřejmě přenositelný mezi různými XSL procesory.

Postup pro XSL procesor Xalan-J je následující:
Do XSL šablony elementu xsl:stylesheet přidáme atributy xmlns:redirect="http://xml.apache.org/xalan/redirect" a extension-element-prefixes="redirect", čímž si zpřístupníme xalanovské rozšíření Redirect.
Potom můžeme použít element redirect:write select="jmenosouboru", který zařídí výstup do požadovaného souboru. (Viz kompletní popis rozšíření Redirect.)

středa 9. května 2007

XPath výrazy a XML jmenné prostory

Jmenné prostory (XML namespaces) slouží k oddělení XML elementů z různých schémat, které pak mohou být použity v jednom dokumentu. Jmenný prostor má svůj prefix, kterým jsou v dokumentu označeny "jeho" elementy (prefix předchází jménu elementu a je od jména oddělený dvojtečkou). Jeden jmenný prostor prefix mít nemusí (ani elementy potom prefixy nemají) a ten je potom výchozí.XML se dvěma jmennými prostory.

XPath výrazy, které v XML dokumentu bez jmenných prostorů fungují jako z praku, přidáním byť i jediného výchozího jmenného prostoru fungovat přestanou. Bohužel v té chvíli se ocitáme na poli, kde XPath tutoriály neorají a výrazy /root/child nebo //e:parent na uvedeném příkladě nic nevrátí.
Důležité pro pochopení je, že
  1. jmenný prostor není identifikován svým prefixem, ale svým jménem (tj. tím, co je za dvojtečkou)
  2. XPath elementy ve výchozím jmenném prostoru prostě zpracovat neumí
Cesta ven je poměrně jednoduchá: při zpracování XML obsahující jmenné prostory musíme tyto prostory vyjmenovat a všem jim přiřadit prefixy (které se můžou lišit od těch, které jsou v dokumentu použity).
V případě použití XPath procesoru Jaxen (který je součástí DOM4J, XOM a dalších) se to zařídí tak, že se vytvoří mapa prefixů a odpovídajících jmen jmenných prostorů a tuto mapu pak nastavíme jako namespace pro DocumentFactory, kterou vytváříme nebo načítáme XML soubory ke zpracování:
Map<String, String> ns = new HashMap<String, String>();
ns.put("x", "http://geek.cz");
ns.put("e", "http://geek.cz/enhanced");
DocumentFactory factory = new DocumentFactory();
factory.setXPathNamespaceURIs(ns);
Document doc = ...
doc.valueOf("//x:child"); // vrátí "ahoj"


V případě, že XPath potřebujeme použít v XSLT, tak opět vždy v šabloně musíme definovat prefix i výchozímu jmennému prostoru.

Kromě definování jmenných prostorů nám dává XPath možnost použít výrazy jako //*[local-name(.)='child'] nebo //*[name()='child'] (ten ale není doporučován), které vrací jméno elementu bez prefixu. Ty se ale dají použít jen v případě, že jmenné prostory nemají společná jména elementů a taky jejich nevýhodou je, že výrazy jsou pak méně přehledné.