Simplify xml node using if-else condition by XSLT

2019-08-25 05:21发布

This is the input file:

<root> 
        <node id="N1">
            <fruit id="small_fruit" action="create">
                <orange id="1" action="create">
                    <attribute>
                        <color>yellow</color>
                    </attribute>
                </orange>
            </fruit>

            <fruit id="small_fruit" action="create">
                <orange id="1" action="destroy">
                    <attribute>
                        <color>green</color>
                    </attribute>
                </orange>
            </fruit>            
        </node>

        <node id="N2">
            <dog id="small_dog">    
                <poodle id="1" action="create">
                    <attribute>
                        <color>Yellow</color>    
                    </attribute>
                </poodle>       

                <terrier id="2" action="create">
                    <attribute>
                        <color>White</color>    
                    </attribute>
                </terrier>

                <poodle id="1" action="change">
                    <attribute>
                        <color>Brown</color>        
                    </attribute>
                </poodle>

                <terrier id="2" action="destroy">
                    <attribute>
                        <color>Blue</color>    
                    </attribute>
                </terrier>
            </dog>

            <dog id="small_dog" action="create">               
                <poodle id="1" action="destroy">
                    <attribute>
                        <color>Black</color>        
                    </attribute>
                </poodle>

                <terrier id="2" action="change">
                    <attribute>
                        <color>White</color>        
                    </attribute>
                </terrier>
                <terrier id="2" action="change">
                    <attribute>
                        <color>Grey</color>        
                    </attribute>
                </terrier>
            </dog>

            <dog id="large_dog">                
                <poodle id="1" action="create">
                    <attribute>
                        <color>Red</color>
                    </attribute>
                </poodle>
            </dog>
        </node>
    </root>

This is the expected output:

<root> 
<node id="N1">
    <fruit id="small_fruit" action="create">

    </fruit>

    <fruit id="small_fruit" action="create">
        <orange id="1" action="destroy">
            <attribute>
                <color>green</color>
            </attribute>
        </orange>
    </fruit>            
</node>

<node id="N2">
    <dog id="small_dog">                           

    </dog>

    <dog id="small_dog" action="create">               
        <poodle id="1" action="destroy">
            <attribute>
                <color>Black</color>        
            </attribute>
        </poodle>

        <terrier id="2" action="change">
            <attribute>
                <color>White</color>        
            </attribute>
        </terrier>
        <terrier id="2" action="change">
            <attribute>
                <color>Grey</color>        
            </attribute>
        </terrier>
    </dog>

    <dog id="large_dog">                
        <poodle id="1" action="create">
            <attribute>
                <color>Red</color>
            </attribute>
        </poodle>
     </dog>
</node>
</root>

The rule:

  1. if a node with the method 'destroy' appears at the end of the same parent (a fruit or an animal) we remove all the previous nodes.

  2. if NOT, we remove all the nodes including the one with 'destroy' method and leave the rest unchanged.

To simplify:

  • xxx/destroy -> destroy
  • xxx/destroy/aaa/bbb -> aaa/bbb

In summary we check the node that has the same id and node name (orange-id:1 or terrier-id:2 or poodle-id:1) and it must be under the same parent ex. (fruit or dog)

标签: xml xslt
1条回答
我欲成王,谁敢阻挡
2楼-- · 2019-08-25 06:01

I couldn't quite match up your expected results, with how you described the rules you wanted. However, from comparing your expected output with the input, I think this is the condition you may need:

<xsl:if test="not(following::*[../@id = current()/../@id][@action='destroy'])">

So, given the following XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="node/*/*">
      <xsl:if test="not(following::*[../@id = current()/../@id][@action='destroy'])">
         <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
         </xsl:copy>
      </xsl:if>
   </xsl:template>

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

When applied on your current input XML, the following is output, which matches you current expected output:

<root>
   <node id="N1">
      <fruit id="small_fruit" action="create"/>
      <fruit id="small_fruit" action="create">
         <orange id="1" action="destroy">
            <attribute>
               <color>green</color>
            </attribute>
         </orange>
      </fruit>
   </node>
   <node id="N2">
      <dog id="small_dog"/>
      <dog id="small_dog" action="create">
         <poodle id="1" action="destroy">
            <attribute>
               <color>Black</color>
            </attribute>
         </poodle>
         <terrier id="2" action="change">
            <attribute>
               <color>White</color>
            </attribute>
         </terrier>
         <terrier id="2" action="change">
            <attribute>
               <color>Grey</color>
            </attribute>
         </terrier>
      </dog>
      <dog id="large_dog">
         <poodle id="1" action="create">
            <attribute>
               <color>Red</color>
            </attribute>
         </poodle>
      </dog>
   </node>
</root>
查看更多
登录 后发表回答