2012-04-21 5 views
2

Мне нужно обработать атрибуты (любого узла, которые имеют их) в определенном порядке. Например:Атрибуты процесса XSL в порядке

<test> 
    <event 
     era ="modern" 
     year ="1996" 
     quarter = "first" 
     day = "13" 
     month= "January" 
     bcad ="ad" 
     hour ="18" 
     minute = "23" 
     >The big game began.</event> 
    <happening 
     era ="modern" 
     day = "18" 
     bcad ="ad" 
     month= "February" 
     hour ="19" 
     minute = "24" 
     >The big game ended.</happening> 
    <other>Before time existed.</other> 
</test> 

Это

<xsl:template match="test//*"> 
    <div> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates /> 
    </div> 
</xsl:template> 

<xsl:template match="@*"> 
    <span class="{name()}"> 
     <xsl:value-of select="."/> 
    </span> 
</xsl:template> 

бы форматировать вещи, как я нуждаюсь в них. То есть, я получаю

<div><span class="era">modern</span> 
    <span class="year">1996</span> 
    <span class="quarter">first</span> 
    <span class="day">13</span> 
    <span class="month">January</span> 
    <span class="bcad">ad</span> 
    <span class="hour">18</span> 
    <span class="minute">23</span>The big game began.</div> 
<div><span class="era">modern</span> 
    <span class="day">18</span> 
    <span class="bcad">ad</span> 
    <span class="month">February</span> 
    <span class="hour">19</span> 
    <span class="minute">24</span>The big game ended.</div> 
<div>Before time existed.</div> 

(хотя без новой строки я добавил сюда для удобочитаемости).

Но порядок атрибутов не был бы (обязательно) правильным.

Чтобы исправить это, я мог бы изменить <xsl:apply-templates select="@*" /> к <xsl:call-template name="atts" /> и добавить шаблон, который применяет шаблоны в нужном порядке, как это:

<xsl:template match="test//*"> 
    <div> 
     <xsl:call-template name="atts" /> 
     <xsl:apply-templates /> 
    </div> 
</xsl:template> 

<xsl:template name="atts"> 
    <xsl:apply-templates select="@era" /> 
    <xsl:apply-templates select="@bcad" /> 
    <xsl:apply-templates select="@year" /> 
    <xsl:apply-templates select="@quarter" /> 
    <xsl:apply-templates select="@month" /> 
    <xsl:apply-templates select="@day" /> 
    <xsl:apply-templates select="@hour" /> 
    <xsl:apply-templates select="@minute" />   
</xsl:template> 

<xsl:template match="@*"> 
    <span class="{name()}"> 
     <xsl:value-of select="."/> 
    </span> 
</xsl:template> 

Является ли это передовая практика, способ обработки атрибутов в определенном порядке ? Я продолжаю задаваться вопросом, есть ли способ, который использует ключи или глобальную переменную.

Мне нужно использовать XSLT 1.0, а в реальном случае есть несколько десятков атрибутов, а не только восемь.

ответ

1

В отличие от элементов, например, порядок атрибутов не имеет существенного значения в XML, то есть XPath и XSLT могут обрабатывать их в любом порядке. Таким образом, единственный способ заставить данный порядок - указать его каким-то образом. Один из способов - называть их явно, как в вашем последнем примере кода. Вы также можете извлечь все имена атрибутов и сохранить их в отдельном файле XML, например. что-то вроде

<attributes> 
    <attribute>era</attribute> 
    <attribute>year</attribute> 
    <attribute>month</attribute> 
    ... 
<attributes> 

Теперь вы можете загрузить эти элементы с помощью функции документа() и перебор всех атрибутов элементов:

<xsl:variable name="attributes" select="document('attributes.xml')//attribute"/> 
... 
<xsl:template match="*"> 
    <xsl:variable name="self" select="."/> 
    <xsl:for-each select="$attributes"> 
    <xsl:apply-templates select="$self/@*[name()=current()]"/> 
    </xsl:for-each>  
</xsl:template> 
+0

Кроме того, что нет необходимости ставить список атрибутов в отдельный XML-файл - он может и, скорее всего, должен перейти прямо в сам файл XSLT (а затем ссылаться на него с помощью функции document() без аргументов. –

+0

Да, это правильно. Однако я бы не извлекал атрибуты вручную, но напишите таблицу стилей, которая извлекает их из данного XML-файла. Для меня гораздо проще t o сохранить такой список в отдельном файле, а не копировать все в таблицу стилей каждый раз, когда атрибуты будут извлечены и повторно упорядочены. Но это, вероятно, только личное предпочтение. – Martin

+0

@Martin Вы видите, как я могу добавить разделитель между каждым атрибутом? Скажем, шаблон apply просто вернул значение, а атрибуты - месяц, день и год. Я бы хотел «5/16/2012». При вашем подходе я не могу проверить для pos()! = Last(), поскольку эти функции подсчитывают все атрибуты для каждого из них, а не только те, где name() = current(). – JPM

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