使用XSLT

问题描述:

在特定点添加XML节点我有以下的XML和要插入额外的XML到它:使用XSLT

<root> 
    <steps> 
     <step name="step1" type="process"> 
      <steps> 
       <step name="substep1"> 
       </step> 
      </steps> 
     </step> 
     <step name="step2" type="process"> 
      <steps> 
       <step name="substep1"> 
       <!-- more substeps...--> 
       </step> 
      </steps> 
     </step> 
     <step name="step3" type="process"> 
      <steps> 
       <step name="substep1"> 
       </step> 
       <step name="substep2"> 
       </step> 
       <!-- more substeps...--> 
      </steps> 
     </step> 
     <!-- THE BELOW IS WHAT I WISH TO ADD... and it has to be here --> 
     <step name="reference"> 
      <!-- These stuff have been hardcoded in my xsl so its fine --> 
     </step> 
     <!-- ends --> 
    </steps> 
    <references> 
     <reference name="reference1"> 
     </reference> 
     . 
     . 
     . 
    </references> 
</root> 

正如我写的XML样本中,我想添加一个额外的步骤元素是外部大多数步骤中的最后一步。我的xml片段已经在我的xsl中硬编码了,所以我需要做的就是找到移动到xml树的特定点的最佳逻辑,以便我可以调用模板并添加snipet。是推荐/最好的方法来做到这一点?

谢谢。

+0

好问题(+1)。查看我的答案,获得完整而简单的解决方案 - 详细解释。 :) – 2010-08-13 02:53:57

这种转变

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

<xsl:param name="pAddition"> 
    <step name="reference"> 
    <XXX/> 
    </step> 
</xsl:param> 

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

<xsl:template match="/*/steps/step[position()=last()]"> 
    <xsl:call-template name="identity"/> 
    <xsl:copy-of select="$pAddition"/> 
</xsl:template> 
</xsl:stylesheet> 

当这个XML文档施加:

<root> 
    <steps> 
     <step name="step1" type="process"> 
      <steps> 
       <step name="substep1"> 
       </step> 
      </steps> 
     </step> 
     <step name="step2" type="process"> 
      <steps> 
       <step name="substep1"> 
       <!-- more substeps...--> 
       </step> 
      </steps> 
     </step> 
     <step name="step3" type="process"> 
      <steps> 
       <step name="substep1"> 
       </step> 
       <step name="substep2"> 
       </step> 
       <!-- more substeps...--> 
      </steps> 
     </step> 
    </steps> 
    <references> 
     <reference name="reference1"> 
     </reference> 
     . 
     . 
     . 
    </references> 
</root> 

产生想要的,正确的结果

<root> 
    <steps> 
     <step name="step1" type="process"> 
     <steps> 
      <step name="substep1"/> 
     </steps> 
     </step> 
     <step name="step2" type="process"> 
     <steps> 
      <step name="substep1"><!-- more substeps...--></step> 
     </steps> 
     </step> 
     <step name="step3" type="process"> 
     <steps> 
      <step name="substep1"/> 
      <step name="substep2"/><!-- more substeps...--> 
     </steps> 
     </step> 
     <step name="reference"> 
     <XXX/> 
     </step> 
    </steps> 
    <references> 
     <reference name="reference1"/> 
     . 
     . 
     . 
    </references> 
</root> 

请注意

  1. **的身份规则用于复制的所有节点不变。

  2. 要插入的XML片段是作为全局xsl:param的主体指定的(为了方便起见)。在一个实际的应用程序中,它将在一个单独的xml文件中,并将使用xslt document()函数获取。

  3. 匹配插入点的模板通过调用标识规则来复制匹配的节点。那么它会复制xsl:param的内容,因此新的conted将在所需的插入点准确输出。

+0

+1很好的答案。我就是这样做的。但我认为只复制参数RTF会更容易。 – 2010-08-13 13:27:59

+0

@Alejandro:嘿,+1 :)在哪里?至于文字复制 - 是的,但你和我都很清楚我们应用模板来实现灵活性 - 明天有人可能会要求对参数内容进行一些处理。 – 2010-08-13 13:32:54

+0

@Alejandro:其实,你是对的。我简化了很多转换 - 请参阅编辑。 Jae! – 2010-08-13 14:38:29