#xml #xslt #xsl-stylesheet
#xml #xslt #xsl-таблица стилей
Вопрос:
Я новичок в xslt и столкнулся с проблемой, поскольку я динамически сгенерировал XML-файл (т. Е. Имена узлов неизвестны) И пробовал много подходов для просмотра содержимого во вложенных таблицах в html-файле с использованием xslt, но все мои усилия терпят неудачу.
<?xml version="1.0" encoding="UTF-8"?>
<content>
<Source>
<Column1>Name</Column1>
<Column2>Organization Name</Column2>
<SubSource>
<Column1>Name</Column1>
<Column2>Person Name</Column2>
<Column1>Address</Column1>
<Column2>House: E5, Block-G, Road-02</Column2>
<Details>
<Column1>Entry date</Column1>
<Column2>6/6/13 12:04 PM</Column2>
<Column1>height</Column1>
<Column2>153</Column2>
<Column1>weight</Column1>
<Column2>53.5</Column2>
<Column1>temperature</Column1>
<Column2>98.67</Column2>
<Column1>pulse rate</Column1>
<Column2>76</Column2>
<Advices>
<Advice>
<Column1>Title</Column1>
<Column2>Workout</Column2>
<Column1>Location</Column1>
<Column2>In the Park</Column2>
</Advice>
<Advice>
<Column1>Title</Column1>
<Column2>Eating Habit</Column2>
<Column1>Remarks</Column1>
<Column2>Eat Less</Column2>
<Column1>Notes</Column1>
<Column2>Avoid salts</Column2>
</Advice>
</Advices>
</Details>
</SubSource>
</Source>
<Source>
<Column1>Name</Column1>
<Column2>Organization Name</Column2>
<SubSource>
<Column1>Name</Column1>
<Column2>Person Name</Column2>
<Column1>Address</Column1>
<Column2>House: E5, Block-G, Road-02</Column2>
<Details>
<Column1>Entry date</Column1>
<Column2>6/6/13 12:04 PM</Column2>
<Column1>height</Column1>
<Column2>153</Column2>
<Column1>weight</Column1>
<Column2>53.5</Column2>
<Column1>temperature</Column1>
<Column2>98.67</Column2>
<Column1>pulse rate</Column1>
<Column2>76</Column2>
<Advices>
<Advice>
<Column1>Title</Column1>
<Column2>Workout</Column2>
<Column1>Location</Column1>
<Column2>In the Park</Column2>
</Advice>
</Advices>
</Details>
</SubSource>
</Source>
</content>
Я использовал несколько подходов xslt. Однако все они не просматривают данные так, как требуется, либо меньше, либо не в таблице правильного формата!!!
Моим лучшим подходом было следующее (я не делал дизайн с несколькими таблицами, так как хотел сначала получить все данные)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<table>
<xsl:apply-templates select="content/Source"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="content/Source">
<xsl:variable name="column" select="content/Source"/>
<tr>
<td>
<xsl:value-of select="Column1"/>
</td>
<td>
<xsl:value-of select="Column2"/>
</td>
</tr>
<xsl:apply-templates select="SubSource"/>
</xsl:template>
<xsl:template match="SubSource">
<tr>
<td>
<xsl:value-of select="Column1"/>
</td>
<td>
<xsl:value-of select="Column2"/>
</td>
</tr>
<xsl:apply-templates select="Details"/>
</xsl:template>
<xsl:template match="Details">
<tr>
<td>
<xsl:value-of select="Column1"/>
</td>
<td>
<xsl:value-of select="Column2"/>
</td>
</tr>
<xsl:apply-templates select="Advices"/>
</xsl:template>
<xsl:template match="Advices">
<xsl:for-each select="Advice">
<tr>
<td>
<xsl:value-of select="Column1"/>
</td>
<td>
<xsl:value-of select="Column2"/>
</td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
И результат:
<table>
<tr>
<td>Name</td>
<td>Organization Name</td>
</tr>
<tr>
<td>Name</td>
<td>Person Name</td>
</tr>
<tr>
<td>Entry date</td>
<td>6/6/13 12:04 PM</td>
</tr>
<tr>
<td>Title</td>
<td>Workout</td>
</tr>
<tr>
<td>Title</td>
<td>Eating Habit</td>
</tr>
<tr>
<td>Name</td>
<td>Organization Name</td>
</tr>
<tr>
<td>Name</td>
<td>Person Name</td>
</tr>
<tr>
<td>Entry date</td>
<td>6/6/13 12:04 PM</td>
</tr>
<tr>
<td>Title</td>
<td>Workout</td>
</tr>
</table>
Моя цель — получить макет таблицы, аналогичный структурированному XML.
Советы по улучшению формата XML всегда приветствуются!
Спасибо
Ответ №1:
Эта таблица стилей XSLT 1.0 делает то, что вы, кажется, хотите: она создает вложенные HTML-таблицы из структуры неизвестных имен элементов.
I единственным предварительным условием является наличие <Column1>
элементов, за которыми, возможно, следует связанный <Column2>
.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<!-- #1: anything that has <Column1> children becomes a table -->
<xsl:template match="*[Column1]">
<table class="{name()}">
<xsl:apply-templates select="*" mode="nested" />
</table>
</xsl:template>
<!-- #2: ...if it's nested, it is wrapped in a table row first -->
<xsl:template match="*[Column1]" mode="nested">
<tr>
<td colspan="2">
<!-- this actually executes #1 because it uses no mode! -->
<xsl:apply-templates select="." />
</td>
</tr>
</xsl:template>
<!-- #3: <Column1> governs the creation of table rows -->
<xsl:template match="*[Column1]/Column1" mode="nested">
<tr>
<td><xsl:value-of select="." /></td>
<td><xsl:value-of select="following-sibling::*[1][self::Column2]" /></td>
</tr>
</xsl:template>
<!-- #4: suppress any other data field (like <Column2>) -->
<xsl:template match="*[Column1]/*[not(*)]" mode="nested" />
</xsl:stylesheet>
Обратите внимание на использование режимов шаблонов: если существует более одного шаблона, который может соответствовать определенному элементу, вы можете использовать mode
для различения между ними.
В этом случае вы хотите создать вложенные таблицы. На корневом уровне (вариант по умолчанию) вы можете просто создать <table>
элемент.
Однако, если вы уже находитесь внутри a <table>
, сначала вы должны создать <tr>
/ <td>
, но после этого процесс тот же.
Используя режимы, я могу убедиться, что правильный шаблон выполняется в правильном контексте, без необходимости повторяться, когда дело доходит до создания фактического <table>
.
В качестве побочного эффекта, используя режимы, мы могли бы создать целый набор шаблонов, которые можно вставить в существующую таблицу стилей, не влияя на установленный рабочий процесс.
following-sibling::*[1][self::Column2]
является «первым следующим родственным, но только если он на самом деле является <Column2>
.».
Шаблон # 4 необходим, поскольку довольно неопределенный <xsl:apply-templates select="*" mode="nested" />
также применяется к <Column2>
. Однако на самом деле они уже обрабатываются # 3, что означает, что если мы явно не подавим их, они будут генерировать нежелательные повторяющиеся выходные данные.
Комментарии:
1. Большое спасибо за вашу помощь @Tomalak. Однако мне пришлось удалить # 4, поскольку это приводило к тому, что данные в (Column1 и Column2) не появлялись!! Также есть небольшой поток, и я не могу понять, что его вызывает? Значение Column2 по какой-то причине повторяется после </tr> !!!
<tr> <td>Name</td> <td>Organization Name</td> </tr>Organization Name
2. Если вы удалите # 4, все будет повторяться. Я написал это в своем ответе.
3. Да, вы ясно дали это понять. Однако с # 4 я получаю пустые таблицы!!! (без столбцов и строк)
<table class="SubSource"><tr><td colspan="2"><table class="Details"><tr><td colspan="2"><table class="Advice"></table>
4. Ну, я этого не делаю. Сравните: xmlplayground.com/CyZs9O , он использует именно ваш входной образец и именно XSLT из моего ответа. Ошибка должна быть где-то в другом месте.
5. Кажется, у меня возникли некоторые проблемы в моей среде разработки. Протестировал его на w3schools, и он работает отлично. Большое спасибо @Tomalak за помощь и объяснение метода.