well, I admitted that org.w3c.dom (or DOM) is quite difficult to use than the popular dom4j (see here).
But sometimes, it might be problem for us to include new libraries in source code due to library confliction or license issues. For example, a big project is developed by various people independently. If all people use different libraries to parse xml, your product will finally turned out to be very complex to maintain.
So sometimes using the standard package in JDK (like JAXP) is the only choice, though difficult.
Here I demo some examples on how to use it for common purpose.
XMLIOUtilityimport java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
Author : ye_m
Date: Oct.18,2011
Company : Works Applications. Co.Ltd.
*/
public class XMLIOUtility {
public static Document readFromFile(String filename) {
FileInputStream ins = null;
Document doc = null;
try {
ins = new FileInputStream(filename);
doc = readFromStream(ins);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
silentClose(ins);
}
return doc;
}
public static Document readFromStream(InputStream ins) {
DocumentBuilderFactory domFactory = DocumentBuilderFactory
.newInstance();
domFactory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder;
Document doc = null;
try {
builder = domFactory.newDocumentBuilder();
doc = builder.parse(ins);
return doc;
} catch (ParserConfigurationException e) {
} catch (SAXException e) {
} catch (IOException e) {
}
return doc;
}
public static void saveToStream(Document doc, OutputStream stream) {
try {
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(
"{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(stream);
transformer.transform(source, result);
} catch (TransformerConfigurationException tce) {
} catch (TransformerException te) {
}
}
public static void saveToFile(Document doc, String filename) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filename);
saveToStream(doc, fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
silentClose(fos);
}
}
public static void silentClose(InputStream ins) {
if (ins != null) {
try {
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void silentClose(OutputStream wr) {
if (wr != null) {
try {
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static String getNodeText(Node node) {
String value = "";
if (node != null) {
Node first = null;
while ((first = node.getFirstChild()) != null) {
if (first.getNodeType() == Node.TEXT_NODE) {
value = first.getNodeValue().trim();
break;
}
}
}
return value;
}
}
With above code, it becomes easier for you to manipulate XML files.
Here is something important.
Usually, the output format of XML file by DOM is very ugly, with does not change lines or insert indent automatically. So you need to pay attention to the following lines in the method which print out xml files.
XMLIOUtilityTransformer transformer = tFactory.newTransformer();
// create this attribute to enable "auto-line-wrap" function
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// create this attribute (in JDK1.4 only) to enable "auto indent" function
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
OK, I will also paste an example.
XMLResourceBundle class is convinient. But it is only supported by at least JDK1.5. Now I implemented a XMLResourceBundle class by JDK1.4 using DOM.
XMLResourceBundle
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import jp.co.worksap.durga.performance.applaunch.tool.HintUtility;
import jp.co.worksap.durga.performance.applaunch.tool.XMLIOUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
Author : ye_m
Date: Oct.18, 2011
Company : Works Applications.
*/
public class XMLResourceBundle extends ResourceBundle {
private File configFile;
private InputStream ins;
private boolean isReady;
private Logger log;
private OutputStream outs;
private Properties props;
public XMLResourceBundle(final String filename) {
this(filename, null);
}
public XMLResourceBundle(final String filename, final Class myLoader) {
super();
log = LoggerFactory.getLogger(getClass());
if (myLoader != null) {
InputStream ins = null;
for (int i = 0; i < 4; i++) {
ins = myLoader.getResourceAsStream(filename);
if (ins != null) {
isReady = init(ins, null);
break;
}
}
if (ins == null) {
isReady = false;
HintUtility.errorHint(false,
"Cannot Find Resource File under filename=" + filename,
"Error", log);
} else {
isReady = true;
}
} else {
if (!checkFile(filename)) {
isReady = false;
return;
}
isReady = init(new File(filename));
}
}
private boolean checkFile(String filename) {
if (!filename.toLowerCase().trim().endsWith(".xml")) {
return false;
}
File test = new File(filename);
if (!test.exists()) {
props = new Properties();
XMLIOUtility.saveToFile(parsePropsToDoc(), filename);
}
if (test.isDirectory()) {
return false;
}
return true;
}
public Enumeration getKeys() {
if (!isReady) {
return null;
}
Vector keys = new Vector();
for (Enumeration srckeys = props.propertyNames(); srckeys
.hasMoreElements();) {
keys.add(srckeys.nextElement().toString());
}
return keys.elements();
}
protected Object handleGetObject(String key) {
if (!isReady) {
return null;
}
return props.getProperty(key);
}
private boolean init(final File file) {
configFile = file;
return loadFromFile();
}
private boolean init(final InputStream configStream,
final OutputStream saveStream) {
ins = configStream;
outs = saveStream;
props = parseDocToProps(XMLIOUtility.readFromStream(ins));
return true;
}
public boolean isReady() {
return isReady;
}
private boolean loadFromFile() {
props = parseDocToProps(XMLIOUtility.readFromFile(configFile.getPath()));
return true;
}
private Properties parseDocToProps(Document doc) {
Properties props = new Properties();
if (doc != null) {
NodeList list = doc.getDocumentElement().getElementsByTagName(
"entry");
for (int i = 0; i < list.getLength(); i++) {
Element ele = (Element) list.item(i);
String key = ele.getAttribute("key").trim();
String value = XMLIOUtility.getNodeText(ele);
props.setProperty(key, value);
}
}
return props;
}
private Document parsePropsToDoc() {
DocumentBuilderFactory domFactory = DocumentBuilderFactory
.newInstance();
Document document = null;
try {
DocumentBuilder builder = domFactory.newDocumentBuilder();
builder.setErrorHandler(null);
DocumentType type = builder.getDOMImplementation()
.createDocumentType("properties", null,
"http://java.sun.com/dtd/properties.dtd");
document = builder.getDOMImplementation().createDocument(
"http://java.sun.com/dtd/properties.dtd", "properties",
type);
Element root = document.getDocumentElement();
Iterator iter = props.keySet().iterator();
String key = null;
while (iter.hasNext()) {
key = (String) iter.next();
String value = (String) props.getProperty(key);
Element child = document.createElement("entry");
Attr keyAttr = document.createAttribute("key");
keyAttr.setValue(key);
child.setAttributeNode(keyAttr);
Text text = document.createTextNode(value);
child.appendChild(text);
root.appendChild(child);
}
document.getDocumentElement().normalize();
} catch (ParserConfigurationException e) {
}
return document;
}
public void save() {
if (configFile != null) {
XMLIOUtility.saveToFile(parsePropsToDoc(), configFile.getPath());
} else if (outs != null) {
XMLIOUtility.saveToStream(parsePropsToDoc(), outs);
} else {
// No perfmit to Write
}
}
public void setNewValue(final String key, final Object obj) {
if ((isReady) && (key != null) && (obj != null)) {
props.put(key, obj.toString());
}
}
public Object removeValue(final String key) {
if ((isReady) && (key != null)) {
return props.remove(key);
}
return null;
}
}
.The Class HintUtility did nothing but invoking System.out.println() to print messages.
没有评论:
发表评论