поиск предыдущих значений узла xml по имени элемента

#xslt

#xslt

Вопрос:

У меня есть XML-документ в формате follwoing:

 <xml>
<dtd name="formslst">
<XMLDOC>
  <formslst>
    <forms>
      <h1>
        Level 1 heading 
        <h2>
          level 2 heading 
          <h3>
            level 3 heading
            <file>
              file1.pdf
              <title>
                title of file 1
                <file>
                  file2.pdf
                  <title>
                    title of file2
                       <h3> level 3 internal heading
                          <file> file2.pdf
                            <title>
                                title of file 3
                             </title>     
                           </file>
                        </h3>
                  </title>
              </file>
            </title>
          </file>
         </h3>
      </h2>
    </h1>
  </forms>
 </formslst>
</XMLDOC>  
  

Мне нужен скрипт xslt, чтобы, если я передам параметр как «file2.pdf», он должен вернуть мне заголовок file2.pdf как «заголовок file2» и предыдущий текст h3 «заголовок уровня 3«, h2 «заголовок уровня 2» и h1 «заголовок уровня 1″значения.

Но если я передам файл file3.pdf, он должен вернуть мне заголовок file3.pdf как «заголовок файла 3» и предшествующие текстовые значения h3 «внутренний заголовок уровня 3«, h2 «заголовок уровня 2» и h1 «заголовок уровня 1».

Ответ №1:

Вы можете сопоставить соответствующий файл, выполнив следующее (где $file — параметр, содержащий ваше имя файла)

 <xsl:apply-templates select="//file[normalize-space(text()) = $file]"/> 
  

После сопоставления файла заголовок получается довольно просто

 <xsl:value-of select="normalize-space(title/text())" />
  

Глядя на структуру xml (которая не правильно сформирована, потому что вы пропускаете закрывающие теги dtd и xml), вам на самом деле нужны не предыдущие элементы h, а предки

 <xsl:apply-templates select="ancestor::h1|ancestor::h2|ancestor::h3">
  

Вот полный XSLT

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:param name="file" select="'file2.pdf'"/>

   <xsl:template match="/">
      <xsl:apply-templates select="//file[normalize-space(text()) = $file]"/>
   </xsl:template>

   <xsl:template match="file">
      <title>
         <xsl:value-of select="normalize-space(title/text())"/>
      </title>
      <xsl:apply-templates select="ancestor::h1|ancestor::h2|ancestor::h3">
         <xsl:sort select="position()" order="descending"/>
      </xsl:apply-templates>
   </xsl:template>

   <xsl:template match="h1|h2|h3">
      <xsl:copy>
         <xsl:value-of select="normalize-space(text())"/>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>
  

При применении к вашему образцу XML возвращается следующее (обратите внимание, что в вашем XML есть два file2.pdf, я предполагаю, что вторым должен быть file3.pdf

 <title>title of file2</title>
<h3>level 3 heading</h3>
<h2>level 2 heading</h2>
<h1>Level 1 heading</h1>
  

При изменении параметра на file3.pdf вывод выглядит следующим образом:

 <title>title of file 3</title>
<h3>level 3 internal heading</h3>
<h3>level 3 heading</h3>
<h2>level 2 heading</h2>
<h1>Level 1 heading</h1>