ISSN 1312-0379

Главна > Статии > Код

Използваме XML. От Джей Дейвид Айсенберг.

По време на втората ми лекция пред един клас, изучаващ XML в местния колеж, Аз обяснявах как XML ви дава възможност да създадете свой собствен маркъп език (бел. прев. от англ. markup language) със собствени тагове и атрибути. Бях привършил съставянето на прост маркъп език, който щях да използвам за списък с аматьорски спортни клубове и показвах един прост документ написан с този език. В този момент един ученик попита:

"Не е ли неефективно да пишем всички тези тагове за всеки клуб? Какво му е доброто? Изглежда добре, но какво мога да направя с този документ? Как мога да го сложа в уеб страница или да го използвам с други програми? Нямаше ли да е по-лесно да използвам HTML или редактор за база данни /текстов редактор/, позволяващ просто да попълвам празните полета?"

Причината да използваме XML вместо някое конкретно приложение се крие в това, че XML не е просто едно красиво лице, живеещо изолирано от останалия компютърен свят. XML е повече от книга с правила за създаване на различни маркъп езици. Той е част от семейство технологии, които, взети заедно, правят вашия базиран на XML документ наистина много полезен. За да демонстрирам какво имам предвид, реших да създам нов базиран на XML маркъп език, започвайки на чисто, и след това да покажа какво може да се направи с документ написан на този език, използвайки готови приложения.

Създаване на нов маркъп език

Езикът, който създадох, съхранява информацията храните (nutrition), която в Съединените щати може да бъде намерена върху опаковките им. Документът започва с тага <nutrition>, последван от <daily-values> елемента, който ни дава максималните стойности на мазнините, натрия и т.н.. в една диета с 2000 калории на ден и единици, в които се измерва количеството.

Дневните стойности са последвани от серии елементи <food>, всеки от които дава информация за конкретна храна и нейните хранителни свойства. Понеже <daily-values> елементът вече дефинира единиците, в която всяко свойство се измерва, няма нужда да ги повтаряме за всяка храна; ние просто въвеждаме цифрите за общото количество на мазнини, натрий и др. в дадената храна. След последната храна, затваряме документа със затварящ таг </nutrition>.

<nutrition>

<!-- Задаване на дневните стойности -->
<daily-values>
    <total-fat units="g"> 65 </total-fat>
    <saturated-fat units="g"> 20 </saturated-fat>
    <cholesterol units="mg"> 300 </cholesterol>
    <sodium units="mg"> 2400 </sodium>
    <carb units="g"> 300 </carb>
    <fiber units="g"> 25 </fiber>
    <protein units="g"> 50 </protein>
</daily-values>

<!-- Сега списък с отделните храни -->
<food>
    <name>Avocado Dip</name>
    <mfr>Sunnydale</mfr>

    <serving units="g"> 29 </serving>
    <calories total="110" fat="100"/>

    <total-fat> 11 </total-fat>
    <saturated-fat> 3 </saturated-fat>
    <cholesterol> 5 </cholesterol>
    <sodium> 210 </sodium>
    <carb> 2 </carb>
    <fiber> 0 </fiber>
    <protein> 1 </protein>

    <vitamins>
        <a> 0 </a>
        <c> 0 </c>
    </vitamins>

    <minerals>
        <ca> 0 </ca>
        <fe> 0 </fe>
    </minerals>
</food>

<!-- и т.н. -->
</nutrition>

Можете да видите целия документ, който е използван за примерите в тази статия. Всички цифри са истински; променени са единствено имената на производителите, за да бъдат защитени невинните и избегнати съдебни процеси.

Малка бележка: витамините и минералите се измерват в проценти, а не в грамове или милиграми. Ето защо няма нужда да задаваме специални мерни единици или максимални стойности за тях в елемента <daily-values>.

Въведох данните ръчно, използвайки програмата nedit под Linux. Бих могъл да използвам и всеки друг редактор, който ми дава възможността да запазвам файловете като обикновен ASCII текст; Notepad под Windows или vi под Linux биха се справили еднакво добре. За да облекча въвеждането на данни, създадох празен "шаблон" за една храна, който виждате в края на файла. Просто го копирах и вмъквах за всяка нова храна, така че да не ми се налага да пиша едни и същи тагове отново и отново.

Незабавни изгоди

Какво спечелихме като създадохме този XML файл с текстов редактор вместо да правим HTML документ, електронна таблица или база данни? Първо, данните са структурирани; те не са просто купчина числа в HTML таблица или текстов файл състоящ се от разделени с табулация стойности. Заради собствените тагове, това е документ, който може да бъде четен и разбран от хората. Освен това той е отворен; няма нужда от някакъв скъп, специфичен софтуер, за да извлечем информацията от двоичния файл. Ето защо, като преходна медия, XML вече ни върши добра работа.

Валидиране на документа

Дори и да сте единственият човек, който някога ще въвежда данни в документа, вие бихте искали да имате възможността да проверявате дали не сте забравили някаква информация или дали не сте добави някой таг допълнително. Освен това, вие бихте искали да се уверите, че всичките ви проценти са със стойности между 0 и 100.

Това придобива дори още по-голямо значение ако много хора ще въвеждат данни. Дори и да дадете на другите инструкции за правилния формат, те могат да ги пренебрегнат или да направят грешки. Накратко, вие бихте искали компютърът да ви помогне да определите дали данните във вашите документи са валидни.

Можете да направите това, създавайки една машинно-четима граматика (бел. прев. от англ. machine-readable - граматика, която могат да четат машините), която определя кои тагове и атрибути са валидни, в какви комбинации и какви стойности могат да приемат вашите тагове и атрибути. След това давате своя документ и граматиката на програма наречена валидатор и тя проверява дали документът покрива вашите указания.

Една машинно-четима форма за съставяне на такава граматика е системата наречена Relax NG. Relax NG е сама по себе си, базиран на XML маркъп език. Нейната цел е да определя какво е валидно в други маркъп езици. Това не е толкова налудничаво или невъзможно колкото звучи. В крайна сметка, книгите, които ви казват как да използвате английската граматика правилно също са написани на английски.

Примерно, една от спецификациите на нашият маркъп език е, че елементът <calories> е празен елемент и има два атрибута - атрибута total и атрибута fat. И двата трябва да съдържат десетични числа. В Relax NG казваме това така:

<element name="calories">
    <empty/>
    <attribute name="total"><data type="decimal"/></attribute>
    <attribute name="fat"><data type="decimal"/></attribute>
</element>

Когато пускаме документите през валидатора, той ни казва, че първият таг е правилен, но вторият не е.

<calories total="100" fat="10"/>
<calories total="217" fat="don't ask!"/>

Можете да видите цялата граматика за нашия маркъп език тук. Можете също така да научите повече за Relax NG. Между другото, Relax NG не е единственото такова средство за определяне на граматиката наоколо. Можете да използвате нещо, наречено DTD (Document Type Definition - дефиниция за вида на документа), което не е толкова мощно или можете да използвате XML Schema, което е също толкова мощно, колкото и Relax NG, но далеч по-сложно за изучаване.

Опитайте!

Ако сте в настроение за приключения, може би ще поискате да пробвате тези файлове сами. Но за това ще са ви необходими някои XML инструмента. Ето как можете да инсталирате тези инструменти под Windows, а тук е инсталацията под Linux.

За да валидирате един файл, стартирайте MS-DOS Promt ако използвате Windows или отидете в прозореца с конзолата ако използвате Linux. Тогава използвайте batch/shell файла описан в инструкциите за инсталация, за да стартирате Multi-Schema валидатора:

msvalidate nutrition.rng nutrition.xml

Сега какво?

Въпреки че можем да въвеждаме четими данни и да проверяваме дали са ОК, ние все още не можем да направим нищо с тях. Ако ги заредим в браузър, ще видим просто един сбутан на едно място текст. Така е защото браузърът не знае как да показва таговете <food> или <vitamins>.

Оформяне на XML

Ако използвате последните браузъри, можете да прикрепите към XML файла стилове. В този пример, направихме това, добавяйки този ред в началото на файла nutrition.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="nutrition.css"?>
<nutrition>

Стиловете, които пишем за файла nutrition.css приличат много на стиловете, които използвате за HTML файловете си. Разликата е, че прикрепяме стилове към нашите нови тагове, а не към стандартните HTML тагове. Например, да кажем, че ако производителят на всяка храна трябва да се появява в 16 point italic шрифт без да започва нов ред, то трябва да напишете:

mfr {
    display: inline;
    font-size: 16pt;
    font-style: italic;
}

След като напишете цялата таблица със стилове в същата директория, в която е и XML файла, можете да отворите XML файла с някой модерен браузър като Mozilla и той ще покаже информацията.

По-добър начин за трансформация

Проблемите при използването на стилове са следните:

  • Те работят само с най-последните браузъри, които поддържат Cascading Style Sheets Level 2.
  • Те не могат да извличат цялата информация (примерно, мерните единици не се показват в изходния документ, защото са "скрити" в стойностите на атрибутите).
  • Не могат да изчисляват проценти.

Освен това, маркъп езикът, който изобретихме тук е ориентиран към данни (data-oriented); той е създаден, за да описва данните, които ще бъдат съхранявани или предавани на други програми. В тези документи, последователността на елементите и вида на данните във всеки елемент е доста скована. Стиловете работят добре с документи, чиито код е повече разказвателен (narrative-oriented). Такива документи обикновено са предназначение за четене от човек и са в по-свободна форма от ориентирани към данните документи. Примери за такъв narrative-oriented маркъо език е XHTML, DocBook (език за писане на книги и статии) и NewsML (за писане на новинарски отчети).

За да се заобиколят тези проблеми, можем да използваме XSLT, Extensible Stylesheet Language Transformations, за да конвертираме нашия файл в други форми. XSLT е, отново, друг основан на XML маркъп език. Неговата цел е да описва как да се взема входна информация от един XML файл (изходен документ) и да се вкара в краен документ. XSLT е достатъчно гъвкав, за да извлича данни и от съдържанието на атрибутите, и от съдържанието на елементите, а и може да направи изчисленията и сортирането на данните базирайки се на информацията изходния документ.

Тези възможности правят XSLT ключова технология в семейството технологии на XML. За въведение в езика, прочете отличната презентация на Норман Уолш по темата, този наръчник или тази въвеждаща статия. Освен това можете да получите повече информация на http://www.xslt.com/.

Трансформиране в HTML

Първият XSLT файл, който можете да видите тук, конвертира нашия документ в съвсем прост HTML файл, който може спокойно да се показва с всеки браузър или PDA. За да се направи тази конверсия, трябва да напишете следната команда:

transform nutrition.xml nutrition_plain.xslt nutrition_plain.html

В резултат от трансформацията получаваме HTML файл наречен nutrition_plain.html, който можете да отворите с всеки браузър, който си пожелаете. Дори толкова простата трансформация направи две неща, които не бихме могли да направим с CSS: тя използва информацията в атрибутите, за да покаже мерните единици за всяка хранителна съставка и изчислява процентите на дневните стойности.

Поукрасена трансформация

OK, може би искате нещо по-свежо. Ето една по-сложна трансформация, която подрежда данните според съотношението между дела на калориите в мазнините и общите калории за едно ядене; нещо като "справочник за здравословност".

Ако сте запазили XSLT кода във файл, наречен nutrition_fancy.xslt, можете да напишете следната команда:

transform nutrition.xml nutrition_fancy.xslt nutrition_fancy.html

Това създава файл наречен nutrition_fancy.html, който изглежда доста по-различно от обикновената версия. Той използва стилове, за да създаде малките диаграми; ще имате нужда от модерен браузър като Internet Explorer 5+ или Mozilla/Netscape 6, за да видите ефекта. Забележете, че XSLT ви позволява да изберете данните, които искате да покажете; информацията за карбохидратите, витамините и минералите е пропусната в тази поукрасена версия. (Те, разбира се, могат да бъдат добавени чрез промяна в XSLT файла.)

Използвахме XSLT, за да вземем изходния XML файл и да го трансформираме в два различни HTML файла; по-проста версия, която е уместна за по-стари бразуъри и PDA и една поукрасена версия, която е уместна за настолните компютри и модерните браузъри.

Други трансформации

Но почакайте. Може би вие не искате HTML; в света няма само браузъри. Може би искате да вземете информацията и да я конвертирате в текстов файл съдържащ разделни с табулация стойности и ще бъде използван за електронни таблици или база от данни.

Ето трансформиращият файл, които прави това, използвайки тази команда:

transform nutrition.xml nutrition_csv.xslt nutrition.csv

А тук е полученият текстов файл.

Конверсия за печат

Да речем, че искате да от нашия XML искате да създадете PDF файл. Това става възможно като се използва една трансформация, чрез която XML се превръща в друг маркъп език: XSL-FO (Extensible Stylesheet Language - Formatting Objects). Това е език за оформяне на страници. Приложение, наречено FOP (Formatting Objects to PDF), взема този код и създава PDF файлове вместо вас.

Тук е файла за трансформацията, която взема данните и ги конвертира в обекти за оформяне. Ако го запазите като nutrition_fo.xslt, можете да използвате FOP, за да направите конверсията в PDF:

fop -xml nutrition.xml -xsl nutrition_fo.xslt -pdf nutrition.pdf

В резултат се получава PDF файл; той е съставен от страници, които са приблизително 8 сантиметра широки и 9 сантиметра високи, което е размер, пасващ удобно за джоб на риза.

Генериране на графики

И накрая, може би искате да създадете една интерактивна, графична версия на данните. Друг базиран на XML език, SVG—Scalable Vector Graphics— ви дава тази възможност. SVG има елементи подобни на следните, чрез които рисува черна диагонална линия и жълт кръг с зелено очертание:

<line x1="0" y1="0" x2="50" y2="50"
    style="stroke: black; fill:none;"/>
<circle cx="100" cy="100" r="30"
    style="stroke:green; fill:yellow;"/>

Използвайки трансформиращ файл, който създава SVG, можем да съставим графика, показваща стълбовидна диаграма за всяка храна, чието име изберете. Това е командата, която трябва да въведете:

transform nutrition.xml nutrition_svg.xslt nutrition.svg

Можете да видите резултата с SVG браузъра, който е част от комплекта Batik, Ако сте инсталирали Batik според инструкциите за Linux или за Windows, въведете командата batik nutrition.svg. Не съм тествал файла с последната версия на Adobe SVG Viewer, но би трябвало да работи добре. Ето скрийншот; кликнете върху него, за да го разгледате в пълен размер.

bar chart showing categories for a given food

Други начини за използване на XML инструментите

В тази статия използвахме Multi-Schema валидатора, Xalan Transformer, FOP конвертора и Batik чрез командния промпт. Това е най-лесния и бърз начин да накараш нещата да заработят, за да придобиете усещане за това какво може да прави XML.

Подходът с използване на batch или shell файл (бел. прев. файл, съдържащ поредица от команди, които се изпълняват автоматично) ще върши работа в среда, в която генерирате периодично цели сайтове с HTML файловете, използвайки информацията от един или повече XML файлове. Просто настройвате batch файла да се пуска в определеното време (cron командата ако се говори с термините на Unix), за да генерира файловете, които са ви нужни.

Но какво ще стане ако имате нужда от динамично генериране на HTML страници или PDF файлове в отговор на заявките на потребителите? Очевидно, няма да искате да стартирате Java процес всеки път, когато постъпва нова заявка, а статичен batch файл няма да свърши работа. И Multi-Schema валидатора, и Xalan имат API (Application Program Interface) и затова могат да станат част от Java servlet работещ на вашия сървър и който ще се справя със заявките на потребителите. Веднъж като servlet-ът се зареди, той остава в паметта и затова няма допълнително натоварване при следващи трансформации.

Ако сте заинтересовани от работата със servlet.и, можете да използвате Jakarta Tomcat servlet container. Той работи като самостоятелен сървър за тестване или като модул за Apache или Microsoft IIS.

Измерване на времето

Има два аспекта на измерването на времето: колко отнема писането на граматиката и трансформиращите файлове и колко бързо действат те.

Създаването на маркъп езика ми отне около 25 минути, а въвеждането на данните още 25, в някои от които притичвах до кухнята, за да взема някои продукти от шкафовете или хладилника. Писането и тестването на Relax NG граматиката изискваше 30 минути.

Стиловете за директно показване на XML в Mozilla ми отнеха 15 минути. Простата HTML трансформация - около 50 минути, включително времето за преглед на някои XSLT примери и малко експериментиране. Поукрасената версия отне около 45 минути. Трябваха ми 20 минути, за да измисля как да направя стълбовидната графика чрез стилове на първо време и още 5 минути за допълнително нагласяне. Файлът за конверсията в текстов файл беше работа за петнайсетина минути.

Трансформацията в PDF отне час. Първият път направих размера на страниците колкото компакт диск. После премислих и реших да ги направя в джобен формат. Това отне 30 до 45 минути за различните настройки и игра с размерите на шрифта. Освен това трябваше да направя някои промени, за да избегна употребата на части от XSL-FO, които FOP още не разпознава.

Накрая, SVG трансформацията отне около час и половина. През половината от това време експериментирах, за да бъде всичко разположено както трябва и да накарам ECMA Script да работи правилно.

Не е нужно да сте експерти в Relax NG, XSLT, XSL Formatting Objects или SVG, за да направите всичко това. Не използвам нито една от тези технологии всекидневно. Просто знам достатъчно за всяка от тях, за да накарам нещата да заработят. В този случай, моята философия беше "първото каквото ти хрумне и работи е правилното". Ето защо XSLT експертите ще бъдат шокирани, когато видят неефективните конструкции като тази за трансформацията в прост HTML.

select="/nutrition/daily-values/*[name(.)=name($node)]/@units"

Излишно е да се споменава, че тук не уча на нищо; ще трябва сами да прекарате известно време в учене. Но не е нужно да прекарвате цял живот в учене. Определено е възможно е да се научи достатъчно за тези технологии, така че да ги използвате ефективно в скоро време.

Производителност

тествах тези файлове на 400MHz AMD K-6 с 128Mb памет и SuSE Linux 7.2. За трансформациите модифицирах SimpleTransform.java - примерната програма, която идва с Xalan. Тази програма записва пълното време необходимо за генериране на крайния файл и времето за трансформацията след като е парснат XSLT файла. Ако пускате трансформациите на сървър, можете да сложите парснатия XSLT файл в кеша, за да се намали натоварването.

Трансформация Време в секунди
Общо Трансформация
прост HTML 3.691 1.018
украсен HTML 4.057 1.409
текстов файл 3.057 0.548
SVG 3.386 0.689

Измерих времето за PDF трансформацията, използвайки time командата под Linux. Генерирането на файла отне реално около 15.115, като 10.920 от тях бяха за работа на процесора.

Разбира се, това не са единствените средства. Има други XSLT процесори и други програми за конвертиране на XSL-FO в PDF. Избрах Xalan, Fop и Batik, защото са безплатни, лесни за употреба и вече бях запознат с тях.

Обобщение

  • Използването на базиран на XML маркъп език дава на вашите документи структура, прави ги четими и отворени.

  • XML е част от семейство технологии.

  • Можете да използвате граматични маркъп езици като Relax NG или XML Schema, за да валидирате своите документи.

  • Можете да използвате XSLT трансформациите за да променяте документа според нуждите си. Един единствен документ може да бъде източник за XHTML, обикновен текст, PDF или други XML маркъп езици като SVG.

  • Програмите, които правят валидацията и трансформацията, са безплатни и лесни за употреба.

Тези възможности съществуват сега и те са лесни за изучаване и употреба. Ето защо XML е добър. Ето защо хората остават толкова възхитени от него, щом започнат да го използват.

Можете да свалите XML файловете и получените HTML, текстови и PDF файлове.