title: Groovy XMLSlurper update document to match schema
body: <p>I'm having an issue I can't seem to work my way past and hoping some of you knowledgeable mavens can provide a solution.</p>
  
  <p>I have a document with an XSD containing a sequence.  As you know, this means that all the elements must appear in the specified order.  I need to use this because some of them are optional too (minOccurs = "0").</p>
  
  <p>Here is a simplified portion of the schema:</p>
  
  <pre><code>    &lt;xs:element name="result"&gt;
      &lt;xs:complexType&gt;
          &lt;xs:sequence&gt;
              &lt;xs:element ref="tns:resultCode"/&gt;
              &lt;xs:element ref="tns:resultAbbreviations" minOccurs="0"/&gt;
              &lt;xs:element ref="tns:resultReporter" minOccurs="0"/&gt;
              &lt;xs:element ref="tns:vendorData" minOccurs="0" maxOccurs="unbounded"/&gt;
          &lt;/xs:sequence&gt;
      &lt;/xs:complexType&gt;
  &lt;/xs:element&gt;
  </code></pre>
  
  <p>A related portion of the XML document:</p>
  
  <pre><code>&lt;lab:order&gt;
    &lt;lab:results&gt;
       &lt;lab:result&gt;
          &lt;lab:resultCode&gt;005009&lt;/lab:resultCode&gt;
          &lt;lab:resultAbbreviations&gt;
             &lt;lab:resultAbbreviation&gt;FOO&lt;/lab:resultAbbreviation&gt;
          &lt;/lab:resultAbbreviations&gt;
          &lt;lab:resultReporter&gt;
             &lt;lab:enteredEmployeeId&gt;86118&lt;/lab:enteredEmployeeId&gt;
          &lt;/lab:resultReporter&gt;
          &lt;lab:vendorData value="123" key="ABC"/&gt;
          &lt;lab:vendorData value="ABC" key="123"/&gt;
       &lt;/lab:result&gt;
       &lt;lab:result&gt;
          &lt;lab:resultCode&gt;005025&lt;/lab:resultCode&gt;
       &lt;/lab:result&gt;
       ...
  </code></pre>
  
  <p>I need to be able to do two things:</p>
  
  <ol>
  <li>If an element exists, update its value.  E.g. change the enteredEmployeeId value to "EntVal" for resultCode "005009".  This requires finding if that element exists.</li>
  <li>If an element does not exist, add it at a location that will pass validation according to the schema.  E.g. add resultReporter and enteredEmployeeId for resultCode "005025".  Note that there are optional elements that may or may not be there as shown in the XML snippet above.</li>
  </ol>
  
  <p>I have been able to add a Node to the end of the "result" Node, but can't get the find to work to update nor get the Node inserted at the proper spot to satisfy the XSD.  Here is the code:</p>
  
  <pre><code>    ...
  //-- ResultReporter: enteredEmployeeId, verifiedEmployeeId
  // Must add to proper result, based on code
  ResultReporter reporter = nextResult.getReporter();
  NodeChild codeNode = getResultNodeFor( nextResult.getCode() );
  if( codeNode != null ) {    //found proper result - does reporter exist already?
      def reporterNode = codeNode.find { it.name() == 'resultReporter' }
      if( !reporterNode.isEmpty() ) { //reporter node exists - update it
          reporterNode.'lab:enteredEmployeeId'( nextResult.getReporter().getEnteredEmployeeId() )
      } else {    //element does not exist - add new one
          codeNode.appendNode {
              'lab:resultReporter' {
                  'lab:enteredEmployeeId'(nextResult.getReporter().getEnteredEmployeeId())
              }
          }
      }
  } else {    //not found
      throw new IllegalArgumentException("Cannot add reporter for nonexistent result code: " + nextResult.getCode() );
  }
  ...
      /**
   * @param aCode
   * @return the Node with resultCode = aCode, else null
   */
  private NodeChild getResultNodeFor( String aCode ) {
      for( def nextResult : labDoc.order.results.children() ) {
          if(  nextResult.resultCode.text().equals(aCode) ) { //found
              return nextResult;
          }
      }
      return null;    //not found
  }
  </code></pre>
  
  <p>I am looking for an XML output like this (note that the first result's value is updated, the second one is inserted - but at the right place... there could be other elements there too!):</p>
  
  <pre><code>   &lt;lab:order&gt;
    &lt;lab:results&gt;
       &lt;lab:result&gt;
          &lt;lab:resultCode&gt;005009&lt;/lab:resultCode&gt;
          &lt;lab:resultAbbreviations&gt;
             &lt;lab:resultAbbreviation&gt;FOO&lt;/lab:resultAbbreviation&gt;
          &lt;/lab:resultAbbreviations&gt;
          &lt;lab:resultReporter&gt;
             &lt;lab:enteredEmployeeId&gt;EntVal&lt;/lab:enteredEmployeeId&gt;
          &lt;/lab:resultReporter&gt;
          &lt;lab:vendorData value="123" key="ABC"/&gt;
          &lt;lab:vendorData value="ABC" key="123"/&gt;
       &lt;/lab:result&gt;
       &lt;lab:result&gt;
          &lt;lab:resultCode&gt;005025&lt;/lab:resultCode&gt;
          &lt;lab:resultReporter&gt;
             &lt;lab:enteredEmployeeId&gt;EntVal&lt;/lab:enteredEmployeeId&gt;
          &lt;/lab:resultReporter&gt;
       &lt;/lab:result&gt;
       ...
  </code></pre>
  
  <p>So: can anyone tell me how to make this work?  Thanks! Mark</p>