@@ -42,6 +42,13 @@ public class Xpp3DomUtils
4242 public static final String SELF_COMBINATION_OVERRIDE = "override" ;
4343
4444 public static final String SELF_COMBINATION_MERGE = "merge" ;
45+
46+ /**
47+ * In case of complex XML structures, combining can be done based on id.
48+ *
49+ * @since 3.0.22
50+ */
51+ public static final String ID_COMBINATION_MODE_ATTRIBUTE = "combine.id" ;
4552
4653 /**
4754 * This default mode for combining a DOM node during merge means that where element names
@@ -71,7 +78,7 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
7178 * 1. if the recessive DOM is null, there is nothing to do...return.
7279 *
7380 * 2. Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
74- *
81+ *
7582 * A. retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
7683 * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive
7784 * one completely.
@@ -99,10 +106,13 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
99106 *
100107 * D. Iterate through the recessive children, and:
101108 *
102- * i. if mergeChildren == true and there is a corresponding dominant child (matched by element name),
109+ * i. if 'combine.id' is set and there is a corresponding dominant child (matched by value of 'combine.id'),
110+ * merge the two.
111+ *
112+ * ii. if mergeChildren == true and there is a corresponding dominant child (matched by element name),
103113 * merge the two.
104114 *
105- * ii. otherwise, add the recessive child as a new child on the dominant root node.
115+ * iii. otherwise, add the recessive child as a new child on the dominant root node.
106116 */
107117 private static void mergeIntoXpp3Dom ( Xpp3Dom dominant , Xpp3Dom recessive , Boolean childMergeOverride )
108118 {
@@ -115,7 +125,7 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
115125 boolean mergeSelf = true ;
116126
117127 String selfMergeMode = dominant .getAttribute ( SELF_COMBINATION_MODE_ATTRIBUTE );
118-
128+
119129 if ( isNotEmpty ( selfMergeMode ) && SELF_COMBINATION_OVERRIDE .equals ( selfMergeMode ) )
120130 {
121131 mergeSelf = false ;
@@ -154,16 +164,35 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
154164 }
155165
156166 Xpp3Dom [] children = recessive .getChildren ();
157- for ( Xpp3Dom child : children )
167+ for ( Xpp3Dom recessiveChild : children )
158168 {
159- Xpp3Dom childDom = dominant .getChild ( child .getName () );
169+ String idValue = recessiveChild .getAttribute ( ID_COMBINATION_MODE_ATTRIBUTE );
170+
171+ Xpp3Dom childDom = null ;
172+ if ( isNotEmpty ( idValue ) )
173+ {
174+ for ( Xpp3Dom dominantChild : dominant .getChildren () )
175+ {
176+ if ( idValue .equals ( dominantChild .getAttribute ( ID_COMBINATION_MODE_ATTRIBUTE ) ) )
177+ {
178+ childDom = dominantChild ;
179+ // we have a match, so don't append but merge
180+ mergeChildren = true ;
181+ }
182+ }
183+ }
184+ else
185+ {
186+ childDom = dominant .getChild ( recessiveChild .getName () );
187+ }
188+
160189 if ( mergeChildren && childDom != null )
161190 {
162- mergeIntoXpp3Dom ( childDom , child , childMergeOverride );
191+ mergeIntoXpp3Dom ( childDom , recessiveChild , childMergeOverride );
163192 }
164193 else
165194 {
166- dominant .addChild ( new Xpp3Dom ( child ) );
195+ dominant .addChild ( new Xpp3Dom ( recessiveChild ) );
167196 }
168197 }
169198 }
0 commit comments