Найти абсолютную позицию тега XML с помощью XSLT - PullRequest
1 голос
/ 05 марта 2010

У меня есть этот XML-документ, в котором я хочу изменить с помощью XSLT другой формат. Проблема, с которой я сейчас сталкиваюсь - это найти абсолютную позицию тега относительно корня, а не родителя.

Например, возьмем следующий пример:

<book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>
<book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>    <book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>    <book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>

Желаемый вывод:

<book id=1>
  <section id=1>
     <chapter id=1>
     </chapter>
  </section>
</book>
<book id=2>
  <section id=2>
     <chapter id=2>
     </chapter>
  </section>
</book>    
<book id=3>
  <section id=3>
     <chapter id=3>
     </chapter>
  </section>
</book>    
<book id=4>
  <section id=4>
     <chapter id=4>
     </chapter>
  </section>
</book>

Получить идентификатор для тега книги можно легко, используя position (), но как только мы перейдем к разделу и главе, все станет сложнее.

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

заранее спасибо,

FBR

Ответы [ 3 ]

1 голос
/ 06 марта 2010

xsl: number было построено для такого сценария.

Это позволяет очень легко создавать различные отформатированные числа и числа и часто используется в XSL-FO для таких вещей, как оглавление и метки для рисунков и таблиц (например, рисунок 3.a, раздел 1.1 и т. д.)

Я изменил образец XML, добавив элемент документа, чтобы он был правильно сформирован.

Использование этой таблицы стилей дает желаемый результат.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="/">
            <xsl:apply-templates select="*/book" />
</xsl:template>

    <xsl:template match="*">
        <xsl:copy>
            <xsl:attribute name="id">   
                <xsl:number format="1 " level="single" count="book"/>
            </xsl:attribute>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
0 голосов
/ 06 марта 2010

Как насчет

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="*|@*|text()">
    <xsl:copy>
        <xsl:apply-templates select="*|@*|text()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="book|section|chapter">
    <xsl:copy>
           <xsl:attribute name="ix">
                <xsl:value-of select="1 + count(preceding::*[name() = name(current())])"/>
            </xsl:attribute> 
        <xsl:apply-templates select="*|@*|text()" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

(вместо «id» используется «ix», поскольку в вашем XML не должно быть нескольких элементов с одинаковым идентификатором)

0 голосов
/ 05 марта 2010

Должны ли идентификаторы быть целыми числами? Самый простой способ создать уникальные идентификаторы - добавить их к своим родителям:

<book id="1">
  <section id="1.1">
     <chapter id="1.1.1">
     </chapter>
  </section>
</book>

В этом случае вы можете использовать position() и рекурсию для простой генерации идентификаторов.

...