XSLT — добавить родственный элемент

Я пытаюсь использовать XSLT, чтобы добавить context-param в качестве последнего брата. Нет общего родительского элемента, поэтому задача немного сложнее.

Я хотел бы добавить следующий элемент:

<context-param>
    <param-name>miku</param-name>
    <param-value>kawaii</param-value>
</context-param>

как последний элемент context-param (например, все элементы context-param должны быть рядом друг с другом, они не могут быть разбросаны где-либо в xml) в следующем xml:

<web-app>
  <not_interesting_element1/>
  <not_interesting_element2/>

  <context-param>
    <param-name>not_interesting_param_key1</param-name>
    <param-value>kawaii</param-value>
  </context-param>
  <context-param>
    <param-name>not_interesting_param_key2</param-name>
    <param-value>kawaii</param-value>
  </context-param>
  <context-param>
    <param-name>parameterThatsGuaranteedToBeHere</param-name>
    <param-value>someValue</param-value>
  </context-param>


  <not_interesting_element3/>
  <not_interesting_element4/>
  <!-- ... servlets, ... -->
</web-app>

Результат должен выглядеть так:

<web-app>
  <not_interesting_element1/>
  <not_interesting_element2/>

  <context-param>
    <param-name>not_interesting_param_key1</param-name>
    <param-value>kawaii</param-value>
  </context-param>
  <context-param>
    <param-name>not_interesting_param_key2</param-name>
    <param-value>kawaii</param-value>
  </context-param>
  <context-param>
    <param-name>parameterThatsGuaranteedToBeHere</param-name>
    <param-value>someValue</param-value>
  </context-param>
  <context-param>
      <param-name>miku</param-name>
      <param-value>kawaii</param-value>
  </context-param>

  <not_interesting_element3/>
  <not_interesting_element4/>
  <!-- ... servlets, ... -->
</web-app>

Как я могу это сделать, пожалуйста?


person woky    schedule 19.04.2012    source источник
comment
Присоединиться к чему? Пожалуйста, отредактируйте вопрос и предоставьте XML-документ и конкретные одноуровневые узлы, к которым вы хотите добавить элемент context-param. Тогда сообщите мне через комментарий.   -  person Dimitre Novatchev    schedule 19.04.2012
comment
Пожалуйста, разместите образцы ввода и желаемого вывода XML, иллюстрирующие проблему.   -  person Martin Honnen    schedule 19.04.2012
comment
@Dimitre Novatchev: Вопрос обновлен.   -  person woky    schedule 19.04.2012


Ответы (1)


Это преобразование:

<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:param name="pElemToAdd">
    <context-param>
        <param-name>miku</param-name>
        <param-value>kawaii</param-value>
    </context-param>
 </xsl:param>

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

 <xsl:template match="context-param[last()]">
  <xsl:call-template name="identity"/>
  <xsl:copy-of select="$pElemToAdd"/>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному XML-документу:

<web-app>
    <not_interesting_element1/>
    <not_interesting_element2/>
    <context-param>
        <param-name>not_interesting_param_key1</param-name>
        <param-value>kawaii</param-value>
    </context-param>
    <context-param>
        <param-name>not_interesting_param_key2</param-name>
        <param-value>kawaii</param-value>
    </context-param>
    <context-param>
        <param-name>parameterThatsGuaranteedToBeHere</param-name>
        <param-value>someValue</param-value>
    </context-param>
    <not_interesting_element3/>
    <not_interesting_element4/>
    <!-- ... servlets, ... -->
</web-app>

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

<web-app>
   <not_interesting_element1/>
   <not_interesting_element2/>
   <context-param>
      <param-name>not_interesting_param_key1</param-name>
      <param-value>kawaii</param-value>
   </context-param>
   <context-param>
      <param-name>not_interesting_param_key2</param-name>
      <param-value>kawaii</param-value>
   </context-param>
   <context-param>
      <param-name>parameterThatsGuaranteedToBeHere</param-name>
      <param-value>someValue</param-value>
   </context-param>
   <context-param>
      <param-name>miku</param-name>
      <param-value>kawaii</param-value>
   </context-param>
   <not_interesting_element3/>
   <not_interesting_element4/><!-- ... servlets, ... -->
</web-app>

Пояснение:

  1. Правило идентификации копирует каждый узел «как есть».

  2. Существует единственный шаблон, переопределяющий шаблон удостоверения. Этот шаблон соответствует последнему элементу context-param из всех элементов context-param, которые являются дочерними элементами их родителя.

  3. В переопределяющем шаблоне выполняются два действия; текущий узел копируется вызовом правила идентификации; затем добавляемый элемент копируется в вывод. Для удобства и гибкости мы предполагаем, что добавляемый элемент передается преобразованию в качестве параметра.

person Dimitre Novatchev    schedule 19.04.2012
comment
Спасибо. Это работает, если я добавляю один элемент. Если я делаю это неоднократно, добавленный элемент также перезаписывает предыдущий элемент, поэтому похоже, что последний элемент context-path удаляется и добавляются два новых элемента. - person woky; 19.04.2012
comment
@woky: если вы хотите добавить более одного узла, вы должны указать полный набор узлов, который будет добавлен в параметре. - person Dimitre Novatchev; 19.04.2012