Home Ask Login Register

Developers Planet

Your answer is one click away!

Dale February 2016

XSLT Merging two nodes into one

I'm looking to merge two nodes (or more) into one. I've worked with xslt for a little while, but mainly doing pretty simple stuff. I've done much searching, but solutions have been over my head so I haven't been able to adapt to my own problem. Closest thing I've found is an answer by Martin Honnen using a function he built called "eliminate-deep-equal-duplicates".

My problem is I can have two or more <Coverage> nodes that have "CoverageCd=ADDRL" and I need to combine these nodes only, no other Coverage nodes with other CoverageCd values. So I want to merge the ADDRL nodes but keep the unique "Addr" child node for all ADDRL iterations.

One other caveat is that I need to have the count of merged ADDRL nodes and place in the "OptionValue" element. So In my example where I have two ADDRL Coverage nodes my OptionValue needs to be 2. My xslt currently almost gives me what I need, but duplicates the MiscParty/GeneralPartyInfo which I don't want. And while I have the variable AddrlCount that gives me the correct value to place in my OptionValue,

I'm not quite sure how to incorporate that into the current xslt. I know my main problem is that I'm not exactly sure what the "eliminate-deep-equal-duplicates" function is doing. Any help anyone could provide would be greatly appreciated.

Input XML

                <Dwell LocationRef="000b3c6b-264f-83b7-1b80-006a3ce1f40e">
          <UnitMeasurementCd>Square Fo        


Tim C February 2016

You are grouping Coverage elements by CoverageCd values

<xsl:for-each-group select="Coverage" group-by="CoverageCd">

So, at this point you are positioned on a Coverage element (ones with the first occurrence of a CoverageCd value). But you then do this...

<xsl:apply-templates select="Coverage[./CoverageCd='ADDRL'],

This means you are looking for a Coverage element that is a child of a covering Coverage element, which would return element. Similarly, where you do this....

mf:eliminate-deep-equal-duplicates(current-group()/(* except (Addr)))

current-group() returns all Coverage elements with the same code, none of which have Addr elements, so this selects all elements.

What you can possibly do, is just replace the statement with this:

<xsl:apply-templates select="mf:eliminate-deep-equal-duplicates(current-group()/*)" />

Then you can have templates for matching elements you wish to change.

Try this XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:functx="http://www.functx.com" xmlns:mf="http://example.com/mf" exclude-result-prefixes="xs functx mf">
    <xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>

    <xsl:function name="functx:index-of-node" as="xs:integer*">
        <xsl:param name="nodes" as="node()*"/>
        <xsl:param name="nodeToFind" as="node()"/>

        <xsl:sequence select="   for $seq in (1 to count($nodes))   return $seq[$nodes[$seq] is $nodeToFind]  "/>

    <xsl:function name="mf:eliminate-deep-equal-duplicates" as="node()*">
        <xsl:param name="nodes"/>

Post Status

Asked in February 2016
Viewed 2,577 times
Voted 4
Answered 1 times


Leave an answer

Quote of the day: live life

Devs Planet ®

2014-2016 www.devsplanet.com

Devs Planet © all rights reserved