title: Parsing an XML file within a Jenkins pipeline
body: <p><strong>Note:</strong></p>
  <p>I posted this question back when I only had a master node in my Jenkins environment. This made serialization a lesser issue as there were no other nodes to communicate with, thus the code here will not run as expected on a multi-node environment (for instance, <code>readFile</code> will only read files from the master node).</p>
  <p>In my experience it's better to have your configuration written in other formats (JSON, YAML, Groovy which are all supported natively in Jenkins), or use external tools (such as <code>xmllint</code> on Linux) if you don't have control over the file's format.</p>
  <p><strong>Original question:</strong></p>
  <p>I have an XML file which I'd like to use as input for a pipeline script. Problem is the XMLParser isn't serializable so I put it in a NonCPS function, but I lost the Node object because of that.</p>
  <p>This is the pipeline script:</p>
  <pre class="lang-java prettyprint-override"><code>def buildPlanPath = 'C:\\buildPlan_test.xml'
  
  @NonCPS
  groovy.util.Node getBuildPlan(path) {
      new XmlParser().parseText(readFile(path))
  }
      
  node {
      //def buildPlan = new XmlParser().parseText(readFile(buildPlanPath))
      groovy.util.Node buildPlan = getBuildPlan(buildPlanPath)
  
      println buildPlan.getClass()
      println buildPlan
      println buildPlan.branch
  }
  </code></pre>
  <p>This is an input sample:</p>
  <pre class="lang-xml prettyprint-override"><code>&lt;branch name='mybranch'&gt;
      &lt;stage&gt;
          &lt;job name='job11' /&gt;
          &lt;job name='job12' /&gt;
      &lt;/stage&gt;
      &lt;stage&gt;
          &lt;job name='job21' /&gt;
          &lt;job name='job22' /&gt;
          &lt;job name='job23' /&gt;
      &lt;/stage&gt;
      &lt;stage&gt;
          &lt;job name='job31' /&gt;
      &lt;/stage&gt;
  &lt;/branch&gt;
  </code></pre>
  <p>This is the result:</p>
  <pre><code>Started by user admin
  [Pipeline] node
  Running on master in C:\Jenkins\workspace\pipeline-develop
  [Pipeline] {
  [Pipeline] readFile
  [Pipeline] echo
  class java.lang.String
  [Pipeline] echo
  &lt;branch name='mybranch'&gt;
    &lt;stage&gt;
      &lt;job name='job11' /&gt;
      &lt;job name='job12' /&gt;
    &lt;/stage&gt;
    &lt;stage&gt;
      &lt;job name='job21' /&gt;
      &lt;job name='job22' /&gt;
      &lt;job name='job23' /&gt;
    &lt;/stage&gt;
    &lt;stage&gt;
      &lt;job name='job31' /&gt;
    &lt;/stage&gt;
  &lt;/branch&gt;
  [Pipeline] }
  [Pipeline] // node
  [Pipeline] End of Pipeline
  groovy.lang.MissingPropertyException: No such property: branch for class: java.lang.String
      at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
      at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:458)
      at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getProperty(DefaultInvoker.java:25)
      at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:17)
      at WorkflowScript.run(WorkflowScript:16)
      at ___cps.transform___(Native Method)
      at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:62)
      at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
      at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:54)
      at sun.reflect.GeneratedMethodAccessor327.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
      at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
      at com.cloudbees.groovy.cps.Next.step(Next.java:58)
      at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:154)
      at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:164)
      at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:276)
      at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$000(CpsThreadGroup.java:78)
      at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:185)
      at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:183)
      at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:47)
      at java.util.concurrent.FutureTask.run(Unknown Source)
      at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
      at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
      at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
      at java.util.concurrent.FutureTask.run(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)
  Finished: FAILURE
  </code></pre>
  <p>I'm using Jenkins 2.7 with pipeline 2.1, which are currently the latest.</p>