2016-03-03 3 views
1

У меня есть XML-документ, который выглядит примерно так:Вставка изображения при первом появлении

<chapter> 
    <para>Just a random text<cross-ref refid="1234">Abb. 1.0</cross-ref>Some more text</para> 
    <section-title>Title</section-title> 
    <para>and more text text ext<cross-ref refif="1234">Abb 1.0</cross-ref>more more more</para> 
</chapter> 

Как вы можете видеть, что есть два cross-ref элементов внутри абзацев. Они могут встречаться в основном повсюду и несколько идентифицированы их refid (но не однозначно). То, что я сейчас пытаюсь сделать, - это вставить изображение (основанное на refid) в положение первого появления, сохраняя текст в виде заголовка. Каждое другое событие (которое не является первым) должно быть просто встроенными текстами, содержащими внутреннюю базовую ссылку на вставленное изображение. Мое текущее решение:

<xsl:template match="cross-ref"> 
    <xsl:choose> 
     <xsl:when test="position() = 1"> 
     <fo:block text-align="center" id="{@refid}"> 
      <xsl:variable name="refVar" select="@refid"/> 
      <xsl:variable name="imageName" select="/chapter/floats/figure[@id=$refVar]/link/@locator" /> 
      <fo:external-graphic src="url({concat($imageName, '.jpg')})" /> 
      <fo:block text-align="center" xsl:use-attribute-sets="lit-para"> 
      <xsl:value-of select="current()" /> 
      </fo:block> 
     </fo:block> 
     </xsl:when> 

     <xsl:otherwise> 
     <fo:basic-link internal-destination="{@refid}"> 
      <xsl:value-of select="current()" /> 
     </fo:basic-link> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

Это делает работу на некоторых случаях, но так как position() не всегда 1 часть изображения не будут вставлены правильно. Какие у меня варианты? Спасибо!

EDIT: Я должен уточнить. Изображение должно быть вставлено при первом появлении «нового» refid. Таким образом. Каждый refid имеет только одно изображение и любой другой cross-ref элемент с теми же refid указывает, что изображение

ответ

1

Вы должны изменить тест в вашем xsl:when, так что это справедливо только для первого вхождения каждого @ref-id значения; Другими словами, вы должны проверить, что ни один предшествующий cross-ref элемент не имеет тот же @ref-id:

<xsl:when test="not(preceding::cross-ref[@ref-id = current()/@ref_id])"> 
... 
+0

Это сработало отлично. Другой вопрос, если у вас есть время: знаете ли вы, как добавить изображение к родительскому (или к концу текущего блока) текущего выбранного элемента, а не просто прямо в текущую позицию (то есть внутри текста). – puelo

+1

В StackOverlow , вы должны открыть новый вопрос, чтобы задать что-то новое. Не расширяйте свой текущий вопрос с большим количеством вопросов. Это сайт, где люди учатся из других вопросов, и ваш второй вопрос никогда не будет найден. –

1

При использовании XSLT 2.0 или XSLT 3.0, если добавить xsl:key в качестве верхнего уровня элемента:

<xsl:key name="cross-ref" match="cross-ref" use="@refid" /> 

, то вы можете изменить ваш xsl:when на:

<xsl:when test=". is key('cross-ref', @refid)[1]"> 

Это работает, потому что key() возвращает узлы в документ (https://www.w3.org/TR/xslt20/#keys). Это потенциально быстрее (на больших документах), чем с использованием оси preceding, но, конечно, вам придется протестировать его, выполнив ваши документы с помощью вашего XSLT-процессора.

Если вы используете XSLT 1.0, вы должны сделать это с помощью Meunchian Группирование-подобный трюк:

<xsl:when test="count(. | key('cross-ref', @refid)[1]) = 1"> 

но гораздо менее читабельным, чем XSLT версии 2.0.