Данные XML можно преобразовать в HTML с помощью простой таблицы стилей XSL. Поскольку спецификация XML продолжает развиваться, кажется необходимым удовлетворить потребности каждого в новых версиях; к сожалению, выполнение простых преобразований всегда мешало спецификации.
Предположим, у меня есть данные XML, представляющие содержимое страницы, и теперь я хочу преобразовать их содержимое в макет. Вот XML, который я хочу преобразовать:
<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="article.xsl"?>
<xml>
<папки>
<папка>
<text>Папка 1</text>
<файлы>
<файл>
<text>Файл 1</text>
<поля>
<поле>
<данные>
<type>строка</type>
<длина>50</длина>
<value>некоторые данные</value>
</данные>
</поле>
</поля>
</файл>
</файлы>
</папка>
</папки>
</xml>
Это содержимое представляет собой набор папок, файлов и полей. Каждая папка содержит файлы, а каждый файл содержит поля для ввода данных. Каждая папка в группе папок будет представлена элементом TR и элементом TD в первой строке таблицы TABLE. Каждый файл в группе файлов будет представлен как элемент TR и элемент TD в первой строке элемента TABLE, вложенного в элемент TR папки. Каждый домен в группе доменов будет отображаться как ВХОД в связанном файле.
Чтобы реализовать эту идею, нам нужно просмотреть XML и построить таблицу на основе XSL.
Вот XSL, используемый для этого преобразования:
<?xml version="1.0"?>
<xsl:таблица стилей
xmlns:xsl=" http://www.w3.org/1999/XSL/Transform " версия="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:fn=" http://www.mycompany.com/mynamespace ">
<xsl:output метод="html"/>
<msxsl:script Language="JScript" реализует-префикс="fn">
функция getElementCount(список узлов, что) {
вартрн = 0;
rtrn = список узлов[0].parentNode.selectNodes(what).length;
return (rtrn + 1); //1 добавляется для заполнителя TD;
}
</msxsl:script>
<xsl:template match="/">
<TABLE CELLSPACING="0" CELLPADDING="0"
WIDTH="100%" BORDER="0" ID="tblRoot" NAME="tblRoot"
style="table-layout:fixed;">
<ТР>
<xsl:for-each select="xml/folders/folder">
<xsl:element name="TD">
<xsl:attribute name="style">ширина:55 пикселей</xsl:attribute>
<xsl:value-of select="text"/>
</xsl:element>
</xsl:for-each>
<ТД> </ТД>
</TR>
<xsl:for-each select="xml/folders/folder">
<ТР>
<xsl:element name="TD">
<xsl:attribute name="colspan">
<xsl:value-of select="fn:getElementCount(., 'folder')"/>
</xsl:атрибут>
<TABLE CELLSPACING="0" CELLPADDING="0"
WIDTH="100%" BORDER="0" style="table-layout:fixed;">
<ТР>
<xsl:for-each select="files/file">
<xsl:element name="TD">
<xsl:attribute name="style">ширина:55 пикселей;</xsl:attribute>
<xsl:value-of select="text"/>
</xsl:element>
</xsl:for-each>
<ТД> </ТД>
</TR>
<xsl:for-each select="files/file">
<ТР>
<xsl:element name="TD">
<xsl:attribute name="colspan">
<xsl:value-of select="fn:getElementCount(., 'file')"/>
</xsl:attribute>
<xsl:for-each select="fields/field">
<xsl:element name="INPUT">
<xsl:attribute name="type">текст</xsl:attribute>
<xsl:attribute name="maxlength">
<xsl:value-of select="data/length"/>
</xsl:атрибут>
<xsl:имя атрибута="значение">
<xsl:value-of select="data/value"/>
</xsl:атрибут>
</xsl:element><BR/>
</xsl:for-each>
</xsl:element>
</TR>
</xsl:for-each>
</ТАБЛИЦА>
</xsl:element>
</TR>
</xsl:for-each>
</TABLE>
</xsl:template>
</xsl:таблица стилей>
В теге таблицы стилей мы настраиваем несколько пространств имен, включая пространство имен xsl, которое определяет все теги преобразования xsl. msxml, которое позволяет нам создавать пользовательские функции, которые можно использовать в таблицах стилей. Я использую это для получения всех дочерних элементов и получения набора атрибутов COLSPAN для тега TD. Пространство имен fn, используемое для объединения набора пользовательских функций, созданных элементом msxml:script.
Затем мы создаем внешнюю TABLE и первый TR. В TR я создаю TD для каждой папки, указанной в XML. Я использовал тег xsl:element, поскольку он позволяет мне добавлять пользовательские атрибуты или выполнять функцию для установки свойства атрибута COLSPAN в другом элементе TD.
После создания необходимого ТД для каждой папки я приступил к созданию ТР для каждой папки. Я добавляю к этому TR только один TD, но устанавливаю его атрибут COLSPAN равным количеству тегов папок в группе папок плюс один. Дополнительный используется для заполнения пробелов в TABLE с фиксированным макетом.
Чтобы получить COLSPAN, я передаю текущий контекст (указанный здесь знаком «.») и имя узла, который хочу вычислить. В моей функции я получаю текущий контекст, paraentNode и количество узлов, указанных в запросе XPath. Затем функция возвращает эту сумму плюс единицу для заполнения TD.
С помощью этого TD я встраиваю в него еще одну ТАБЛИЦУ, содержащую каждый файл в файловой группе. С этого момента процесс такой же, как и при внешнем преобразовании TABLE. Последний шаг — добавить поля в каждый файл. На этот раз я не создавал встроенную ТАБЛИЦУ, а просто добавил поля в текущую ТД.
После того, как я завершил общий макет, я могу начать добавлять функции пользовательского интерфейса, такие как скрытие других папок и строк файлов, пока пользователь не нажмет соответствующую вкладку. Эту функциональность можно реализовать, написав сценарий, поддерживающий эту функциональность, добавив элемент onclick xsl:attribute к элементам TD папки и файла, а затем установив для него значение имени функции сценария.
Наконец, после завершения общей функциональности вы можете добавить класс xsl:attributes и добавить соответствующие имена классов в STYLE или CSS, чтобы получить желаемый вид.
В этом примере создается основа для представления «Файл-Папка-Поле», используемого при развертывании решений для веб-данных. Посетите MSDN, чтобы узнать больше о спецификации Microsoft XML.