xsl променлива

  • имезадължителен атрибут, задава името на променливата
  • изберете - незадължителен атрибут, израз

Спецификация

Описание и примери

  • първо се оценява стойността на израза, който трябва да бъде присвоен;
  • след това получената стойност се свързва с посоченото име.

Стойността на присвоения израз се оценява в зависимост от това как е дефиниран елементът xsl:variable:

  • ако атрибутът select е дефиниран в елемента xsl:variable, тогава стойността на присвоения израз ще бъде резултат от оценяването на израза, посочен в този атрибут;
  • ако атрибутът select не е дефиниран, но самият елемент xsl:variable има дъщерни възли (с други думи, съдържа шаблон), стойността на променливата, която се дефинира, ще бъде резултантният фрагмент на дървото, резултат от изпълнението на съдържанието на xsl:variable;
  • ако атрибутът select не е дефиниран и самият елемент xsl:variable е празен, параметърът по подразбиране е празен низ.

Можете да използвате стойностите, присвоени на променливи по време на инициализация, като предхождате името на променливата със символа „$“, например за променливата x - $x. В XPath изразите синтаксисът за препращане към променливи съответства на производството на VariableReference.

Името на променливата следва синтаксисното правило QName, с други думи, може да бъде във формата име или префикс:име. По правило имената на променливите се дават без префикси, но ако въпреки това е указан префикс, променливата свързва с някакъв обект не просто, а разширено име. Съответно обжалването на обекта също ще трябва да се направи чрез разширеното име.

Променлив обхват

Всяка от променливите имасобствен обхват (английски scope) - областта, в която може да се използва неговата стойност. Обхватът се определя по следния начин.

За да изясним напълно ситуацията, даваме няколко примера.

Да предположим, че дефинираме променлива с име ID и стойност 4 по този начин:

Лесно се вижда, че тук сме дефинирали глобална променлива, което означава, че нейната стойност може да се използва в трансформацията навсякъде. Например можем да дефинираме други глобални променливи чрез него или да го използваме в шаблон:

би било неправилно поради изричното използване на променливата в нейната собствена дефиниция. По същия начин дефинициите биха били неправилни:

тъй като променливата ID е дефинирана от гледна точка на променливата id, която е дефинирана от гледна точка на променливата ID, и така нататък до безкрайност.

Нещата са малко по-сложни с локалните променливи. За да обясним какво е обхват, нека разгледаме следната трансформация.

Листинг 5.22. Трансформирайте с помощта на i, j, k и gt променливи

Тази трансформация дефинира три локални променливи, i, j и k, и една глобална променлива, gt. В следващите четири списъка ще подчертаем обхвата на променливата (т.е. областта, където може да се използва) със сиво запълване, а самата дефиниция на променливата ще бъде маркирана с удебелен шрифт.

Листинг 5.23. Обхват на променливите i, j, k и gt

Обхват на променлива i

Обхват на променлива j

Обхват на променлива k

Обхват на променлива gt

XSLT има същото правило като много други езици за програмиране: не можете да дефинирате променлива с едно и също име два пъти. Въпреки това и тукимат свои собствени характеристики.

  • Две глобални променливи могат да имат едно и също име, ако и само ако имат различен ред на импортиране. Например, ако променливи с едно и също име са дефинирани в различни трансформации, една от тях може да бъде импортирана. В този случай променливата ще има стойността, дадена от елемента xsl:variable с основния ред на импортиране.
  • Имената на локални и глобални променливи могат да съвпадат - в този случай локалната стойност ще се използва в обхвата на локалната променлива, а глобалната стойност в обхвата на глобалната (но не локалната) променлива. С други думи, локалните променливи „затварят“ стойностите на глобалните.
  • Две локални променливи могат да имат едно и също име, ако и само ако техните обхвати не се припокриват.

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

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

Списък 5.24. en.xsl трансформация

Резултатът от тази трансформация ще бъде следният фрагмент:

За да преведете етикетите на тези бутони на друг език, просто предефинирайте променливите. Например резултатът от изпълнението на следния шаблон.

Списък 5.25. de.xsl трансформация

ще има същия фрагмент, но на немски:

От друга страна, предефинирането на променливи може да бъде опасно: ако отделните модулиразработени независимо, съвпадението на имена на глобални променливи може да доведе до грешки. За да се изключи това по принцип, името на променливата трябва да бъде декларирано в конкретно пространство от имена, например:

В случай, че префиксите app и db (които, разбира се, трябва да бъдат декларирани) сочат към различни пространства от имена, няма да има конфликт между тези две променливи.

Връщайки се към темата за съвпадения на имена на променливи, нека демонстрираме „скриването“ на локална променлива на стойността на глобална:

Резултатът от изпълнението на този шаблон ще бъде:

Разгледайте сега случая на две локални променливи. Нека се опитаме да декларираме две локални променливи - една след друга в следния шаблон:

В текста на този шаблон маркирахме два обхвата на две променливи: в сиво запълване - обхватът на първата и в получер - обхватът на втората променлива. Поради факта, че тези области се пресичат, шаблонът ще бъде неправилен - процесорът ще издаде съобщение за грешка като:

Ето още една трансформация, при която елементите xsl:variable принадлежат на два братски елемента:

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

Използване на променливи

По правило първата реакция на новината, че променливите в XSLT не могат да бъдат променяни, е забележката: „Но защо тогава изобщо са необходими?!“.

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

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

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

много по-удобно и икономично от гледна точка на изчислителни ресурси е да се декларира променлива на формата

и го използвайте при преобразуването като $a. Филтърните изрази на XPath (производство на FilterExpr) ни позволяват след това да имаме достъп до възлите на избрания набор по същия начин, както ако работим с оригиналния израз. Например, $a[1] ще бъде еквивалентно на //a[@href][1] и $a/@href на //a[@href]/@href. В този случай, при достъп до $a, процесорът няма да претърси отново всички елементи на a с атрибута href, което по всяка вероятност ще има положителен ефект върху производителността.

Друга илюстрация на същия случай на използване на променлива може да бъде следната ситуация: в някои случаи изразите могат да бъдат лесни за изчисляване, но твърде тромави за писане. Много по-елегантно е да изчислите този тромав израз веднъж,запазете го в променлива и след това се обърнете към него с краткото му име. Например, следният елемент xsl:variable оценява и съхранява дълга и тромава препратка в променливата gv:

След такава дефиниция използването на тази препратка в трансформацията става удобно и стегнато:

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

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

По-практично използване на способността на променливите да съдържат фрагменти от дърво е условното присвояване на стойност на променлива. Представете си следния алгоритъм:

За процедурен език с променливи променливи това не е проблем. В Java такъв код би изглеждал елементарен:

или в малко по-дълъг вариант:

Въпреки това, ако в XSLT написахме нещо като:

желаният резултат все още не би бил постигнат поради простата причина, че променливите, които дефинирахме, биха били налични само в техния обхват, който завършва със затварящите тагове на елементите xsl:when и xsl:otherwise. Правилният модел за тази задача е както следва:

Разбира се, това не е точно същото - всъщност ние не получаваме стойност, а дърво, съдържащо тази стойност, но за низови и числови стойности няма голяма разлика: дървото ще се държи точно по същия начин като число или низ. За булеви стойности и набори от възли трябва да се намерят други методи. Булева стойност може да бъде изразена чрез условие,Например:

За набор от възли можете да използвате предикати и набор операции:

Обърнете внимание, че шаблон, съдържащ се в елемент xsl:variable, може да включва елементи като xsl:call-template, xsl:apply-templates и т.н. Тоест на променлива може да бъде присвоен резултатът от изпълнението на един или повече шаблони.

Използването на външни документи при трансформацията, като правило, е придружено от тромави изрази като:

За да избегнете използването на функцията документ всеки път при достъп до външен документ, можете да декларирате променлива, която ще съдържа основния възел на този документ, например:

След това документът http://www.xmlhost.com/docs/a.xml може да бъде достъпен чрез променлива с име a.xml, така:

xsl:променлива на MDN xsl:променлива на MSDN