Переместить элемент xml в другой элемент с помощью xslt - PullRequest
5 голосов
/ 14 апреля 2011

У меня есть XML, который выглядит следующим образом

<executionPlan name="Test" >
<paramList>
    <param name="param1" default=""/>
</paramList>

<varList>
    <var name="bla" default=":[param1]"/>
</varList>

<simpleSteps limitToHostSet="bla">
    <execNative>
        <exec cmd="/bin/sh"/>
    </execNative>
</simpleSteps>

, и мне нужно преобразовать его, чтобы он выглядел следующим образом:

<executionPlan name="Test" >
<paramList>
    <param name="param1" default=""/>
</paramList>

<simpleSteps limitToHostSet="bla">
    <varList>
        <var name="bla" default=":[param1]"/>
    </varList>
    <execNative>
        <exec cmd="/bin/sh"/>
    </execNative>
</simpleSteps>

Как вы можете видеть, элемент varList должен быть вложен в элемент simpleSteps сразу за открывающим тегом.Внутри simpleSteps могут быть другие элементы varList, которые нельзя изменять.

Есть идеи, как этого добиться с помощью XSLT?Я новичок в XSLT и безуспешно пробовал весь день ... Любая помощь будет очень признательна.

Lutz

Ответы [ 2 ]

4 голосов
/ 14 апреля 2011

Следующая таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="varList[following-sibling::*[1][self::simpleSteps]]" />
    <xsl:template match="simpleSteps">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:copy-of select="preceding-sibling::varList[1]" />
            <xsl:apply-templates select="node()" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

На этом входе:

<executionPlan name="Test">
    <paramList>
        <param name="param1" default="" />
    </paramList>
    <varList>
        <var name="bla" default=":[param1]" />
    </varList>
    <varList>
        <var name="bla2" default=":[param2]" />
    </varList>
    <simpleSteps limitToHostSet="bla">
        <execNative>
            <exec cmd="/bin/sh" />
        </execNative>
    </simpleSteps>
</executionPlan>

Производит:

<executionPlan name="Test">
    <paramList>
        <param name="param1" default="" />
    </paramList>
    <varList>
        <var name="bla" default=":[param1]" />
    </varList>
    <simpleSteps limitToHostSet="bla">
        <varList>
            <var name="bla2" default=":[param2]" />
        </varList>
        <execNative>
            <exec cmd="/bin/sh" />
        </execNative>
    </simpleSteps>
</executionPlan>

Редактировать: Тольконепосредственно предшествующий varList перемещается в связанный с ним simpleSteps.Все остальные элементы varList копируются без изменений.

Мне неожиданно неясно, является ли это желаемым поведением, или если внутри элемента simpleSteps уже есть несколько элементов varList, которые должны бытьбез изменений.Смотрите мое оригинальное решение для этого случая:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="varList" />
    <xsl:template match="simpleSteps">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:copy-of select="../varList" />
            <xsl:apply-templates select="node()" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

На этом входе:

<executionPlan name="Test">
    <paramList>
        <param name="param1" default="" />
    </paramList>
    <varList>
        <var name="bla" default=":[param1]" />
    </varList>
    <simpleSteps limitToHostSet="bla">
        <varList>
            <var name="bla7" default=":[param7]" />
        </varList>
        <execNative>
            <exec cmd="/bin/sh" />
        </execNative>
    </simpleSteps>
</executionPlan>

Производит:

<executionPlan name="Test">
    <paramList>
        <param name="param1" default="" />
    </paramList>
    <simpleSteps limitToHostSet="bla">
        <varList>
            <var name="bla" default=":[param1]" />
        </varList>
        <varList>
            <var name="bla7" default=":[param7]" />
        </varList>
        <execNative>
            <exec cmd="/bin/sh" />
        </execNative>
    </simpleSteps>
</executionPlan>
2 голосов
/ 15 апреля 2011

Это более простое и короткое решение :

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

 <xsl:template match="simpleSteps/*[1]">
  <xsl:copy-of select="/*/varList[1]"/>
  <xsl:call-template name="identity"/>
 </xsl:template>

 <xsl:template match="/*/varList[1]"/>
</xsl:stylesheet>

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

<executionPlan name="Test" >
    <paramList>
        <param name="param1" default=""/>
    </paramList>
    <varList>
        <var name="bla" default=":[param1]"/>
    </varList>
    <simpleSteps limitToHostSet="bla">
        <execNative>
            <exec cmd="/bin/sh"/>
        </execNative>
    </simpleSteps>
</executionPlan>

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

<executionPlan name="Test">
   <paramList>
      <param name="param1" default=""/>
   </paramList>
   <simpleSteps limitToHostSet="bla">
      <varList>
         <var name="bla" default=":[param1]"/>
      </varList>
      <execNative>
         <exec cmd="/bin/sh"/>
      </execNative>
   </simpleSteps>
</executionPlan>

Объяснение

  1. Правило идентификации / шаблон копирует каждый узел "как есть". Есть только два исключения, объясненные ниже.

  2. Шаблон переопределения, который соответствует только первому varList дочернему элементу верхнего элемента, не имеет тела - это фактически отменяет действие копирования шаблона идентификации для этого элемента.

  3. Переопределяющий шаблон, соответствующий первому дочернему элементу simpleSteps, выполняет две функции: а) копирует требуемый элемент varList (дочерний элемент верхнего элемента), а затем б) вызывает идентификационный шаблон для скопировать себя в вывод.

...