Hi everyone.

I need help. I'm supposed to have my program edit an XML field.
The user has the option to change the values in certain nodes.

After the node values have been filled in, and a certain button has been clicked, the program should write the changes to the file.

Here's the origional XML file:

<?xml version="1.0" ?> 
- <APOLLERSETTINGS>
- <SYSTEM>
  <VERSION>3.1</VERSION> 
  <SMTPSRV>blue</SMTPSRV> 
  <SMTPPORT>29</SMTPPORT> 
  <SMTPUSR>Me</SMTPUSR> 
  <SMTPPSW>Password</SMTPPSW> 
  <EMAILFROM>lodewyk.duminy@gmail.com</EMAILFROM> 
  <EMAILTO>lodewyk.duminy@gmail.com</EMAILTO> 
  <ALTEMAILTO>lodewyk.duminy@gmail.com</ALTEMAILTO> 
  </SYSTEM>
- <JOB>
  <JOBNAME>The Name</JOBNAME> 
  <INPUTFOLDER>C:\</INPUTFOLDER> 
  <FILEMASK>*.txt</FILEMASK> 
  <PROCESSORDER /> 
  <RETAINFOLDER>C:\</RETAINFOLDER> 
  <OVERRIDEFOLDER>C:\</OVERRIDEFOLDER> 
  <ERRORFOLDER>C:\</ERRORFOLDER> 
  <POLLINTERVAL>6000</POLLINTERVAL> 
  <JOBBATCHFILEPATH>C:\</JOBBATCHFILEPATH> 
  <JOBBATCHPARAMS>three</JOBBATCHPARAMS> 
  <JOBLOGPATH>C:\</JOBLOGPATH> 
  <JOBEMAILTO>lodewyk.duminy@gmail.com</JOBEMAILTO> 
  <JOBALTEMAILTO>lodewyk.duminy@gmail.com</JOBALTEMAILTO> 
  </JOB>
- <JOB>
  <JOBNAME>Second job</JOBNAME> 
  <INPUTFOLDER>C:\</INPUTFOLDER> 
  <FILEMASK>*.xml</FILEMASK> 
  <PROCESSORDER>BACKWARDS</PROCESSORDER> 
  <RETAINFOLDER>C:\</RETAINFOLDER> 
  <OVERRIDEFOLDER>C:\</OVERRIDEFOLDER> 
  <ERRORFOLDER>C:\</ERRORFOLDER> 
  <POLLINTERVAL>200 000</POLLINTERVAL> 
  <JOBBATCHFILEPATH>C:\</JOBBATCHFILEPATH> 
  <JOBBATCHPARAMS>none</JOBBATCHPARAMS> 
  <JOBLOGPATH>C:\</JOBLOGPATH> 
  <JOBEMAILTO>lodewyk.duminy@gmail.com</JOBEMAILTO> 
  <JOBALTEMAILTO>lodewyk.duminy@gmail.com</JOBALTEMAILTO> 
  </JOB>
  </APOLLERSETTINGS>

My problem is that there can be many <JOB></JOB> sets. THe only unique value they have is <JOBNAME></JOBNAME>.

1) How, if there are more than 1 <JOB></JOB> groups, do I find the right one (<JOBNAME></JOBNAME> is unique).

2) What should I use the write a value in a node,

There are some sort of web services xml bindings for java, but it seems to me that you could just treat it as a plain text file, do a search for <JOBNAME> based on a regular expression, then do your editing and write everything back out to the file again.

There are some sort of web services xml bindings for java, but it seems to me that you could just treat it as a plain text file, do a search for <JOBNAME> based on a regular expression, then do your editing and write everything back out to the file again.

I've thought of that. Finding the job name would be really easy. My problem is that I have no idea ho to replace it with the new text, though. For example, how would I replace <POLLINTERVAL>5000</POLLINTERVAL> with <POLLINTERVAL>6000</POLLINTERVAL>? (Assume I dont know that it is 5000, that it could be anything, even text)

Very carefully. For example, if you use a regular expression, use a while loop to read in all of the text until it matches the beginning tag. Now that you matched the beginning tag, you know that the text you want to replace is next. Now skip over the rest of the text until you see the ending tag (also using a regular expression to find it). You can easily keep track of where you saw the beginning and end by doing that, and it doesn't really matter *where* in the file this occurs, as long as you've stored everything else. Once you see the ending tag, add that to the info to be written back out to file, and then add everything else after the end tag as well.

Edit: The index methods shown here show you how you can tell exactly where in the file the expressions were found. So if you use the Scanner class's nextLine() method, I think the way the XML file is formatted (with each tag on a different line, right?) will make your problem easier to solve. Just read in each line, use your regular expressions to search it. Since you already know what your tag is, though, it shouldn't matter what is inbetween originally... after you find the start tag just get rid of the rest of the line, put your text after the start tag, then add on the end tag, and write that back out to the file. (this is all assuming the xml file has one open/close tag per line, ignore what I just said if that isn't always the case)

Using a XML processing library like JDOM would significantly ease your job. All you'd need to do with such a library is:
- Parse the source XML document
- Get all the JOB nodes and filter the JOB node with the given JOBNAME
- Update the child elements of the JOB element
- Save the in-memory XML back to the file

But do keep in mind that this would become unwieldy if the file becomes too large due to the overhead of reading and writing an XML document. XML IMO is a bad format for frequent reading/writing of data. An embeddable small memory footprint database like H2/Derby would shine for your given use case.

Like I mentioned originally, I was aware that what S.o.S mentioned existed (and I agree with him that it is a better idea) if you want to learn XML in the future, or have any interest in continuing with it in any way. But the quickest way to do your current task would probably be the regular methods such as Scanner and Regex rather than learn how to use JDOM.

Using a XML processing library like JDOM would significantly ease your job. All you'd need to do with such a library is:
- Parse the source XML document
- Get all the JOB nodes and filter the JOB node with the given JOBNAME
- Update the child elements of the JOB element
- Save the in-memory XML back to the file

But do keep in mind that this would become unwieldy if the file becomes too large due to the overhead of reading and writing an XML document. XML IMO is a bad format for frequent reading/writing of data. An embeddable small memory footprint database like H2/Derby would shine for your given use case.

This won't be a problem. I'm writing a program that makes it easier for end users to edit a settings file(The settings files are never very large, but the information in them have to be carefully checked before they are used, faulty settings could cause havoc for the user).

A friend sent me the following piece of code :

public void editSettings(String fileName) {
        Document doc = new Document(fileName);
        Element root = doc.getDocumentElement();
        NodeList rootlist = root.getChildNodes();
        for (int i = 0; i < rootlist.getLength(); i++) {
            Element person = (Element) rootlist.item(i);
            NodeList personlist = person.getChildNodes();

            Element name = (Element) personlist.item(0);
            NodeList namelist = name.getChildNodes();

            Text nametext = (Text) namelist.item(0);
            String oldname = nametext.getData();

            if (oldname.equals(newname)) {
                Element email = (Element) personlist.item(1);
                NodeList emaillist = email.getChildNodes();
                Text emailtext = (Text) emaillist.item(0);
                emailtext.setData(newemail);
            }
        }
}

I understand most of what is happening here, But

Document doc = new Document(fileName);

Doesn't work. Any advice on how I should create/define the document? I don't want to create a whole new xml document, as the one im trying to edit already exists.

Thanks for the help so far, guys, and thanks in advance for your help yet to come.

> Any advice on how I should create/define the document?

Here's a simple throw-away implementation in JDOM [requires jdom.jar of course]:

public static void main(String args[]) throws Exception {
   DocumentBuilder builder = DocumentBuilderFactory.newInstance()
         .newDocumentBuilder();
   DOMBuilder domBuilder = new DOMBuilder();
   Document jdomDoc = domBuilder.build(builder.parse(new File("src/home/projects/misc/Test.xml")));
   Iterator iter = jdomDoc.getRootElement().getChildren("JOB").iterator();
   while(iter.hasNext()) {
      Element jobElem = (Element)iter.next();
      if(jobElem.getChild("JOBNAME").getValue().equals("Second job")) {
         jobElem.getChild("INPUTFOLDER").setText("MY-NEW-LOCATION");
      }
   }
   XMLOutputter outputter = new XMLOutputter();
   outputter.output(jdomDoc, System.out);
}

In your case you can output or direct the XML to some other stream/file.

> But the quickest way to do your current task would probably be
> the regular methods such as Scanner and Regex

Given that I've dabbled with both XML processing API's and regular expressions, I disagree. I'd love to see a regular expression implementation of the above having the same sort of clarity and brevity. :-)

> rather than learn how to use JDOM.

I personally feel that one shouldn't shy away from using the best possible tool for the job even if it comes with a bit of learning curve. Experience has shown that implementing something in a round-a-bout way brings in too much pain and generally has a higher cost associated than learning the right tool and doing things right.

> There are some sort of web services xml bindings for java

You can very well use the XML processing libraries which implement the XML specifications without getting involved with web services i.e. XML processing != Web Services

Thanks s.o.s! You were a great help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.