powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Как перенести элемент на уровень выше с помощью XSLT?
15 сообщений из 15, страница 1 из 1
Как перенести элемент на уровень выше с помощью XSLT?
    #37190049
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Уважаемые, подскажите пожалуйста, как перенести элемент на уровень выше?

Вот моя предыдущая тема по конвертеру FB2DocBook , позволяющему сделать из FB2 документ PDF или EPUB трансформацией FB2 — DocBook — XSL-FO — PDF|EPUB:
http://www.sql.ru/forum/actualthread.aspx?tid=836994


Теперь возникла проблема со сносками внутри сносок. DocBook-XSL допускает вложения <footnote> одного в другое, а FOP поддерживает только один уровень (вылетая с ошибкой при большем их числе).

Сейчас я сделал ссылки второго и ниже уровней вложения как простой текст внутри сноски первого уровня. Можно ли как-то переносить сами сноски на уровень выше, или хотя бы в самый конец сноски первого уровня как простой текст?

Вот код шаблона трансформаций, ответственный за ссылки:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
<!-- ================================================================ -->

    <xsl:template match="fb:a">
        <xsl:variable name="href_id">
            <xsl:call-template name="gen_fname">
                <xsl:with-param name="href" select="@xlink:href"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:choose>
          <!-- Исключить из обработки сноски в сносках (т.е. находящиеся в body name="notes") -->
          <!-- Причина: FOP не обрабатывает такие сноски и конвертер вылетает с ошибкой -->
            <xsl:when test="ancestor::fb:body[not(@name='notes' or @name='footnotes')] and @type='note'">
                <xsl:call-template name="a_footnote">
                    <xsl:with-param name="href_id" select="$href_id"/>
                    <xsl:with-param name="label" select="text()"/>
                </xsl:call-template>
            </xsl:when>
          <!-- Обработка сносок в сносках -->
            <xsl:when test="ancestor::fb:body[(@name='notes' or @name='footnotes')] and @type='note'">
                <xsl:call-template name="a_footnote_in">
                    <xsl:with-param name="href_id" select="$href_id"/>
                </xsl:call-template>
            </xsl:when>
          <!-- Внешние ссылки -->
            <xsl:when test="starts-with($href_id,'http://') or starts-with($href_id,'https://')
                         or starts-with($href_id,'ftp://') or starts-with($href_id,'mailto:')">
                <xsl:call-template name="a_ulink">
                    <xsl:with-param name="href_id" select="$href_id"/>
                </xsl:call-template>
            </xsl:when>
          <!-- Всё прочее как перекрёстные ссылки -->
            <xsl:otherwise>
                <xsl:call-template name="a_link">
                    <xsl:with-param name="href_id" select="$href_id"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Шаблон для обработки подстраничных сносок -->
    <xsl:template name="a_footnote">
        <xsl:param name="href_id"/>
        <xsl:param name="label"/>
        <xsl:element name="footnote">
            <xsl:attribute name="id">
                <xsl:value-of select="$href_id"/>
            </xsl:attribute>
            <xsl:for-each select="key('note-link', $href_id)">
                <xsl:apply-templates select="fb:p|fb:poem|fb:cite|fb:image|fb:table"/>
            </xsl:for-each>
            <xsl:if test="count(key('note-link', $href_id)) = 0">
                <xsl:message> Footnote body not found <xsl:value-of select="$href_id"/>!</xsl:message>
                <xsl:element name="para">
                    <xsl:text>Not found </xsl:text> <xsl:value-of select="$href_id"/> <xsl:text>!</xsl:text>
                </xsl:element>
            </xsl:if>
        </xsl:element>
    </xsl:template>

    <!-- Шаблон для обработки сносок в сносках (с форматированием как параграфа) -->
    <xsl:template name="a_footnote_in">
        <xsl:param name="href_id"/>
        <xsl:message> INFO: footnote body moved [<xsl:value-of select="$href_id"/>]</xsl:message>
        <xsl:element name="superscript">
            <xsl:text>[</xsl:text> <xsl:value-of select="$href_id"/> <xsl:text>]</xsl:text>
        </xsl:element>
        <xsl:element name="para">
            <xsl:text>---</xsl:text>
            <xsl:for-each select="key('note-link', $href_id)">
                <xsl:apply-templates select="fb:p|fb:poem|fb:cite|fb:image|fb:table"/>
            </xsl:for-each>
            <xsl:text>---</xsl:text>
        </xsl:element>
    </xsl:template>

    <!-- Шаблон для обработки внешних ссылок -->
    <xsl:template name="a_ulink">
        <xsl:param name="href_id"/>
        <ulink url="{$href_id}">
            <xsl:if test="@xlink:type != ''">
                <xsl:attribute name="xlink:type">
                    <xsl:value-of select="@xlink:type"/>
                </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates/>
        </ulink>
    </xsl:template>

    <!-- Перекрёстные ссылки в виде гиперссылок внутри документа -->
    <xsl:template name="a_link">
        <xsl:param name="href_id"/>
        <link linkend="{$href_id}">
            <xsl:apply-templates/>
        </link>
    </xsl:template>

<!-- ================================================================ -->
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190156
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kaznelson,

Можно упростить вопрос? В чем суть проблемы? Сделать из
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
<footnotes>
	<footnote>
		<text>Сноска1</text>
		<footnote>
			<text>сноска сноски1</text>
		</footnote>
	</footnote>
	<footnote>
		<text>Сноска2</text>
	</footnote>
	<footnote>
		<text>Сноска3</text>
	</footnote>
</footnotes>
такое:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
<footnotes>
	<footnote>
		<text>Сноска1</text>
	</footnote>
	<footnote>
		<text>сноска сноски1</text>
	</footnote>
	<footnote>
		<text>Сноска2</text>
	</footnote>
	<footnote>
		<text>Сноска3</text>
	</footnote>
</footnotes>
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190188
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
refreg

Cовершенно верно.
Сейчас я добился только такого результата, т.е. текст вставляется прямо на место маркёра сноски:
Код: plaintext
1.
2.
3.
4.
5.
6.
<footnotes>
	<footnote>
		<text>Сно</text>
		           <text>сноска сноски1</text>
		<text>ска1</text>
	</footnote>
</footnotes>

Вынести вложенные сноски наверное более корректно, однако такой вариант тоже подойдёт:
Код: plaintext
1.
2.
3.
4.
5.
<footnotes>
	<footnote>
		<text>Сноска1</text>
		<text>сноска сноски1</text>
	</footnote>
</footnotes>
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190202
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kaznelson,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
<xsl:template match="footnotes">
		<footnotes>
			<xsl:for-each select="//footnote">
				<footnote>
					<text>
						<xsl:value-of select="text"/>
					</text>
				</footnote>
			</xsl:for-each>
		</footnotes>
</xsl:template>
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190303
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
refreg,

Псмотрел, но не понял как прикрутить к шаблону. Элемента <footnotes > в трансформации нет, а результирующий *.docbook с вложенными сносками выглядит так:
Код: plaintext
<footnote id="n_7">Текст первой<footnote id="n_16">Текст второй сноски.</footnote> сноски.</footnote>
Процессор XSL-FO по идее с этим должен сам разбираться, но FOP - не умеет.
По сути всё, что я могу сделать, происходит в a_footnote_in ...

PS: note-link задаётся в начале шаблона:
Код: plaintext
<xsl:key name="note-link" match="fb:section" use="@id"/>
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190333
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kaznelson,

xml
Код: plaintext
1.
2.
3.
4.
<footnotes>
	<footnote>Сноcка1</footnote>
	<footnote id="n_7">Текст первой<footnote id="n_16">Текст второй сноски.</footnote> сноски.</footnote>
	<footnote>Сноска2</footnote>
</footnotes>
xsl
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:template match="footnotes">
		<footnotes>
			<xsl:for-each select="//footnote">
				<footnote>
					<text>
						<xsl:apply-templates select="text()"/>
					</text>
				</footnote>
			</xsl:for-each>
		</footnotes>
	</xsl:template>
	<!-- -->
	<xsl:template match="text()">
		<xsl:copy/>
	</xsl:template>
</xsl:stylesheet>
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190350
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или так, если хочется рекурсии (второй вариант)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:template match="footnotes">
		<footnotes>
			<xsl:for-each select="footnote">
				<footnote>
					<xsl:apply-templates select="."/>
				</footnote>
			</xsl:for-each>
		</footnotes>
	</xsl:template>
	<!-- -->
	<xsl:template match="footnote">
		<text>
			<xsl:apply-templates select="text()"/>
		</text>
		<xsl:apply-templates select="footnote"/>
	</xsl:template>
	<!-- -->
	<xsl:template match="text()">
		<xsl:copy/>
	</xsl:template>
</xsl:stylesheet>
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190435
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
refreg,

Так не получается, по крайней мере у меня. :(

Давайте я попробую объяснить, как работает этот шайтан-конвертер.

Дело в том, что элемента <footnote> в схеме FB2 нету. Есть специальный тип тела <body name="notes "> и ссылки вида <a l:href="#n_18" type="note ">[18]</a>, ведущие на элементы <section id="n_18"> в этом теле.

Конвертер с этим телом работает просто - выдёргивает секции со сносками а само тело удаляет. Так что обрабатывать пакетно вероятно не получится, т.к. нечего.

Соответственно <footnote> появляются непосредственно в процессе трансформации в *.docbook, в приведённом мной куске шаблона (а именно - в <xsl:template name="a_footnote"> ).
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190472
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kaznelson,

Ну, приведите исходный xml, и результирующий xml - маленький пример, решение которого дало бы ответ: как сделать вашу реальную задачу.
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190586
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
refreg,
Вот архив: http://rghost.ru/4998268

fb2docbook.xsl - шаблон трансформаций, где сейчас сноски в сносках заменяются на текст в сносках;
___Test.fb2 - тестовая книга с вложенными сносками;
1___Test.fb2.docbook - готовый файл docbook со сносками в сносках, на которых FOP валится;
2___Test.fb2.docbook - готовый файл с заменёнными на текст сносками, сделаный через приложенный fb2docbook.xsl .

Могу дать здесь как листинги, если так будет удобнее...
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190737
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kaznelson,

Ясно... Видимо, все таки лучше "сноску в сноске" писать в этой же сноске с новой строки (можно звездочку поставить перед началом такой сноски). Может, вечером гляну, если никто не поможет к этому времени. Навскидку, 10445988 - этот вариант те поможет
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37190835
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
refreg,

ОК, буду ждать.
авторвсе таки лучше "сноску в сноске" писать в этой же сноске с новой строки В общем да, только наверное придётся как-то расширять шаблон <xsl:template name="a_footnote"> , чтобы он понимал сноски в сносках и мог их перемещать...

Если что - вот весь конвертер, 33 Мб: fb2docbook_kdx.7z
Кроме Java ему ничего не надо, распаковать куда угодно и запустить confsetup.ехе .
Тестовый FB2 в комплекте есть со сноской в сноске (глава "Цитаты"), достаточно перетащить на btransformer.cmd ...
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37191128
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kaznelson,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:key name="foot_notes" use="@id" match="/FictionBook/body[@name='notes']/section"/>
	<!-- -->
	<xsl:template match="/">
		<book>
			<chapter>
				<xsl:apply-templates select="/FictionBook/body[not(@name)]/section/p" mode="txt"/>
			</chapter>
		</book>
	</xsl:template>
	<!-- -->
	<xsl:template match="p" mode="txt">
		<para>
			<xsl:apply-templates select="node()" mode="para"/>
		</para>
	</xsl:template>
	<!-- -->
	<xsl:template match="*" mode="para">
		<xsl:choose>
			<xsl:when test="name()='a'">
				<xsl:value-of select="."/>
				<footnote>
					<xsl:call-template name="snoska">
						<xsl:with-param name="id_snoska" select="substring(@href,2)"/>
					</xsl:call-template>
				</footnote>
			</xsl:when>
			<xsl:otherwise>
				<xsl:copy-of select="."/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- -->
	<xsl:template match="text()" mode="para">
		<xsl:copy/>
	</xsl:template>
	<!-- -->
	<xsl:template name="snoska">
		<xsl:param name="id_snoska" select="0"/>
		<xsl:for-each select="/FictionBook/body/section[@id=$id_snoska]/p/node()">
			<xsl:choose>
				<xsl:when test="name()='a'">
					<xsl:value-of select="."/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:copy-of select="."/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:for-each>
		<xsl:for-each select="/FictionBook/body/section[@id=$id_snoska]/p/a">
			<para>
				<xsl:value-of select="."/>
				<xsl:call-template name="snoska">
					<xsl:with-param name="id_snoska" select="substring(@href,2)"/>
				</xsl:call-template>
			</para>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>
Надеюсь, поможет...
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37192045
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
refreg,

К сожалению, не получается.
...
Рейтинг: 0 / 0
Как перенести элемент на уровень выше с помощью XSLT?
    #37192074
kaznelson
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если я выхожу за пределы шаблоша <xsl:template name="a_footnote"> , то рушится обработка других элементов. А сам a_footnote обрабатывает только одну ссылку, полученную из цикла <xsl:template match="fb:a"> , и прикрепить вложенную ссылку в произвольное место вышестоящей не выходит...
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Как перенести элемент на уровень выше с помощью XSLT?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]