<p>I have a <code>XmlDocument</code> in java, created with the <code>Weblogic XmlDocument</code> parser.</p>

<p>I want to replace the content of a tag in this <code>XMLDocument</code> with my own data, or insert the tag if it isn't there.</p>

<pre><code>&lt;customdata&gt;
   &lt;tag1 /&gt;
   &lt;tag2&gt;mfkdslmlfkm&lt;/tag2&gt;
   &lt;location /&gt;
   &lt;tag3 /&gt;
&lt;/customdata&gt;
</code></pre>

<p>For example I want to insert a URL in the location tag:</p>

<pre><code>&lt;location&gt;http://something&lt;/location&gt;
</code></pre>

<p>but otherwise leave the XML as is.</p>

<p>Currently I use a <code>XMLCursor</code>:</p>

<pre><code>    XmlObject xmlobj = XmlObject.Factory.parse(a.getCustomData(), options);
    XmlCursor xmlcur = xmlobj.newCursor();

    while (xmlcur.hasNextToken()) {
      boolean found = false;
      if (xmlcur.isStart() &amp;&amp; "schema-location".equals(xmlcur.getName().toString())) {
        xmlcur.setTextValue("http://replaced");
        System.out.println("replaced");
        found = true;
      } else if (xmlcur.isStart() &amp;&amp; "customdata".equals(xmlcur.getName().toString())) {
        xmlcur.push();
      } else if (xmlcur.isEnddoc()) {
        if (!found) {
          xmlcur.pop();
          xmlcur.toEndToken();
          xmlcur.insertElementWithText("schema-location", "http://inserted");
          System.out.println("inserted");
        }

      }
      xmlcur.toNextToken();
    }
</code></pre>

<p>I tried to find a "quick" <code>xquery</code> way to do this since the <code>XmlDocument</code> has an <code>execQuery</code> method, but didn't find it very easy. </p>

<p>Do anyone have a better way than this? It seems a bit elaborate.</p>

[{'answer_id': 15961, 'author': 'alanl', 'author_id': 1464, 'author_profile': 'https://Stackoverflow.com/users/1464', 'pm_score': 0, 'selected': False, 'text': '<p>You should be able to do this with <code>query</code></p>\n\n<p>try </p>\n\n<pre><code> fn:replace(string,pattern,replace)\n</code></pre>\n\n<p>I am new to xquery myself and I have found it to be a painful query language to work with, but it does work quiet well once you get over the initial learning curve. </p>\n\n<p>I do still wish there was an easier way which was as efficient? </p>\n'}, {'answer_id': 15967, 'author': 'Olly', 'author_id': 1174, 'author_profile': 'https://Stackoverflow.com/users/1174', 'pm_score': 2, 'selected': False, 'text': '<p>How about an object oriented approach?  You could deserialise the XML to an object, set the location value on the object, then serialise back to XML.</p>\n\n<p><a href="http://xstream.codehaus.org/tutorial.html" rel="nofollow noreferrer">XStream</a> makes this really easy.</p>\n\n<p>For example, you would define the main object, which in your case is CustomData (I\'m using public fields to keep the example simple):</p>\n\n<pre><code>public class CustomData {\n  public String tag1;\n  public String tag2;\n  public String location;\n  public String tag3;\n}\n</code></pre>\n\n<p>Then you initialize XStream:</p>\n\n<pre><code>XStream xstream = new XStream();\n// if you need to output the main tag in lowercase, use the following line\nxstream.alias("customdata", CustomData.class);  \n</code></pre>\n\n<p>Now you can construct an object from XML, set the location field on the object and regenerate the XML:</p>\n\n<pre><code>CustomData d = (CustomData)xstream.fromXML(xml);\nd.location = "http://stackoverflow.com";\nxml = xstream.toXML(d);\n</code></pre>\n\n<p>How does that sound?</p>\n'}, {'answer_id': 16019, 'author': 'Cheekysoft', 'author_id': 1820, 'author_profile': 'https://Stackoverflow.com/users/1820', 'pm_score': 4, 'selected': True, 'text': '<p>How about an XPath based approach? I like this approach as the logic is super-easy to understand. The code is pretty much self-documenting.</p>\n\n<p>If your xml document is available to you as an org.w3c.dom.Document object (as most parsers return), then you could do something like the following:</p>\n\n<pre><code>// get the list of customdata nodes\nNodeList customDataNodeSet = findNodes(document, "//customdata" );\n\nfor (int i=0 ; i &lt; customDataNodeSet.getLength() ; i++) {\n  Node customDataNode = customDataNodeSet.item( i );\n\n  // get the location nodes (if any) within this one customdata node\n  NodeList locationNodeSet = findNodes(customDataNode, "location" );\n\n  if (locationNodeSet.getLength() &gt; 0) {\n    // replace\n    locationNodeSet.item( 0 ).setTextContent( "http://stackoverflow.com/" );\n  }\n  else {\n    // insert\n    Element newLocationNode = document.createElement( "location" );\n    newLocationNode.setTextContent("http://stackoverflow.com/" );\n    customDataNode.appendChild( newLocationNode );\n  }\n}\n</code></pre>\n\n<p>And here\'s the helper method findNodes that does the XPath search.</p>\n\n<pre><code>private NodeList findNodes( Object obj, String xPathString )\n  throws XPathExpressionException {\n\n  XPath xPath = XPathFactory.newInstance().newXPath();\n  XPathExpression expression = xPath.compile( xPathString );\n  return (NodeList) expression.evaluate( obj, XPathConstants.NODESET );\n}\n</code></pre>\n'}, {'answer_id': 16375, 'author': 'Olly', 'author_id': 1174, 'author_profile': 'https://Stackoverflow.com/users/1174', 'pm_score': 1, 'selected': False, 'text': "<p>If you don't know the schema the XStream solution probably isn't the way to go. At least XStream is on your radar now, might come in handy in the future!</p>\n"}]
['https://Stackoverflow.com/questions/15899', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/86/']