【问题标题】:XSLT add missing node at specific locationXSLT 在特定位置添加缺失节点
【发布时间】:2015-12-14 12:19:15
【问题描述】:

我想在 XML 中插入一个缺失的节点,以防它丢失。例如,我想在 CustomInformation 节点之前添加一个<Details> 节点。我已经编写了下面的 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>

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>

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    好吧,匹配CostPlan[not(Details)] 的模板不处理属性。变化:

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

    到:

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

    还请注意,您的样式表标记为 XSLT 1.0,但您肯定使用的是 XSLT 2.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>
    

    请注意,$elements-after 变量只使用一次,因此是多余的(在两个版本中)。

    【讨论】:

    • 谢谢!它似乎工作得很好......关于我如何在 XSLT 1.0 中做到这一点的任何指导?
    【解决方案2】:

    更短更简单

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

    【讨论】:

    • 是的,这是一个不错的方法!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多