XSLT转换

时间:2017-06-14 13:49:39

标签: xml xslt

我尝试使用xslt将源XML转换为目标XML。

在Source xml中,我有多个 action 标记。 对于每个 action/action_kind/code='pickup' ,都会有另一个 action/action_kind/code='deliver'

action个标记orderId中都是相同的。

我需要根据此选择 from to 标记,我需要填充下面显示的目标XML。

源XML



<section>
  
  <action>
    <action_kind>
      <code>pickup</code>
    </action_kind>
    <pickup>
      <orderId>11</orderId>
    </pickup>
    <name>NameOne</name>
    <address>AddressOne</address>
  </action>
 
  <action>
    <action_kind>
      <code>pickup</code>
    </action_kind>
    <pickup>
      <orderId>22</orderId>
    </pickup>
    <name>NameTwo</name>
    <address>AddressTwo</address>
  </action>
  
  <action>
    <action_kind>
      <code>deliver</code>
    </action_kind>
    <expected>
      <from>FirstOrderFro</from>
      <to>FirstOrderTo</to>
    </expected>
    <delivery>
      <orderId>11</orderId>
    </delivery>
  </action>
  
  <action>
    <action_kind>
      <code>deliver</code>
    </action_kind>
    <expected>
      <from>ScondOrderFro</from>
      <to>SecondOrderTo</to>
    </expected>
    <delivery>
      <orderId>22</orderId>
    </delivery>
  </action>
  
</section>
&#13;
&#13;
&#13;

目标XML

&#13;
&#13;
<Orders>
  <Order>
    <OrderId>11</OrderId>
    <Name>NameOne</Name>
    <Address>AddressOne</Address>
    <From>FirstOrderFro</From>
    <To>FirstOrderTo</To>
  </Order>
  <Order>
    <OrderId>22</OrderId>
    <Name>NameTwo</Name>
    <Address>AddressTwo</Address>
    <From>SecondOrderFro</From>
    <To>SecondOrderTo</To>
  </Order>
</Orders>
&#13;
&#13;
&#13;

有人可以给我xslt解决方案,它可以将Source XML转换为Target XML吗?

2 个答案:

答案 0 :(得分:0)

在尝试了多种方法之后,我找到了以下方法来获得预期的输出。

&#13;
&#13;
<xsl:template match="/">
   <Orders>
     <xsl:for-each select="/section/action">
       <xsl:variable name="PickupOrderId" select="pickup/orderId"/>
       <xsl:if test="action_kind/code='pickup'">
         <Order>
           <OrderId>
             <xsl:value-of select="pickup/orderId"/>
           </OrderId>
           <Name>
             <xsl:value-of select="name"/>
           </Name>
           <Address>
             <xsl:value-of select="address"/>
           </Address>
           <xsl:for-each select="/section/action">
             <xsl:if test="action_kind/code='deliver'">
               <xsl:if test="./delivery/orderId=$PickupOrderId">
                 <From>
                   <xsl:value-of select="expected/from"/>
                 </From>
                 <To>
                   <xsl:value-of select="expected/to"/>
                 </To>
               </xsl:if>
             </xsl:if>
           </xsl:for-each>
         </Order>
       </xsl:if>
     </xsl:for-each>
   </Orders>
 </xsl:template>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

这是使用Muenchian分组的另一个选项,就像我在评论中提到的那样。

XML输入

<section>
    <action>
        <action_kind>
            <code>pickup</code>
        </action_kind>
        <pickup>
            <orderId>11</orderId>
        </pickup>
        <name>NameOne</name>
        <address>AddressOne</address>
    </action>
    <action>
        <action_kind>
            <code>pickup</code>
        </action_kind>
        <pickup>
            <orderId>22</orderId>
        </pickup>
        <name>NameTwo</name>
        <address>AddressTwo</address>
    </action>
    <action>
        <action_kind>
            <code>deliver</code>
        </action_kind>
        <expected>
            <from>FirstOrderFro</from>
            <to>FirstOrderTo</to>
        </expected>
        <delivery>
            <orderId>11</orderId>
        </delivery>
    </action>
    <action>
        <action_kind>
            <code>deliver</code>
        </action_kind>
        <expected>
            <from>ScondOrderFro</from>
            <to>SecondOrderTo</to>
        </expected>
        <delivery>
            <orderId>22</orderId>
        </delivery>
    </action>
</section>

XSLT 1.0

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

  <xsl:key name="actionByOrderId" match="action" use="*/orderId"/>

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

  <xsl:template match="section">
    <Orders>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each select="action[count(.|key('actionByOrderId',*/orderId)[1])=1]">
        <Order>
          <OrderId><xsl:value-of select="*/orderId"/></OrderId>
          <xsl:apply-templates select="key('actionByOrderId',*/orderId)"/>          
        </Order>
      </xsl:for-each>
    </Orders>
  </xsl:template>

  <xsl:template match="action">
    <xsl:apply-templates select="name|address|expected/*"/>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<Orders>
   <Order>
      <OrderId>11</OrderId>
      <name>NameOne</name>
      <address>AddressOne</address>
      <from>FirstOrderFro</from>
      <to>FirstOrderTo</to>
   </Order>
   <Order>
      <OrderId>22</OrderId>
      <name>NameTwo</name>
      <address>AddressTwo</address>
      <from>ScondOrderFro</from>
      <to>SecondOrderTo</to>
   </Order>
</Orders>

注意:我省略了将元素名称的第一个字母大写的部分。