Xml XSLT在特定位置添加缺少的节点

Xml XSLT在特定位置添加缺少的节点,xml,xslt,Xml,Xslt,我想在XML中插入一个缺少的节点,以防它丢失。例如,我想在CustomInformation节点之前添加一个节点。我已经编写了下面的XSLT转换,但是CostPlan节点上的属性没有出现。我哪里做错了 样本数据: <CostPlan code="test" periodType="MONTHLY" > <Description/> <GroupingAttributes> <GroupingAttribute>cos

我想在XML中插入一个缺少的节点,以防它丢失。例如,我想在CustomInformation节点之前添加一个
节点。我已经编写了下面的XSLT转换,但是CostPlan节点上的属性没有出现。我哪里做错了

样本数据:

<CostPlan code="test" periodType="MONTHLY" >
    <Description/>
    <GroupingAttributes>
        <GroupingAttribute>cost_type_id</GroupingAttribute>
        <GroupingAttribute>transaction_class_id</GroupingAttribute>
        <GroupingAttribute>charge_code_id</GroupingAttribute>
    </GroupingAttributes>

    <CustomInformation>
        <ColumnValue name="pra">xyz</ColumnValue>
        <ColumnValue name="partition_code">abc</ColumnValue>
    </CustomInformation>
</CostPlan>

成本类型标识
事务\u类\u id
费用代码id
xyz
abc
XSLT转换:

<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="CostPlan[not(Details)]">
         <xsl:variable name="elements-after" select="CustomInformation"/>
      <xsl:copy>
          <xsl:copy-of select="* except $elements-after"/>
          <Details/>
          <xsl:copy-of select="$elements-after"/>
        </xsl:copy>
      </xsl:template>
</xsl:stylesheet>

输出:

<CostPlan> <!-- attributes missing compared to original  -->
   <Description/>
   <GroupingAttributes>
      <GroupingAttribute>cost_type_id</GroupingAttribute>
      <GroupingAttribute>transaction_class_id</GroupingAttribute>
      <GroupingAttribute>charge_code_id</GroupingAttribute>
   </GroupingAttributes>
   <Details/>
   <CustomInformation>
      <ColumnValue name="pra">xyz</ColumnValue>
      <ColumnValue name="partition_code">abc</ColumnValue>
   </CustomInformation>
</CostPlan>

成本类型标识
事务\u类\u id
费用代码id
xyz
abc

好吧,您的模板匹配
成本计划[不(详细信息)]
不会处理属性。更改:

<xsl:copy-of select="* except $elements-after"/>

致:



还要注意,样式表标记为XSLT1.0,但您肯定在使用XSLT2.0

在XSLT 1.0中,您可以这样做:

<xsl:template match="CostPlan[not(Details)]">
    <xsl:copy>
        <xsl:copy-of select="@* | *[not(self::CustomInformation)]"/>
        <Details/>
        <xsl:copy-of select="CustomInformation"/>
    </xsl:copy>
</xsl:template>


请注意,变量后的
$元素仅使用一次,因此是冗余的(在两个版本中)。

更短、更简单

<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="CostPlan[not(Details)]/CustomInformation">
    <Details/>
    <xsl:call-template name="identity"/>
  </xsl:template>
</xsl:stylesheet>


谢谢!它似乎工作得很好。。有关于如何在XSLT1.0中实现这一点的指导吗?是的,这是一个很好的实现方法!非常感谢。
<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="CostPlan[not(Details)]/CustomInformation">
    <Details/>
    <xsl:call-template name="identity"/>
  </xsl:template>
</xsl:stylesheet>