Subject: RE: [xsl] Constructing a tree from leaf nodes (knowing the tree structure)? From: "Simon Shutter" <simon@xxxxxxxxxxx> Date: Sun, 24 Jun 2007 22:16:07 -0700 |
This post refers to a question I posed back on April 19th and the suggested transformations that Michael Kay and Ken Holman generously provided. Michael provided two slightly different solutions to cover some ambiguity in my question. When I run his solutions, however, I get different results than I expected and wonder if I am implementing them incorrectly or if my statement of the problem was unclear. I have since revised the summary of the problem for hopefully better clarity and also edited the data file to remove what I believe are redundant attributes. I'm hoping to try and resolve why I can't get Michael's solutions to work. Simon ************************************************************************** Summary of Problem ************************************************************************** (thanks to Trevor Nicholls and Ragulf Pickaxe back in April for their help) There is a structure tree (in.xml) and a data tree (data.xml) - see examples below. The structure tree is fixed and complete. The data tree is variable and may contain any element which corresponds to a descendant-less node (leaf node) in the structure tree (at most one of each element). The desired output is a merge of the structure tree and the data tree, where: a) for any specific leaf node in the structure tree: (i) if the data tree contains a matching node with @result=true then @complete=true and @result=true, (ii) if the data tree contains a matching node with @result=false then @complete=true and @result=false, and (iii) if the data tree does not contain a matching node then @complete=false and @result=true (because I do not want to affect the logical AND value of ancestor nodes' @result value when they include leaf nodes with @complete=false - see b) (iii) below b) for every other internal node in the structure tree: (i) if the data tree contains a matching node for every leaf node in the structure tree (that is descendent of this internal node) and each matching node has @result=true then for this internal node @complete=true and @result=true, (ii) similarly, if the data tree contains a matching node for every leaf node in the structure tree but not all results are true then for this internal node @complete=true and @result=false, (iii) if the data tree does not contain a matching node for every leaf node in the structure tree but the value of each matching node that it does contain has @result=true then for the internal node @complete=false and @result=true, (iv) if the data tree does not contain a matching node for every leaf node in the structure tree and the value of any matching node that it does contain has @result=false then @complete=false and @result=false ************************************************************************** Example structure tree (in.xml) ************************************************************************** <a> <b> <c/> <d/> </b> <e> <f/> <g> <h/> <i/> </g> </e> </a> ************************************************************************** Example data tree (data.xml) ************************************************************************** <data> <c result="true"/> <d result="false"/> <h result="true"/> <i result="true"/> </data> ************************************************************************** Example desired result ************************************************************************** <a complete="false" result="false"> <b complete="true" result="false"> <c complete="true" result="true"/> <d complete="true" result="false"/> </b> <e complete="false" result="true"> <f complete="false" result="true"/> <g complete="true" result="true"/> <h complete="true" result="true"/> <i complete="true" result="true"/> </g> </e> </a> ************************************************************************** Michael's first stylesheet (mkay1.xsl) Comments: - non-leaf nodes look at all descendants ************************************************************************** <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:variable name="tree" select="/"/> <xsl:variable name="data" select="doc('data.xml')/data"/> <!-- rule for non-leaf nodes --> <xsl:template match="*[*]"> <xsl:copy> <xsl:attribute name="complete" select="every $n in descendant::* satisfies exists($data/*[name() = name($n)])"/> <xsl:attribute name="result" select="every $n in descendant::* satisfies exists($data/*[name() = name($n) and @result='true']) "/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <!-- rule for leaf nodes --> <xsl:template match="*"> <xsl:copy> <xsl:attribute name="complete" select="exists($data/*[name() = name(current())])"/> <xsl:attribute name="result" select="$data/*[name() = name(current())]/@result"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet> ************************************************************************** Output I get from Michael's first stylesheet (mkay1.xml) Comments: - node e should have result="true" because none of its descendent nodes have result="false" - not sure how $tree is used ************************************************************************** <?xml version="1.0" encoding="UTF-8"?> <a complete="false" result="false"> <b complete="true" result="false"> <c complete="true" result="true"/> <d complete="true" result="false"/> </b> <e complete="false" result="false"> <!-- @result should be true --> <f complete="false" result=""/> <g complete="true" result="true"> <h complete="true" result="true"/> <i complete="true" result="true"/> </g> </e> </a> ************************************************************************** Michael's second stylesheet (mkay2.xsl) Comments: - non-leaf nodes should only look at leaf node descendants ************************************************************************** <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:variable name="tree" select="/"/> <xsl:variable name="data" select="doc('data.xml')/data"/> <!-- rule for non-leaf nodes --> <xsl:template match="*[*]"> <xsl:copy> <xsl:attribute name="complete" select="every $n in descendant::* satisfies (* or exists($data/*[name() = name($n)]))"/> <xsl:attribute name="result" select="every $n in descendant::* satisfies (* or exists($data/*[name() = name($n) and @result='true']))"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <!-- rule for leaf nodes --> <xsl:template match="*"> <xsl:copy> <xsl:attribute name="complete" select="exists($data/*[name() = name(current())])"/> <xsl:attribute name="result" select="$data/*[name() = name(current())]/@result"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet> ************************************************************************** Output from Michael's second stylesheet (mkay2.xml) Comments: - nodes a and b should have @result=false because node d has @result=false - node e should have @complete=false because node f is missing from data.xml - not sure how $tree is used ************************************************************************** <?xml version="1.0" encoding="UTF-8"?> <a complete="true" result="true"> <!-- @result should be false --> <b complete="true" result="true"> <!-- @result should be false --> <c complete="true" result="true"/> <d complete="true" result="false"/> </b> <e complete="true" result="true"> <!-- @complete should be false --> <f complete="false" result=""/> <g complete="true" result="true"> <h complete="true" result="true"/> <i complete="true" result="true"/> </g> </e> </a>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] XPath Question (related t, Michael Kay | Thread | [xsl] XSL Syntax in XML File?, Matt |
Re: [xsl] XPath Question (related t, Grant Slade | Date | [xsl] XSL Syntax in XML File?, Matt |
Month |