XSLT с перекрывающимися элементами? - PullRequest
3 голосов
/ 16 августа 2010

Так что название этого поста может вводить в заблуждение, но это лучшее, что я могу придумать.Я работаю над проектом, который использует TEI для кодирования текстов.Одним из требований моей текущей работы является написание XSL-преобразований для отображения XML-кодированных текстов в виде HTML.По большей части, нет проблем.Я как бы застрял в этом вопросе:

    <l>There is <delSpan spanTo="A1"/>deleted text spanning</l>
    <l>multiple lines here.<anchor xml:id="A1"/> More text...</l>

Или, в других случаях:

    <delSpan spanTo="A2"/>
    <l>Several deleted lines -- the delspan marker can appear </l>
    <l>outside of an l element.... </l>
    <anchor xml:id="A2"/>

(Если вы не знакомы с TEI: l = aстрока текста; delSpan = диапазон удаленного текста, который содержит более 1 строки, страницы или меньшего блока.)

Цель состоит в том, чтобы отобразить текст между delSpan (A1) и его соответствующим якорем (A1)- «удаленный текстовый охват / несколько строк здесь» - с некоторым форматированием, которое указывает на удаление (например, text-художественное оформление = «сквозной»).Прямо сейчас есть шаблон для элементов "l", который обрабатывает большинство форматирования текста - или, по крайней мере, вызывает другие шаблоны для этого.

Но эти одноэлементные метки являются аномалией;все остальное форматирование / разметка выполняется с помощью тегов, которые фактически содержат текст, который они должны отформатировать.Прав ли я, предполагая, что мне нужно обработать элементы delSpan и anchor в шаблоне "l"?Какой самый элегантный способ решения этой проблемы и обработки псевдоперекрывающихся элементов?

Извините, если это нубский вопрос или я не предоставил достаточно информации.Я в основном программист на C / C ++ с небольшим опытом работы с XSLT, поэтому я ценю любые предложения.

Ответы [ 2 ]

2 голосов
/ 16 августа 2010

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="delSpan|anchor"/>
    <xsl:template match="text()[preceding::delSpan[1]/@spanTo=following::anchor[1]/@xml:id]">
        <span style="text-decoration:line-through;">
            <xsl:value-of select="."/>
        </span>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<doc>
    <l>There is <span style="text-decoration:line-through;">deleted text spanning</span></l>
    <l><span style="text-decoration:line-through;">multiple lines here.</span> More text...</l>
</doc>

Примечание : использование предыдущей и следующей оси и их значение в порядке документа.Мы не перезаписываем любые предыдущие шаблоны, соответствующие l элементам.delSpan и anchor также не могут быть полосатыми.

1 голос
/ 16 августа 2010

Ваша главная проблема здесь заключается в том, что элементы delSpan не являются родителями, а его завершающий и закрывающий "элемент" является пустым элементом (anchor для закрытия). Связь между открытием и закрытием осуществляется путем ссылки на тег xml:id.

Существует несколько решений этой проблемы, вот одно из них, если вы используете XSLT 1.0 (с XSLT 2.0 это намного проще). Идея проста: найти всех братьев и сестер и применить их, но только если они сами сопровождаются братом anchor с правильным xml:id:

<xsl:template match="delSpan">
   <xsl:variable select="@spanTo" name="spanTo" />
   <xsl:apply-templates select="following-sibling::*[following-sibling::anchor[@xml:id = $spanTo]" mode="deleted" />
</xsl:template>

<!--
     do this for all elements you need to treat inside delSpan
     if they have children, remember to use apply-templates with mode deleted
 -->
<xsl:template match="l" mode="deleted">
   <strike><xsl:value-of select="." /></strike>
</xsl:template>

Я не уверен на 100%, что это совершенно правильно. Это может пойти не так, если <delSpan> может быть вложенным. Если вам повезет, Дмитрий Новачев пройдет мимо и тоже посмотрит.

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