Using XML in a Java Context - Modifying an XML Document
(Page 2 of 5 )
The next project, the ChangeDomains application, makes several changes to the XML document that was just produced, domains.xml. The text enclosed by the ttl element is changed from 86400 to 604800, and a new email element is added:
<email>
<address user=postmaster@java21days.com
destination="rcade" />
</email>
Using the nu.xom package, XML documents can be loaded into a tree from several sources: a File, InputStream, Reader, or a URL (which is specified as a String instead of a java.net.URL object).
The Builder class represents a SAX parser that can load an XML document into a Document object. Constructor methods can be used to specify a particular parser or let XOM use the first available parser from this list: Xerces 2, Crimson, Piccolo, GNU Aelfred, Oracle, XP, Saxon Aelfred, or Dom4J Aelfred. If none of these is found, the parser specified by the system property org.xml.sax.driver is used. Constructors also determine whether the parser is validating or nonvalidating.
The Builder() and Builder(true) constructors both use the default parser—most likely a version of Xerces. The presence of the Boolean argument true in the second constructor configures the parser to be validating. It would be nonvalidating otherwise. A validating parser throws a nu.xom.ValidityException if the XML document doesn't validate according to the rules of its document type declaration.
The Builder object's build() method loads an XML document from a source and returns a Document object:
Builder builder = new Builder();
File xmlFile = new File("domains.xml");
Document doc = builder.build(xmlFile);
These statements load an XML document from the file domains.xml barring one of two problems: a nu.xom.ParseException is thrown if the file does not contain well-formed XML, and a java.io.IOException is thrown if the input operation fails.
Elements are retrieved from the tree by calling a method of their parent node.
A Document object's getRootElement() method returns the root element of the document:
Element root = doc.getRootElement();
In the XML document domains.xml, the root element is domains.
Elements with names can be retrieved by calling their parent node's getFirst ChildElement() method with the name as a String argument:
Element name = domain.getFirstChildElement("name");
This statement retrieves the name element contained in the domain element (or null if that element could not be found). Like other examples, this is simplified by the lack of a namespace in the document; there are also methods where a name and namespace are arguments.
When several elements within a parent have the same name, the parent node's getChildElements() method can be used instead:
Elements rootChildren =
root.getChildElements("domain");
The getChildElements() method returns an Elements object containing each of the elements. This object is a read-only list and does not change automatically if the parent node's contents change after getChildElements() is called.
Elements has a size() method containing an integer count of the elements it holds. This can be used in a loop to cycle through each element in turn beginning with the one at position 0. There's a get() method to retrieve each element; call it with the integer position of the element to be retrieved:
Elements rootChildren =
root.getChildElements("domain");
for (int i = 0; i < rootChildren.size(); i++) {
Element domain = rootChildren.get(i);
}
This for loop cycles through each domain element that's a child of the root element domains (the domains.xml document contains only one.
Elements without names can be retrieved by calling their parent node's getChild() method with one argument: an integer indicating the element's position within the parent node:
Text nameText = (Text) name.getChild(0);
This statement creates the Text object for the text "java21days.com" found within the name element. Text elements always will be at position 0 within their enclosing parent.
To work with this text as a String, call the Text object's getValue() method, as in this statement:
if (nameText.getValue().equals("java21days.com"))
updateDomain(domain);
The ChangeDomain application only modifies a domain element if its name element encloses the text "java21days.com". The application makes the following changes: the text of the ttl element is deleted, the new text "604800" is added in its place, and then a new email element is added.
A parent node has two removeChild() methods to delete a child node from the document. Calling the method with an integer deletes the child at that position:
Element dns = domain.getFirstChildElement("dns");
Element ttl = dns.getFirstChildElement("ttl");
ttl.removeChild(0);
These statements delete the Text object contained within the ttl element.
Calling the removeChild() method with a node as an argument deletes that particular node. Extending the previous example, the ttl element could be deleted with this statement:
dns.removeChild(ttl);
Listing 20.8 shows the source code of the ChangeDomains application.
Listing 20.8 The Full Text of ChangeDomains.java
1: import java.io.*;
2: import nu.xom.*;
3:
4: public class ChangeDomains {
5: public static void main(String[] arguments)
throws IOException {
6: try {
7: // Create a tree from the XML document
domains.xml
8: Builder builder = new Builder();
9: File xmlFile = new File("domains.xml");
10: Document doc = builder.build(xmlFile);
11:
12: // Get the root element <domains>
13: Element root = doc.getRootElement();
14:
15: // Loop through of its <domain> elements
16: Elements rootChildren =
root.getChildElements("domain");
17: for (int i = 0; i < rootChildren.size();
i++) {
18:
19: // Get a <domain> element
20: Element domain = rootChildren.get(i);
21:
22: // Get its <name> element and the text
it encloses
23: Element name =
domain.getFirstChildElement("name");
24: Text nameText = (Text) name.getChild(0);
25:
26: // Update any domain with the <name>
text "java21days.com"
27: if (nameText.getValue().equals
("java21days.com"))
28: updateDomain(domain);
29: }
30:
31: // Display the XML document
32: System.out.println(doc.toXML());
33: } catch (ParsingException pe) {
34: System.out.println("Error: " +
pe.getMessage());
35: pe.printStackTrace();
36: System.exit(-1);
37: }
38: }
39:
40: private static void
updateDomain(Element domain) {
41: // Get the domain's <dns> element
42: Element dns =
domain.getFirstChildElement("dns");
43:
44: // Get its <ttl> element
45: Element ttl =
dns.getFirstChildElement("ttl");
46:
47: // Replace its Text child with "604800"
48: ttl.removeChild(0);
49: ttl.appendChild("604800");
50:
51: // Create new elements and attributes to add
52: Element email = new Element("email");
53: Element address = new Element("address");
54: Attribute user =
new Attribute("user", "postmaster@java21days.com");
55: Attribute destination =
new Attribute("destination", "rcade");
56:
57: // Add them to the <domain> element
58: domain.appendChild(email);
59: email.appendChild(address);
60: address.addAttribute(user);
61: address.addAttribute(destination);
62: }
63: }
The ChangeDomains application displays the modified XML document to standard output, so it can be run with the following command to produce a file named domains2.xml:
java ChangeDomains > domains2.xml
Next: Formatting an XML Document >>
More Java Articles
More By Sams Publishing
|
This article is excerpted from chapter 20 of the book Sams Teach Yourself Java 2 in 21 Days, 4th Edition, written by Rogers Cadenhead and Laura Lemay (Sams; ISBN: 0672326280). Check it out today at your favorite bookstore. Buy this book now.
|
|