【问题标题】:XSLT 1.0 Test deviationXSLT 1.0 测试偏差
【发布时间】:2020-01-24 10:08:44
【问题描述】:

如何检查两个值是否不同? -> 关注节点Item.DeliveryDateItem.OrigDeliveryDate

如果是,则应使用值yes 创建一个新节点LineChangeDeliveryDate,否则使用值no

目前的XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<OrderResponse>
  <Interchange>    
    <Interchange_Control_Number>5637248870</Interchange_Control_Number>
  </Interchange>
  <HeaderInformation>
    <ConfirmDocNum>SO0009783-1</ConfirmDocNum>   
    <TransportDetails>
      <DeliveryMode>ROU</DeliveryMode>
    </TransportDetails>   
  </HeaderInformation>
  <LineInformation>
    <Item>      
      <DeliveryDate>2020-01-27</DeliveryDate>
      <OrigDeliveryDate>2019-12-07</OrigDeliveryDate>
    </Item>
  </LineInformation>
</OrderResponse>

XML 新/正确:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<OrderResponse>
  <Interchange>    
    <Interchange_Control_Number>5637248870</Interchange_Control_Number>
  </Interchange>
  <HeaderInformation>
    <ConfirmDocNum>SO0009783-1</ConfirmDocNum>   
    <TransportDetails>
      <DeliveryMode>ROU</DeliveryMode>
    </TransportDetails>   
  </HeaderInformation>
  <LineInformation>
    <Item>      
      <DeliveryDate>2020-01-27</DeliveryDate>
      <OrigDeliveryDate>2019-12-07</OrigDeliveryDate>
      <LineChangeDeliveryDate>yes</LineChangeDeliveryDate>
    </Item>
  </LineInformation>
</OrderResponse>

当前 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes" indent="yes"/>
  <xsl:strip-space elements="*" />

  <xsl:key name="header_text" match="HeaderText" use="Text"/>
  <xsl:key name="line_text" match="LineText" use="concat(../LineNum, '|', Text)"/>
  <xsl:key name="allowance_charge_header" match="AllowanceOrCharge_Header" use="concat(Code, '|', Amount)"/>
  <xsl:key name="allowance_charge_line" match="AllowanceOrCharge_Line" use="concat(../LineNum, '|', Code, '|', Amount)"/>
  <xsl:key use="concat(../LineNum, '|', Text)" match="LineText" name="line_text"/>

  <!-- Identity-Template für die nicht explizit benannten Elemente -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="HeaderText[generate-id() != generate-id(key('header_text', Text)[1])]" />
  <xsl:template match="LineText[generate-id() != generate-id(key('line_text', concat(../LineNum, '|', Text))[1])]" />
  <xsl:template match="AllowanceOrCharge_Header[generate-id() != generate-id(key('allowance_charge_header', concat(Code, '|', Amount))[1])]" />
  <xsl:template match="AllowanceOrCharge_Line[generate-id() != generate-id(key('allowance_charge_line', concat(../LineNum, '|', Code, '|', Amount))[1])]" />
  <xsl:template match="LineText[generate-id() != generate-id(key('line_text', concat(../LineNum, '|', Text))[1])]"/>

  <xsl:template match="Item">
    <xsl:copy>
      <LineChangeDeliveryDate>
        <xsl:choose>
          <xsl:when test="OrigDeliveryDate = DeliveryDate"/>
            <xsl:value-of select="'yes'"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="'no'"/>
          </xsl:otherwise>
        </xsl:choose>
      </LineChangeDeliveryDate>
      <!--copy all other nodes-->
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

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

  <xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']"/>

</xsl:stylesheet>

【问题讨论】:

    标签: xml xslt xslt-1.0


    【解决方案1】:

    在带有match="Item"的模板规则中,做

    <LineChangeDeliveryDate>
      <xsl:choose>
        <xsl:when test="OrigDeliveryDate = DeliveryDate">
           <xsl:value-of select="'yes'/>
        </xsl:when>
        <xsl:otherwise>
           <xsl:value-of select="'no'/>
        </xsl:otherwise>
      </xsl:choose>
    </LineChangeDeliveryDate>
    

    这是 XSLT 2.0 代码更加简洁的众多案例之一:

    <LineChangeDeliveryDate>
           <xsl:value-of select="if (OrigDeliveryDate = DeliveryDate) then 'yes' else 'no'"/>
    </LineChangeDeliveryDate>
    

    在 3.0 中它进一步减少到

    <LineChangeDeliveryDate>{
      if (OrigDeliveryDate = DeliveryDate) then 'yes' else 'no'
    }</LineChangeDeliveryDate>
    

    【讨论】:

    • 你把代码放在了匹配LineInformation的模板中,而不是Item,所以上下文节点是错误的。
    • 已更正但错误消息:XML 解析器报告的错误:元素类型“xsl:choose”必须由匹配的结束标记“”终止。
    • 末尾有一个额外的斜线
    • 我喜欢确保人们必须阅读和理解代码,而不是盲目地复制它;-)。希望这意味着他们将来不必问这么多问题。
    • 好答案,我这边+1! Michael,是时候发布您的 XSLT 3.0 书籍了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    相关资源
    最近更新 更多