Я хотел бы извиниться за плохое название - я действительно не знал, как это лучше сформулировать.В настоящее время я работаю над сценарием XSLT 1.0 (использующим xsltproc ), который преобразует простой формат XML в текстовое представление, пригодное для использования генератором PDF.
В моем формате XML естьвсего три элемента: <book>
, <chapter>
и <section>
.Однако из-за некоторых неприятных особенностей DTD мне трудно написать правильный сценарий XSLT для преобразования документа.Вот DTD, описывающее их отношение:
<!ELEMENT book ((chapter|section)*)>
<!ELEMENT chapter (section*)>
<!ELEMENT section (#PCDATA)>
Вот моя таблица стилей XSLT, которая выполняет перевод:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1"/>
<xsl:strip-space elements="*"/>
<xsl:template match="section">
<xsl:if test="not(preceding-sibling::section)">@BeginSections
</xsl:if>
<xsl:text>@Section @Begin
</xsl:text>
<xsl:apply-templates/>
<xsl:text>@End @Section
</xsl:text>
<xsl:if test="not(following-sibling::section)">@EndSections
</xsl:if>
</xsl:template>
<xsl:template match="chapter">
<xsl:if test="not(preceding-sibling::chapter)">@BeginChapters
</xsl:if>
<xsl:text>@Chapter @Begin
</xsl:text>
<xsl:apply-templates/>
<xsl:text>@End @Chapter
</xsl:text>
<xsl:if test="not(following-sibling::chapter)">@EndChapters
</xsl:if>
</xsl:template>
<xsl:template match="/book">
<xsl:text>@Book @Begin
</xsl:text>
<xsl:apply-templates/>
<xsl:text>@End @Book
</xsl:text>
</xsl:template>
</xsl:stylesheet>
Теперь, здесь возникает сложная часть и мой вопрос: DTD делаетэлементы <section>
могут иметь прямые дочерние элементы <book>
.Тем не менее, мне все равно нужно выдать тот же вывод, как если бы этот элемент /book/section
был на самом деле /book/chapter/section
.
Так, например: <book><section/><chapter/></book>
становится (я отступил для вывода для лучшей читаемости)
@Book @Begin
@BeginChapters
@Chapter @Begin
@BeginSections
@Section @Begin
@End @Section
@EndSections
@End @Chapter
@Chapter @Begin
@End @Chapter
@EndChapters
@End @Book
Итак, я хотел бы настроить мой XSLT-скрипт так, чтобы шаблон 'section' так или иначе вызывал шаблон 'chapter' в случае, если данный элемент <section>
не находится внутри <chapter>
.Как я мог это сделать?
Для чего это стоит, вот еще один пример.Несколько <section>
элементов, которых еще нет в <chapter>
, должны быть объединены в один.Следовательно, <book><section/><section/><section/><chapter/><section/></book>
дает вывод для трех глав (первая из которых имеет три секции, вторая не имеет ни одной, третья имеет одну секцию).