Как использовать увеличенный счетчик для предоставления уникального идентификатора в XSLT? - PullRequest
3 голосов
/ 10 ноября 2009

Я использую XSLT для преобразования очень большого XML-документа в (X) HTML. Для некоторых тегов я конвертирую их в <div>. Я хотел бы иметь возможность создать уникальный идентификатор для этих тегов, используя увеличенное целое число, чтобы сформировать часть уникального идентификатора.

Пример используемого мной правила:

<xsl:template match="bookcoll/book">
    <div class="book">
        <xsl:apply-templates/>
    </div>
</xsl:template>

Этот шаблон XSLT работает хорошо. Теперь я хотел бы иметь тег:

<div class="book">;  

становится:

<div class="book" id="book-[COUNTER-VALUE]">  

В идеале счетчик должен начинаться с 1, а не с 0.

Я не знаю, имеет ли это большое значение, я использую Java-пакеты javax.xml.parsers и javax.xml.transform для выполнения фактического преобразования. Я немного новичок в XSLT, поэтому, если есть какая-то соответствующая информация, которую я пропустил, пожалуйста, дайте мне знать.

Как этого можно достичь в XSLT?

Ответы [ 4 ]

7 голосов
/ 10 ноября 2009

Естественное / идиоматическое / отказоустойчивое решение будет:

<div class="book" id="book-{generate-id()}">

Он не увеличивается, но гарантированно будет уникальным. И он будет производить HTML-допустимые строки идентификаторов ( name tokens ).

РЕДАКТИРОВАТЬ: Если это должно быть увеличение, сделайте что-то вроде следующего:

<!-- in the calling template… -->
<xsl:apply-templates select="bookcoll/book[xpath to filter them if necessary]" />

<!-- …later -->
<xsl:template match="bookcoll/book">
  <div class="book" id="book-{position()}">
    <xsl:apply-templates/>
  </div>
</xsl:template>

Вы можете использовать format-number(), чтобы адаптировать вывод position() к вашим потребностям.

position() вернет позицию узла относительно «пакета», который в данный момент обрабатывается. При явном вызове <xsl:apply-templates> вы убедитесь, что они пронумерованы так, как вы хотите.

4 голосов
/ 10 ноября 2009

Как предлагалось несколько раз ранее, вам нужно position(), но вы должны перебирать элементы, используя xsl:for-each:

<xsl:template match="bookcoll">
    <xsl:for-each select="book">
        <div class="book" id="book-{position()}">
            <xsl:apply-templates/>
        </div>
    </xsl:for-each>
</xsl:template>

Это даст что-то вроде:

<div class="book" id="book-1">book1</div>
<div class="book" id="book-2">book2</div>
<div class="book" id="book-3">book3</div>

для

<bookcoll>
    <book>book1</book>
    <book>book2</book>
    <book>book3</book>
</bookcoll>
0 голосов
/ 10 ноября 2009

Посмотрите на функцию position ().

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

Вы можете добавить выноски к статическим методам в классах Java для ваших преобразований ... это работает, но есть некоторые недостатки, такие как 1) Теперь ваше преобразование привязано к некоторому коду Java, и его сложнее тестировать / отлаживать во внешних инструментах, таких как Oxygen (хотя есть несколько способов смягчить это) 2) Вы должны поддерживать состояние в виде статики или, возможно, локальных потоков, что может создавать всевозможные проблемы (проблемы с синхронизацией, вопросы о сбросе, если вы делаете это несколько раз и т. Д.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...