2013-07-15 5 views
0

Используя Apache FOP, я хочу собрать некоторую информацию в файле PDF. Источник XML имеет некоторые дочерние узлы a, e, скажемXSLT для последовательности дочерних узлов в FOP

<node> 
    <a>some val</a> 
    <b>some other val</b> 
    <c>more val</c> 
    <d>even more val</d> 
    <e>a last val</e> 
</node> 

Я не хочу отображать их все. a, b, c всегда отображаются, но могут быть emtpy. Максимальное количество отображаемых значений равно 3. Итак, d и e являются необязательными и должны храниться в указанном порядке.

К сожалению, структура XML не может быть изменена.

Для чего нужен XSLT? Я попробовал

<xsl:for-each select="child::*[name()='a' or name() = 'b' or name() = 'c' or name() = 'd' or name() = 'e'][string-length(.)&gt;0]"> 
    <xsl:if test="position() &lt;= 3"> 
     <xsl:value-of select="name()"/> 
    </xsl:if> 
</xsl:for-each> 

но это не приносит мне упорядоченный список. . :(

+0

Возможно использование Apache FOP с Saxon 9 для использования XSLT 2.0, я думаю. И с XSLT 2.0 вы можете просто записать заказ, который вы хотите, например. '

+0

a, b, c может быть пустым. .. –

+0

Фрагмент '

ответ

1

<xsl:sort /> должен

ГПУ

В вашем случае это будет:

<xsl:sort select="name()"/> 

Поэтому попробуйте:

<xsl:for-each select="child::*[name()='a' or name() = 'b' or name() = 'c' or name() = 'd' or name() = 'e'][string-length(.)&gt;0]"> 
     <xsl:sort select="name()"/> 
     <xsl:if test="position() &lt;= 3"> 
      <xsl:value-of select="name()"/> 
     </xsl:if> 
    </xsl:for-each> 

Обновление: Поскольку в реальном входном XML там жить не полезная информация для сортировки, вы можете добавить некоторую метаинформацию. Где хранить метаинформацию зависят от возможностей процессора xslt.

Если вы можете использовать набор узлов() расширение, которое вы можете попробовать что-то вроде этого:

Добавить переменный в таблице стилей с ожидаемым порядком.

xsl:variable name="myOrder"> 
     <order name="a" pos="1" /> 
     <order name="b" pos="3" /> 
     <order name="c" pos="2" /> 
     <order name="d" pos="4" /> 
     <order name="e" pos="5" /> 
    </xsl:variable> 

Сделать эту переменную можно использовать как набор узлов с помощью:

<xsl:variable name="Order" select="exsl:node-set($myOrder)" /> 

Сортировка с помощью этой переменной.

<xsl:sort select="$Order/order[@name= name(current())]/@pos"/> 
+0

Спасибо, это помогло бы, если бы я был упростить код примера. *г*. На самом деле имена узлов: a = Lagerort, b = Abteilung, c = Kostenstelle, d = Mitarbeiter, e = Lieferant. Так что естественного порядка я не могу здесь. –

+0

Итак, правильный ответ за неправильный вопрос? ;-) XSLT-1.0 или 2.0 и т. Д.? И узлы не находятся в правильном порядке во входном XML? –

+0

Я не знаком с FOP. Можете ли вы использовать расширение, подобное node-set()? Или Если вы не можете добавить некоторые метаданные в свой XML-файл, который содержит сопоставление от имени к позиции? –

1

@Florian Рух, ваше заявленная требование не является самосогласованной: «Я не хочу, чтобы отобразить все из них, б, должна всегда отображаться максимальное количество отображаемых значений 3.. Таким образом, d и e являются необязательными и должны храниться в этом порядке ».

Если индикаторы a, b и c всегда отображаются, а максимальное количество отображаемых значений равно 3, тогда нет возможности отобразить d и 3.

Просьба уточнить ваше требование.

Обратите внимание, что это очень плохая форма использования функции name(), как и у вас.

Эквивалент:

<xsl:for-each select="child::*[name()='a' or name() = 'b' or name() = 'c' or name() = 'd' or name() = 'e'][string-length(.)&gt;0]"> 

является:

<xsl:for-each select="(a|b|c|d|e)[string(.)]"> 

... и подход, который я постулировать пространством имен безопасно, в то время как подход вы использовали не так.

+0

Спасибо за отзыв. Да, я не упоминал, что а может быть пустым. –

+0

Благодарим вас за безопасность пространства имен! :) Я последую за этим! –

0

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

<xsl:template match="node"> 
<fo:list-block> 
<xsl:apply-templates/> 
</fo:list-block> 
</xsl:template> 

И

<xsl:template match="node/*[4] | node/*[5]"/> 
<xsl:template match="node/*[1] | node/*[2] | node/*[3]"> 
<fo:list-item> 
<fo:list-item-label> 
<fo:block><xsl:value-of select="position()"/></fo:block> 
</fo:list-item-label> 
<fo:list-item-body> 
<fo:block><xsl:value-of select="."/></fo:block> 
</fo:list-item-body> 
</fo:list-item> 
</xsl:template> 

Это игнорирует любые 4-й и 5-й элементы, но обрабатывает первый, второй и третий порядок документа (так как это порядок, в котором они встречаются).

+0

Спасибо за этот ответ. Хорошая идея игнорировать 4-й и 5-й элементы таким образом. Однако список, который у меня есть, не упорядочен, и элементы могут быть пустыми. –

Смежные вопросы