xslt - infer result from children
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:
Use the identity transform to copy everything from the input to the output, and
for element nodes without a
Pass
attribute, add it. Set it toFalse
if there is at least onePass
attribute with valueFalse
in the children, and toTrue
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".
精彩评论