![]() |
Александр Самиляк
14 июня 2011 |
|
![]() |
Задача. | Рассказать о неймспейсах в XSLT. |
![]() |
![]() |
![]() |
Корневым элементом XSL-шаблона является <xsl:stylesheet>, и во многих случаях он выглядит так:
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > ... </xsl:stylesheet>
Атрибут version является обязательным, равно как и объявление XSL-неймспейса xmlns:xsl="http://www.w3.org/1999/XSL/Transform" (иначе было бы неясно, где в шаблоне сам XSL-код). А вот зачем нам нужна запись xmlns="http://www.w3.org/1999/xhtml", не очень понятно.
Для начала уясним, что вообще делают эти конструкции, начинающиеся с xmlns. У всесильного W3C на эту тему тоже есть свой документ, озаглавленный «Неймспейсы в XML». Почитав его (перед сном это делать не рекомендуется), мы узнаем, что основной причиной возникновения неймспейсов явилась необходимость отличать
Хорошим примером такого разделения может служить как раз милый нашему сердцу XSL. Скажем, элемент <xsl:text> имеет неймспейс xsl и является управляющим XSL-кодом, тогда как элемент <text> неймспейса не имеет и просто отправляется на вывод, несмотря на то что имя у него тоже text.
Чтобы использовать какой-то неймспейс в своем XML (а XSL есть XML), его надо сначала объявить. Продолжая изучать вышеозначенный документ, мы обнаруживаем, что существуют два способа объявления неймспейсов: с префиксом и без префикса.
Форма с префиксом имеет вид:
xmlns : префикс = "полный URI"
Здесь префикс — это некоторое внутреннее имя нашего
Следует также понимать, что
Итак, объявив неймспейс с префиксом, мы теперь можем его использовать — писать элементы, имеющие этот неймспейс. Как это делать, читатель наверняка знает:
<префикс : имя элемента>
Ровно так все делают в XSL-коде, когда хотят использовать какой-то XSL-элемент, например <xsl:template>. Как я уже сказал, префикс может быть любым, поэтому можно писать и так:
<god_bless_america:stylesheet version="1.0" xmlns:god_bless_america="http://www.w3.org/1999/XSL/Transform" > <god_bless_america:template match="/"> ... </god_bless_america:template> </god_bless_america:stylesheet>
Но все привыкли использовать xsl — это коротко и удобно.
Переходим к неймспейсу без префикса. Он имеет вид:
xmlns = "полный URI"
Эта конструкция объявляет неймспейс по умолчанию. Он нужен в ситуации, когда при написании элемента мы не указываем префикс, а пишем сразу имя элемента — <div>. То есть элемент, не имеющий префикса, считается принадлежащим к неймспейсу по умолчанию.
А что если неймспейс по умолчанию не объявлен и у элемента нет префикса? Такую ситуацию вэтрицэшники тоже регламентируют: тогда элемент получит неймспейс, не имеющий значения, который называется null.
Следовательно, запись xmlns="http://www.w3.org/1999/xhtml" в начале XSL-шаблона нужна для того, чтобы сообщить XSL-процессору (трансформатору), что все элементы, не имеющие префикса, относятся к этому неймспейсу XHTML-документов. А что это дает? Самое смешное, что ничего особенного.
Все, что произойдет, — это копирование указанного неймспейса в выходной HTML. То есть такой XSL-шаблон:
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:template match="/"> <html> <body> <p>Дизайн спасет мир</p> </body> </html> </xsl:template> </xsl:stylesheet>
выведет следующее:
<html xmlns="http://www.w3.org/1999/xhtml"> <body> <p>Дизайн спасет мир</p> </body> </html>
Это, конечно, круто, и этого даже требует XHTML-спецификация, но в жизни от этого ни холодно ни жарко. Другое замеченное изменение в поведении трансформатора: если выставлен <xsl:output method="html" />, то при отсутствии неймспейса по умолчанию выходят незакрытые теги (<br>). Но при xmlns="http://www.w3.org/1999/xhtml" теги начинают закрываться. Однако если кто-то думает, что сайт с валидным HTML работает лучше, чем с невалидным, то ему самое время встать и выйти. Меня это сильно раздражает, ведь сайты делаются для людей, а не для валидатора.
Итак, берусь утверждать, что при выводе HTML ощутимой пользы от этого xmlns="http://www.w3.org/1999/xhtml" нет. А есть ли вред? Оказывается, небольшой есть — от неаккуратного использования.
Трансформаторы обязаны копировать xmlns в выходной HTML по XSL-спецификации. Дело в том, что трансформатор может генерировать не только HTML, но и произвольный XML (который может быть подвергнут дальнейшей машинной обработке), и в нем нужно сообщить, какому неймспейсу принадлежат элементы, не имеющие префикса. Причем в этом месте действуют определенные правила. В частности, запись:
<html xmlns="http://www.w3.org/1999/xhtml"> ... </html>
говорит, что текущий элемент <html> и все его потомки, не имеющие префикса, относятся к неймспейсу http://www.w3.org/1999/xhtml. Это важно. Именно из-за этого в HTML регулярно вылезают эти записи xmlns="http://www.w3.org/1999/xhtml".
Разберемся на примере. Представим, что у нас есть два XSL-шаблона, причем один импортирует другой.
Главный шаблон:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:import href="import.xsl" /> <xsl:template match="/"> <html> <head> <title>Billie Jean</title> </head> <body> <xsl:call-template name="lyrics" /> </body> </html> </xsl:template> </xsl:stylesheet>
Импортируемый шаблон import.xsl:
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:template name="lyrics"> <p>Billie Jean is not my lover</p> <p>She's just a girl who claims that I am the one</p> <p>But the kid is not my son</p> </xsl:template> </xsl:stylesheet>
Результатом выполнения главного шаблона будет:
<html> <head> <title>Billie Jean</title> </head> <body> <p xmlns="http://www.w3.org/1999/xhtml">Billie Jean is not my lover</p> <p xmlns="http://www.w3.org/1999/xhtml">She's just a girl who claims that I am the one</p> <p xmlns="http://www.w3.org/1999/xhtml">But the kid is not my son</p> </body> </html>
Почему посреди нашего HTML вылезли эти xmlns="http://www.w3.org/1999/xhtml", да еще три раза?
Сначала главный шаблон выводит элементы <html>, <head> и <body>. В главном шаблоне нет объявления неймспейса по умолчанию (он null), поэтому никаких xmlns у элемента <html> тоже нет. Но дальше внутри <body> вызывается шаблон name="lyrics", который находится в другом файле import.xsl. И вот у негó уже есть объявление неймспейса по умолчанию, которое действует на все элементы, выводимые в коде этого файла import.xsl. Поэтому при выводе абзацев <p> нам и сообщается, что у них неймспейс http://www.w3.org/1999/xhtml, иначе они примут неймспейс своего родителя <body>, который равен null. Это произошло с каждым абзацем, так как они вышли братьями.
Рассмотрим обратную ситуацию, когда в главном шаблоне есть xmlns="http://www.w3.org/1999/xhtml", а в импортируемом — нет. Тогда на выходе мы получим другой сюрприз:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Billie Jean</title> </head> <body> <p xmlns="">Billie Jean is not my lover</p> <p xmlns="">She's just a girl who claims that I am the one</p> <p xmlns="">But the kid is not my son</p> </body> </html>
Элемент <html> и все его потомки законно получают XHTML-неймспейс. Но у абзацев-то он null (ибо в их файле import.xsl xmlns не указан), поэтому абзацы бунтуют и говорят нам: «Идите к черту. Не хотим наследовать ваш XHTML. У нас свой неймспейс null». Это выражается в записи xmlns="" у каждого абзаца, которая как раз и означает, что неймспейс этого элемента null.
Вывод: надо или во всех XSL-файлах объявлять неймспейс по умолчанию, или во всех не объявлять. Лично я везде не объявляю — меньше суеты в коде.
В следующей части мы подробнее разберемся в неймспейсах с префиксом.
1 |
|
© 19952023 Студия Артемия Лебедева
|