Subject: Re: [xsl] Merge XML, simple but can't get it! From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Fri, 8 Jun 2001 15:05:39 +0100 |
Hi Jason, > The XSL below is supposed to process the xml by merging the > information in <Returned> back in main body, not sure if we are > using the right methodology as we are still new to XML, if anyone > can point me in the right direction it would be much appreciated! You seem to be on the right track, using something based on the identity template to work through the main body, and going off to find the relevant part of the Returned information as required. There are a few things that you could do to improve it, and a couple of things that you're doing that are a bit weird so it's probably worth checking whether you mean them or not, but you haven't said what part isn't working or what you want it to come out with. Perhaps the problem is the fact that the content of the Returned element is getting output when you don't want it to be? You can solve that by only applying templates to the Policy within a MergePolicy-matching template: <xsl:template match="MergePolicy"> <xsl:apply-templates select="Policy" /> </xsl:template> Or by having an empty template matching the Returned element: <xsl:template match="Returned" /> You could make it more efficient if you had a global variable that held the Returned information so you don't have to go and get it every time you come to another node: <xsl:variable name="returned" select="/MergePolicy/Returned" /> You could also use intermediate templates within your identity template, again to save repeating the same paths: <xsl:template match="@*|node()" mode="copy"> <xsl:copy> <xsl:apply-templates select="@*" mode="copy" /> <xsl:variable name="currentNode" select="name()" /> <xsl:variable name="descendantNode" select="name(descendant::*)" /> <xsl:variable name="currentRefAttribute" select="@ref" /> <xsl:variable name="returnedNode" select="$returned/*[name() = $currentNode and @ref = $currentRefAttribute]" /> <xsl:choose> <xsl:when test="$returnedNode/*[name() = $descendantNode]"> <xsl:apply-templates select="$returnedNode" mode="add" /> </xsl:when> <xsl:when test="$returnedNode"> <xsl:copy-of select="$returnedNode/*" /> <xsl:apply-templates mode="copy" /> </xsl:when> <xsl:otherwise> <xsl:if test="$returnedNode"> </xsl:if> <xsl:apply-templates mode="copy" /> </xsl:otherwise> </xsl:choose> </xsl:copy> </xsl:template> The problem that leaps out with the above is the definition of the $descendantNode variable. The name() function will get the name of the first node in the node set you pass to it as an argument. The first descendant of an element is the same as its first child, so the definition you have above is equivalent to: <xsl:variable name="firstChildNode" select="name(*[1])" /> In fact, the current behaviour of the template means that you could change the template to the following with the same effect: <xsl:template match="@*|node()" mode="copy"> <xsl:copy> <xsl:apply-templates select="@*" mode="copy" /> <xsl:variable name="currentNode" select="name()" /> <xsl:variable name="firstChildNode" select="name(*[1])" /> <xsl:variable name="currentRefAttribute" select="@ref" /> <xsl:variable name="returnedNode" select="$returned/*[name() = $currentNode and @ref = $currentRefAttribute]" /> <!-- if there's a node in Returned that matches, then copy its children --> <xsl:if test="$returnedNode"> <xsl:copy-of select="$returnedNode/*" /> </xsl:if> <!-- if the node in Returned doesn't have a child whose name is the same as the first child of the current node, then carry on processing the children of the current node --> <xsl:if test="not($returnedNode/*[name() = $firstChildNode])"> <xsl:apply-templates mode="copy" /> </xsl:if> </xsl:copy> </xsl:template> If you have lots of elements underneath Returned, you might consider having a key: <xsl:key name="returnedNodes" select="Returned/*" use="concat(name(), ':', @ref)" /> You could then retrieve the returned Node with the following instead: <xsl:variable name="returnedNode" select="key('returnedNodes', concat(name(), ':', @ref))" /> and wouldn't have to use $returned, $currentNode or $currentRefAttribute. I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Merge XML, simple but can't g, Jason Swalwell | Thread | [xsl] RE: xsl:varaible, Dimitre Novatchev |
[xsl] Indent extension in Saxon?, Gustaf Liljegren | Date | RE: [xsl] xml->xsl->pdf (using Ante, Rene de Vries |
Month |