title: Fast replacement of XML node values
body: <p>I have a bunch of XML documents which contain personal information that I need to replace with fake data. The Person node contains the following elements:</p>
  
  <ul>
  <li>uuid - required, should not be touched.</li>
  <li>firstName - optional</li>
  <li>lastName - optional</li>
  <li>address - optional</li>
  <li>personID - required</li>
  </ul>
  
  <p>A person may appear many times, in which case the same fake data should be used, i.e. if two Person nodes have the same personID, they should both recieve the same fake ID.</p>
  
  <p>I have implemented some Java code that builds a DOM tree from the XML string and replaces the nodes before writing it back to a string. This works fine, but since I have so many documents I was wondering if there is a faster approach. Maybe through regular expressions or XSLT or something?</p>
  
  <p>Here is an example document:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;ADocument&gt;
    &lt;Stuff&gt;
      ...
    &lt;/Stuff&gt;
    &lt;OtherStuff&gt;
      ...
    &lt;/OtherStuff&gt;
    &lt;Person&gt;
      &lt;uuid&gt;11111111-1111-1111-1111-111111111111&lt;/uuid&gt;
      &lt;firstName&gt;Some&lt;/firstName&gt;
      &lt;lastName&gt;Person&lt;/lastName&gt;
      &lt;personID&gt;111111111111&lt;/personID&gt;
    &lt;/Person&gt;
    &lt;Person&gt;
      &lt;uuid&gt;22222222-2222-2222-2222-222222222222&lt;/uuid&gt;
      &lt;firstName&gt;Another Person&lt;/firstName&gt;
      &lt;address&gt;Main St. 2&lt;/address&gt;
      &lt;personID&gt;222222222222&lt;/personID&gt;
    &lt;/Person&gt;
    &lt;Person&gt;
      &lt;uuid&gt;33333333-3333-3333-3333-333333333333&lt;/uuid&gt;
      &lt;firstName&gt;Some&lt;/firstName&gt;
      &lt;lastName&gt;Person&lt;/lastName&gt;
      &lt;personID&gt;111111111111&lt;/personID&gt;
    &lt;/Person&gt;
    &lt;MoreStuff&gt;
      ...
    &lt;/MoreStuff&gt;
  &lt;/ADocument&gt;
  </code></pre>
  
  <p>And this is my current implementation:</p>
  
  <pre class="lang-java prettyprint-override"><code>public String replaceWithFalseData(String xmlInstance) {
      Document dom = toDOM(xmlInstance);
  
      XPathExpression xPathExpression = XPathExpressionFactory.createXPathExpression("//Person");
      List&lt;Node&gt; nodeList = xPathExpression.evaluateAsNodeList(dom);
  
      for(Node personNode : nodeList) {
          Map&lt;String, Node&gt; childNodes = getChildNodes(personNode);
          String personID = childNodes.get("personID").getTextContent();
          // Retrieve a cached fake person using the ID, or create a new one if none exists.
          Person fakePerson = getFakePerson(personID);
  
          setIfExists(childNodes.get("firstName"), fakePerson.getFirstName());
          setIfExists(childNodes.get("lastName"), fakePerson.getLastName());
          setIfExists(childNodes.get("address"), fakePerson.getAddress());
          setIfExists(childNodes.get("personID"), fakePerson.getPersonID());
      }
  
      return toString(dom);
  }
  
  public Map&lt;String, Node&gt; getChildNodes(Node parent) {
      Map&lt;String, Node&gt; childNodes = new HashMap&lt;String, Node&gt;();
      for(Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
          if(child.getLocalName() != null) {
              childNodes.put(child.getLocalName(), child);
          }
      }
      return childNodes;
  }
  
  public void setIfExists(Node node, String value) {
      if(node != null) {
          node.setTextContent(value);
      }
  }
  </code></pre>