XSL转换 - 插入属性

时间:2011-02-17 11:57:37

标签: xslt

我是xsl转换的初学者

我有一些xml,当该属性不存在时,我需要将一个属性插入元素中。

使用以下xml作为示例。

<Order Id="IR1598756" Status="2">
  <Details>
    <SomeInfo>Sample Data</SomeInfo>
  </Details>
  <Documents>
    <Invoice>
      <Date>15-02-2011</Date>
      <Time>11:22</Time>
      <Employee Id="159">James Morrison</Employee>
    </Invoice>
    <DeliveryNote>
      <Reference>DN1235588</Reference>
      <HoldingRef>HR1598785</HoldingRef>
      <Date>16-02-2011</Date>
      <Time>15:00</Time>
      <Employee Id="25">Javi Cortez</Employee>
    </DeliveryNote>
  </Documents>
</Order>

期望输出

<Order Id="IR1598756" Status="2">
  <Details>
    <SomeInfo>Sample Data</SomeInfo>
  </Details>
  <Documents>
    <Invoice Id="DN1235588">
      <Date>15-02-2011</Date>
      <Time>11:22</Time>
      <Employee Id="159">James Morrison</Employee>
    </Invoice>
  </Documents>
</Order>    

<Invoice>元素可以包含Id属性<Invoice Id="IR1564897">

如何查看以下内容。

  1. 检查属性是否存在
  2. 如果没有,请将<Refernce>DN1235588</Reference>的值作为Id
  3. 插入
  4. 如果没有<Reference>,请使用<HoldingRef>HR1598785</HoldingRef>
  5. 的值

    我正在考虑实施类似以下的内容

     <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="/">
        <xsl:apply-templates select="//Order"/>
      </xsl:template>
    
      <xsl:template match="Order/Documents/Invoice[not(@Id)]">
          <xsl:attribute name="Id">
            <xsl:value-of select="//Documents/DeliveryNote/Reference"/>
          </xsl:attribute>      
      </xsl:template>
    

    以上内容未输出完整的<Invoice>元素。 我怎么能纠正这个?

      <xsl:if test="Order/Documents/DeliveryNote/Reference">
        <xsl:value-of select="//Documents/DeliveryNote/Reference"/>
      </xsl:if>
      <xsl:if test="Not(Order/Documents/DeliveryNote/Reference)">
        <xsl:value-of select="//Documents/DeliveryNote/HoldingRef"/>
      </xsl:if>
    

    如果其中任何一个始终存在,这是否可以在<Reference><HoldingRef>之间切换?

    在Alex的帮助下: 以下内容有助于我替换属性

      <xsl:template match="Order/Documents/Invoice[not(@Id)]">       
        <Invoice>
          <xsl:attribute name="Id">         
            <xsl:value-of Select="//Documents/DeliveryNote/Reference"/>
          </xsl:attribute>         
          <xsl:apply-templates select="@* | node()"/>
        </Invoice>
      </xsl:template>
    

3 个答案:

答案 0 :(得分:6)

答案最短:

<xsl:template match="Invoice[not(@Id)]">
    <Invoice Id="{(../DeliveryNote/Reference|
                   ../DeliveryNote/HoldingRef)[1]}">
        <xsl:apply-templates select="@* | node()"/>
    </Invoice>
</xsl:template>

答案 1 :(得分:0)

试一试:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates select="//Order"/>
    </xsl:template>

    <!-- Match invoices without ids -->
    <!-- [DeliveryNote[Reference or HoldingRef] - defend against empty attributes -->
    <xsl:template match="Invoice[not(@id)][DeliveryNote[Reference or HoldingRef]]">
        <xsl:copy>
            <!-- create an attribute and fetch required data. In case Reference is present then insert reference
             otherwise - HoldingRef -->
            <xsl:attribute name="Id">
                <xsl:value-of select="following-sibling::DeliveryNote[1]/Reference |
                        following-sibling::DeliveryNote[1]/HoldingRef"/>
            </xsl:attribute>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//DeliveryNote"/>

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

关于你的问题:

  

以上不输出完整元素。我怎么能纠正这个?

见我的例子。

  

如果其中任何一个始终存在,这是否可以在<Reference><HoldingRef>之间切换?

使用XPath(在我的示例中)或使用xsl:choose

答案 2 :(得分:0)

这个怎么样?

  <xsl:template match="Invoice[not(@Id)]">
    <xsl:element name="Invoice">
      <xsl:attribute name="Id">
        <xsl:variable name="REF" select="../DeliveryNote/Reference"/>
        <xsl:choose>
          <xsl:when test="not($REF)">
            <xsl:value-of select="../DeliveryNote/HoldingRef"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="../DeliveryNote/Reference"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
      <xsl:apply-templates select="*"/>
    </xsl:element>
  </xsl:template>

使用它代替<xsl:template match="Order/Documents/Invoice[not(@Id)]">