如何在xslt中将元素插入到已标识的元素中?

时间:2017-01-30 11:08:59

标签: xslt insert element

我有一个具有复杂层次结构的XML文件,我将其与文档fileName.xml一起复制。我想在其他元素中插入一个新元素。目标元素基于带concat('b_',$id)的输入文件计算。

例如 fileName.xml

<root>
 <transform id="b_0">
  <transform id="b_1">
   <transform id="b_2">
    <transform id="b_3"/>
    <transform id="b_4"/>
   </transform>
  </transform>
 </transform>
</root>

这是结果文档的示例:

<root>
 <transform id="b_0">
  <transform id="obj_1"/>
  <transform id="b_1">
   <transform id="b_2">
    <transform id="b_3">
     <transform id="obj_2"/>
    </transform>
    <transform id="b_4"/>
   </transform>
  </transform>
 </transform>
</root>

我的xslt代码模式:

<xsl:variable name="transforms" select="document('fileName.xml')"/>
<xsl:variable name="table" select="."/>  
<xsl:template match="tr"> 
  <xsl:variable name="param" select="$table//tr/td[2]"/>  
  <xsl:variable name="id" select="concat('b_',$param)"/> 
  <xsl:copy-of select="$transforms"/>
  <xsl:copy>
   <Transform> 
    <xsl:attribute name="id"><xsl:value-of select="concat('obj_', position())"/></xsl:attribute>
    <xsl:apply-templates select="$transforms/transform[@id = $id]"/> 
   </Transform>  
  </xsl:copy>
</xsl:template>

1 个答案:

答案 0 :(得分:0)

首先,很难理解你想要实现的目标,你没有向变换显示输入(尽管从标签名称“table”,“tr”,“td”,I'我猜一个html格式的表格。)

您似乎对某些xslt概念感到困惑:

  • xsl:copy-of - 标记将节点集(在您的情况下:$transforms - 变量的内容)复制到输出
  • xsl:copy - 标记将当前标记(在您的情况下为tr - 标记,因为这是模板匹配的内容)复制到输出

另外,请注意:

  • position()将返回当前节点(您的tr)在其父级内的相对位置,也许这​​就是您想要的,也许不是
  • $transforms/transform[@id=$id]仅匹配transform顶层的$transforms个元素。如果要匹配任何级别的元素,请使用双斜杠//

现在,为了转换您指定的$transform - 变量的内容,在您指定的元素中插入新元素,您必须创建:

  • 身份转换复制输入到输出
  • 除非标签是您要查找的标签,在这种情况下,您插入新元素然后复制

由于您要查找的标记是动态的,基于$id - 变量,因此必须将其作为参数传递。根据你的代码,我想你想在@id=$id元素中插入一个新元素作为以下兄弟。

您可以使用以下方法创建此类转换:

<xsl:template match="node()" mode="tx">
    <!-- parameters controlling behaviour as input -->
    <xsl:param name="id" />
    <xsl:param name="pos" />
    <!-- copies the current node -->
    <xsl:copy>
        <!-- copies attributes of the current node -->
        <xsl:copy-of select="@*" />
        <!-- if the next sibling with tag transform has id=$id, insert a new element -->
        <xsl:if test="following-sibling::transform[position()=1 and @id=$id]">
            <transform>
                <xsl:attribute name="id">
                    <xsl:value-of select="concat('obj_', $pos)" />
                </xsl:attribute>
            </transform>
        </xsl:if>

        <!-- call recursively, make sure to include the parameters -->
        <xsl:apply-templates select="node()" mode="tx">
          <xsl:with-param name="id"  select="$id"/>
          <xsl:with-param name="pos" select="$pos" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

请注意,我在此变换上设置mode以便能够控制何时调用它(我只是希望在特定情况下调用它,而不是在所有输入上调用)。

这可以通过变换匹配tr调用,如下所示:

<xsl:template match="tr"> 
  <xsl:variable name="param" select="$table//tr/td[2]" />  
  <xsl:variable name="id" select="concat('b_',$param)" />

  <xsl:apply-templates select="$transforms" mode="tx">
      <xsl:with-param name="id"  select="$id"/>
      <xsl:with-param name="pos" select="position()" />
  </xsl:apply-templates>
</xsl:template>

此处提供了一个完整的示例:http://xsltransform.net/bwdwsA/1