Skip to content

Instantly share code, notes, and snippets.

@bmchild
Created August 22, 2013 21:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bmchild/6312814 to your computer and use it in GitHub Desktop.
Save bmchild/6312814 to your computer and use it in GitHub Desktop.
A Dom4J Utility
/**
*
*/
package com.bmchild.service.xml;
import java.io.IOException;
import java.io.InputStream;
import org.dom4j.Document;
import org.dom4j.Node;
/**
* @author bchild
*
*/
public interface XMLService {
String ENCODING = "ISO-8859-1";
/**
* Creates an XML document with the root
*
* @param root
* @param xmlMap
* @return
*/
Document createDocument(String root);
/**
* Recursive method to create an element and, if necessary, its parents and siblings
* @param document
* @param xpath to single element
* @param value if null an empty element will be created
* @return the created Node
*/
Node addElementToDocument(Document document, String xpath, String value);
/**
* Transforms one xml document to another
* @param document to transform
* @param xlsResourceName name of the transformation file
* @return transformed Document
*/
Document transformDocument(Document document, String xlsResourceName);
/**
* Gets the xml as a string
* @param document
*/
String documentToString(Document document);
/**
* Gets the input stream for the document based on default settings
* @param document
* @return
* @throws IOException
*/
InputStream getInputStream(Document document) throws IOException;
}
/**
*
*/
package com.bmchild.service.xml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.List;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.stereotype.Service;
import com.bmchild.service.xml.exception.XmlException;
/**
* @author bchild
*
*/
@Service
public class XMLServiceImpl implements XMLService {
private static final Logger LOGGER = Logger.getLogger(XMLServiceImpl.class.getName());
/* (non-Javadoc)
* @see com.bmchild.service.xml.XMLService#createDocument(java.lang.String)
*/
@Override
public Document createDocument(String root) {
return DocumentHelper.createDocument(DocumentHelper.createElement(root));
}
/* (non-Javadoc)
* @see com.bmchild.service.xml.XMLService#addElementToDocument(org.dom4j.Document, java.lang.String, java.lang.String)
*/
@Override
public Node addElementToDocument(Document document, String xpath, String value) {
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("adding Element: " + xpath + " -> " + value);
}
Element created = null;
try {
String elementName = XPathUtils.getChildElementName(xpath);
String parentXPath = XPathUtils.getParentXPath(xpath);
Integer childIndex = XPathUtils.getChildElementIndex(xpath);
Node parentNode = document.selectSingleNode(parentXPath);
if(parentNode == null) {
parentNode = addElementToDocument(document, parentXPath, null);
}
// create younger siblings if needed
if(childIndex > 1) {
List<?> nodelist = document.selectNodes(XPathUtils.createPositionXpath(xpath, childIndex));
// how many to create = (index wanted - existing - 1 to account for the new element we will create)
int nodesToCreate = childIndex - nodelist.size() - 1;
for(int i = 0; i < nodesToCreate; i++) {
((Element)parentNode).addElement(elementName);
}
}
// create requested element
created = ((Element)parentNode).addElement(elementName);
if(null != value) {
created.addText(value);
}
} catch (CreXmlException e) {
LOGGER.warn("unable to parse xpath", e);
}
return created;
}
/* (non-Javadoc)
* @see com.bmchild.service.xml.XMLService#transformDocument(org.dom4j.Document, java.lang.String)
*/
@Override
public Document transformDocument(Document document, String xlsResourceName) {
TransformerFactory factory = TransformerFactory.newInstance();
Document transformedDoc = null;
try {
InputStream stream = this.getClass().getResourceAsStream(xlsResourceName);
Transformer transformer = factory.newTransformer(new StreamSource(stream));
DocumentSource source = new DocumentSource( document );
DocumentResult result = new DocumentResult();
transformer.transform( source, result );
transformedDoc = result.getDocument();
} catch (TransformerException e) {
throw new IllegalArgumentException("error configuring transformer", e);
}
return transformedDoc;
}
/* (non-Javadoc)
* @see com.bmchild.service.xml.XMLService#printDocToDebug(org.dom4j.Document)
*/
@Override
public String documentToString(Document document) {
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding(ENCODING);
StringWriter writer = new StringWriter();
XMLWriter xmlwriter = new XMLWriter(writer, format);
String xml = null;
try {
xmlwriter.write( document );
xml = writer.getBuffer().toString();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
return xml;
}
/* (non-Javadoc)
* @see com.bmchild.service.xml.XMLService#getInputStream(org.dom4j.Document)
*/
@Override
public InputStream getInputStream(Document document) throws IOException {
InputStream input = null;
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding(ENCODING);
ByteArrayOutputStream output = new ByteArrayOutputStream();
XMLWriter xmlWriter = new XMLWriter(output, format);
xmlWriter.write(document);
input = new ByteArrayInputStream(output.toByteArray());
return input;
}
}
/**
*
*/
package com.bmchild.service.xml;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.runners.MockitoJUnitRunner;
/**
* @author bchild
*
*/
@RunWith(MockitoJUnitRunner.class)
public class XMLServiceImplTest {
private static final Logger LOGGER = Logger.getLogger(XMLServiceImplTest.class.getName());
private static final String ROOT = "root";
private static final String BASE_XPATH = "/" + ROOT + "/data";
@InjectMocks
private XMLService xmlService = new XMLServiceImpl();
@Test
public void testCreateDocument() {
Document doc = xmlService.createDocument(ROOT);
assertEquals(ROOT, doc.getRootElement().getName());
}
@Test
public void testAddElementToDocument() throws Exception {
Document doc = xmlService.createDocument(ROOT);
xmlService.addElementToDocument(doc, prependBase("/discharge_status"), "ACTIVE");
xmlService.addElementToDocument(doc, prependBase("/suspension_rec[2]/start"), "0915");
xmlService.addElementToDocument(doc, prependBase("/suspension_rec[1]/start"), "0815");
xmlService.addElementToDocument(doc, prependBase("/suspension_rec[3]/start"), "0115");
xmlService.addElementToDocument(doc, prependBase("/suspension_rec[1]/end"), "0125");
List<?> nodes = doc.selectNodes("//discharge_status");
assertEquals(1, nodes.size());
assertEquals("ACTIVE", ((Element)nodes.get(0)).getText());
nodes = doc.selectNodes("//suspension_rec");
assertEquals(3, nodes.size());
assertEquals("0915", ((Element)doc.selectSingleNode(prependBase("/suspension_rec[2]/start"))).getText());
assertEquals("0815", ((Element)doc.selectSingleNode(prependBase("/suspension_rec[1]/start"))).getText());
assertEquals("0115", ((Element)doc.selectSingleNode(prependBase("/suspension_rec[3]/start"))).getText());
assertEquals("0125", ((Element)doc.selectSingleNode(prependBase("/suspension_rec[1]/end"))).getText());
if(LOGGER.isDebugEnabled()) {
printDoc(doc);
}
}
/**
* @param string
* @return
*/
private String prependBase(String string) {
return BASE_XPATH + string;
}
/**
* prints the xml to the LOGGER
* @param document
*/
private String printDoc(Document document) {
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("ISO-8859-1");
StringWriter writer = new StringWriter();
XMLWriter xmlwriter = new XMLWriter(writer, format);
String xml = null;
try {
xmlwriter.write( document );
xml = writer.getBuffer().toString();
LOGGER.debug("generated xml: \n" + xml);
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
return xml;
}
@Test
public void testDocumentToString() throws Exception {
Document doc = xmlService.createDocument(ROOT);
String docString = xmlService.documentToString(doc);
assertTrue(docString.contains(ROOT));
}
@Test
public void testGetInputStream() throws Exception {
Document doc = xmlService.createDocument(ROOT);
InputStream in = xmlService.getInputStream(doc);
StringWriter writer = new StringWriter();
IOUtils.copy(in, writer);
assertTrue(writer.toString().contains(ROOT));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment