开发者

xslt - infer result from children

开发者 https://www.devze.com 2022-12-08 06:11 出处:网络
Given the following xml input: <Sections> <Section number=\"1\"> <Step number=\"1\"> <SubStep number=\"1\" Pass=\"True\">

Given the following xml input:

<Sections>
 <Section number="1">       
  <Step number="1">
   <SubStep number="1" Pass="True">             
    <SubSubStep number="1" Pass="True"/>                    
    <SubSubStep number="2" Pass="True"/>                    
   </SubStep>
  </Step>
  <Step number="2">
   <SubStep number="1" Pass="False">                
    <SubSubStep number="1" Pass="True"/>                    
    <SubSubStep number="2" Pass="False"/>                   
   </SubStep>
  </Step>
 </Section>
</Sections>

How can I transform it to:

<Sections Pass="False">
 <Section number="1" Pass="False">      
  <Step number="1" Pass="True">
   <SubStep number="1" Pass="True">             
    <SubSubStep number="1" Pass="True"/>                    
    <SubSubStep number="2" Pass="True"/>                    
   </SubStep>
  </Step>
  <Step number="2" Pass="False">
   <SubStep number="1" Pass="False">                
    <SubSubStep number="1" Pass="True"/>                    
    <SubSubStep number="2" Pass="False"/>                   
   </SubStep>
  </Step>
 </Section>
</Sections>

I want to infer the result of the parent from the children. If any of the children have a Pass="False" result the parent result will 开发者_Go百科be Pass="False". Backwards recursion?


You could do it as follows:

  1. Use the identity transform to copy everything from the input to the output, and

  2. for element nodes without a Pass attribute, add it. Set it to False if there is at least one Pass attribute with value False in the children, and to True otherwise.


<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes"/>

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

  <!-- set missing Pass attribute -->
  <xsl:template match="*[not(@Pass)]">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="Pass">
        <xsl:choose>
          <xsl:when test=".//*[@Pass = 'False']">False</xsl:when>
          <xsl:otherwise>True</xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>


You can use the ".//node()[ @Pass='True' ]" XPath expression to see if any children of the current node are "True".

0

精彩评论

暂无评论...
验证码 换一张
取 消