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

如何将元素插入xslt中已标识的元素中?,xslt,insert,element,Xslt,Insert,Element,我有一个具有复杂层次结构的XML文件,我用documentfileName.XML复制它。我想在其他元素中插入一个新元素。基于输入文件计算的目标元素,带有concat('b_',$id) 例如fileName.xml: <root> <transform id="b_0"> <transform id="b_1"> <transform id="b_2"> <transform id="b_3"/> <

我有一个具有复杂层次结构的XML文件,我用document
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>

首先,很难理解您要实现的目标,您没有显示要转换的输入(尽管从标记名“table”、“tr”、“td”,我猜是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>
此处提供了一个完整的工作示例:

<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>