Как сохранить количество вложенных элементов с помощью XSLT? - PullRequest
1 голос
/ 16 ноября 2009

Относится к вопросу здесь .

У меня есть ввод XML в форме:

<book>
    <chapter>
        ...
    </chapter>
</book>  

В настоящее время я вывожу что-то вроде:

<div class="book" id="book-3">
    <div class="chapter>
        ...
    </div>
</div>

Использование правила <div class="book" id="book-{position()}"> для создания идентификатора книги. Так что значение идентификатора увеличивается на каждом <book> узле.

Я бы хотел получить вывод вида:

<div class="book" id="book-3">
    <div class="chapter" id="book-3-chapter-7">
        ...
    </div>
</div>

Я пытался использовать правило, которое извлекало атрибут id из родительского элемента и выводило его в дочернем элементе. Только когда я задавал этот вопрос, я понял, что, конечно, никогда не будет совпадения для "../@id", поскольку атрибут не существует в исходном XML, только в выводе.

Попытка получить родительский атрибут для использования в качестве части идентификатора, вероятно, не является "способом XSLT". Поэтому, даже если есть способ получить доступ к выходу, это, вероятно, неправильный способ сделать это.

Как только теги главы созданы с их идентификатором, появляются дочерние элементы элементов главы, которые я хотел бы придерживаться того же соглашения (поэтому они будут иметь <div id="book-2-chapter12-verse212">). Идентификатор будет использоваться отдельным приложением Java для связи с документом, поэтому важно, чтобы он следовал соглашению (т.е. сгенерированные идентификаторы не будут работать).

Как лучше всего создать этот вложенный инкрементный счетчик с использованием XSLT?

P.S. Название вопроса, вероятно, далеко от того, что я действительно хочу спросить, но я недостаточно знаю XSLT, чтобы задать правильный вопрос. Пожалуйста, не стесняйтесь редактировать или предлагать лучший заголовок.


РЕДАКТИРОВАТЬ: Хотя на первоначальный вопрос были хорошие ответы, как я уже сказал, я не был уверен, как правильно задать вопрос. Получив ответ на вопрос, который я должен был задать, я изменил вопрос.

Это означает, что есть ответы, которые касаются моего (неправильно поставленного) исходного вопроса, и ответ, который понимает намерение, которое мне было трудно выразить. Я принял последнее.

Я надеюсь, что другие ответившие найдут это приемлемым, и если есть какие-либо предложения о том, как задать неправильный вопрос, в первую очередь , я буду рад их услышать.

Ответы [ 3 ]

3 голосов
/ 16 ноября 2009

Вам следует взглянуть на элемент xsl: number . Он имеет множество форматирующих и группирующих конструкций для выполнения подсчета и меток, которые вы пытаетесь идентифицировать.

В этой статье XML.com объясняется, как использовать некоторые атрибуты для создания многоуровневых чисел (счетчиков) для книги, главы, раздела и т. Д.

Что-то вроде:

<xsl:number format="1. " level="multiple" count="book|chapter|verse"/>

, примененный в шаблоне для стиха, даст: 2.12.212

2 голосов
/ 16 ноября 2009

Я бы, вероятно, добавил параметр в шаблон и использовал with-param в apply-templates, чтобы передать его. Избегает всей двусмысленности.

<xsl:template match="..."> <!-- the child match -->
    <xsl:parameter name="parentId"/>
    <child id="{$parentId}-@id">
      <!-- code involving $parentId -->
    </child>
</xsl:template>

и что-то вроде:

<xsl:apply-templates select="child">
    <xsl:with-param name="parentId" select="@id"/>
</xsl:apply-templates>

Другой вариант - использовать .. и т. Д. Для ребенка - возможно, используя сопоставление с шаблоном на @id (из обоих мест), чтобы избежать дублирования.

0 голосов
/ 16 ноября 2009

Для этой цели я бы использовал универсальную функцию:

<xsl:template match="*">
  <xsl:copy>
    <xsl:attribute name="id">
      <xsl:call-template name="compute-id"/>
    </xsl:attribute>
    <xsl:apply-templates />
  </xsl:copy>
</xsl:template>

<xsl:template name="compute-id">
  <xsl:param name="curr-elem" select="."/>
  <xsl:param name="id" select="''"/>
  <xsl:choose>
    <xsl:when test="$curr-elem/..">
    <xsl:call-template name="compute-id">
      <xsl:with-param name="curr-elem" select="$curr-elem/.."/>
      <xsl:with-param name="id">
        <xsl:value-of select="concat(name($curr-elem), count($curr-elem/preceding-sibling::*[name()=name($curr-elem)])+1)"/>
        <xsl:if test="$id != ''">
          <xsl:value-of select="concat('-', $id)"/>
        </xsl:if>
      </xsl:with-param>
    </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$id"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...