Тег заголовка на основе позиции в xml

Я хотел бы создать тег от h1 до h3 для заголовка на основе позиции его раздела.

xml находится в формате

<sections>
        <section>
            <header>section 1 header</header>
            <image alt="section 1 image alt">imagename.filetype</image>
            <content>section 1 content</content>
        </section>
        <section>
            <header>section 2 header</header>
            <image alt="section 2 image alt">imagename.filetype</image>
            <content>section 2 content</content>
        </section>
        <section>
            <header>section 3 header</header>
            <image alt="section 3 image alt">imagename.filetype</image>
            <content>section 3 content</content>
        </section>
    </sections>

мой вывод хотел бы быть похожим

<div>
<h1> section 1 header</h1>
<img alt="section 1 image alt" src="imagename.filename"/>
section 1 content
</div>

<div>
<h2> section 2 header</h2>
<img alt="section 2 image alt" src="imagename.filename"/>
section 2 content
</div>

<div>
<h3> section 3 header</h3>
<img alt="section 3 image alt" src="imagename.filename"/>
section 3 content
</div>

есть ли простой способ сделать это? любые идеи приветствуются!

любезное спасибо

Обновить:

<xsl:template mode="section" match="section">    
        <xsl:apply-templates mode="header" select="header">
            <xsl:with-param name="position">h<xsl:value-of select="position()"/></xsl:with-param>
        </xsl:apply-templates>   
        <img alt="{image/@alt}" src="{image}" />
        <xsl:value-of select="content"/>
    </xsl:template>

    <xsl:template mode="header" match="header">  
    <xsl:param name="position">0</xsl:param>  
        <xsl:element name="{$position}"><xsl:value-of select="."/></xsl:element>    
    </xsl:template>  

используя приведенный выше xslt, который является слегка обновленной версией поста хачика


person Treemonkey    schedule 12.12.2010    source источник
comment
Хороший вопрос, +1. См. мой ответ для полного решения, которое полностью соответствует духу XSLT (стиль push). :)   -  person Dimitre Novatchev    schedule 12.12.2010


Ответы (2)


Вот полное решение, полностью выполненное в стиле push:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="section">
  <div>
   <xsl:apply-templates/>
  </div>
 </xsl:template>

 <xsl:template match="header">
  <xsl:element name="h{count(../preceding-sibling::section)+1}">
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>
 <xsl:template match="sections|content">
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному XML-документу:

<sections>
    <section>
        <header>section 1 header</header>
        <image alt="section 1 image alt">imagename.filetype</image>
        <content>section 1 content</content>
    </section>
    <section>
        <header>section 2 header</header>
        <image alt="section 2 image alt">imagename.filetype</image>
        <content>section 2 content</content>
    </section>
    <section>
        <header>section 3 header</header>
        <image alt="section 3 image alt">imagename.filetype</image>
        <content>section 3 content</content>
    </section>
</sections>

получен желаемый правильный результат:

    <div>
       <h1>section 1 header</h1>
       <image alt="section 1 image alt">imagename.filetype</image>
section 1 content
    </div>
    <div>
       <h2>section 2 header</h2>
       <image alt="section 2 image alt">imagename.filetype</image>
section 2 content
    </div>
    <div>
       <h3>section 3 header</h3>
       <image alt="section 3 image alt">imagename.filetype</image>
section 3 content
    </div>
person Dimitre Novatchev    schedule 12.12.2010
comment
Спасибо за это именно то, что мне было нужно!, пока не понимаю, но разберусь. ах, так что он считает заголовки перед добавлением 1. понял, спасибо, Димитр - person Treemonkey; 12.12.2010
comment
+1 Хороший ответ. Это будет точно соответствовать желаемому результату, добавив правило для image и даже отбросив правило отождествления и правило, перезаписывающее встроенное правило для элементов. - person ; 13.12.2010

Это не ответ, так как он выглядит некрасиво, но слишком длинный для комментария. Я не уверен, что это лучший способ сделать это, но:

<xsl:template match="section">
    <xsl:apply-templates select="./header">
        <xsl:with-param name="position"><xsl:value-of select="position()"/>
         </xsl:with-param>
    </xsl:apply-templates>
    <!-- section stuff here -->
</xsl:template>

<xsl:template match="header">
    <xsl:param name="position">0</xsl:param>
    <xsl:variable name="tagname"><xsl:value-of select="concat('h', $position)"></xsl:value-of></xsl:variable>
    <xsl:element name="{$tagname}"><xsl:value-of select="."/></xsl:element>
</xsl:template>

Примечание: я не думаю, что направление в зависимости от позиции — хорошая идея. DocBook и другие языки используют уровень раздела для размещения соответствующего тега заголовка.

person khachik    schedule 12.12.2010
comment
это похоже на мою первоначальную идею, можете попробовать с небольшим редактированием :) - person Treemonkey; 12.12.2010