org.sakaiproject.tool.assessment.qti.util.XmlStringBuffer Maven / Gradle / Ivy
/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/sam/tags/sakai-10.2/samigo-qti/src/java/org/sakaiproject/tool/assessment/qti/util/XmlStringBuffer.java $
* $Id: XmlStringBuffer.java 305964 2014-02-14 01:05:35Z [email protected] $
***********************************************************************************
*
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.sakaiproject.tool.assessment.qti.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.collections.ReferenceMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.jaxen.dom.DOMXPath;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.DOMOutputter;
import org.w3c.dom.Attr;
import org.w3c.dom.CharacterData;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.SAXException;
/**
* Copyright: Copyright (c) 2004
* Organization: Sakai Project
* @author rshastri
* @author Ed Smiley [email protected]
* @version $Id: XmlStringBuffer.java 305964 2014-02-14 01:05:35Z [email protected] $
*/
public class XmlStringBuffer
implements java.io.Serializable
{
private static Log log = LogFactory.getLog(XmlStringBuffer.class);
/**
* Explicitly setting serialVersionUID insures future versions can be
* successfully restored. It is essential this variable name not be changed
* to SERIALVERSIONUID, as the default serialization methods expects this
* exact name.
*/
private static final long serialVersionUID = 1;
//The following need not be persisted and so are declared transient
private transient Document document = null;
private transient DocumentBuilder builder = null;
private transient ReferenceMap cache = null;
private StringBuffer xml;
/**
* Constructor to be accessed by subclasses.
*/
protected XmlStringBuffer()
{
this.xml = new StringBuffer();
}
/**
* Constructs an XmlStringBuffer whose initial value is String.
*
* @param xml XML string
*/
public XmlStringBuffer(String xml)
{
this.xml = new StringBuffer(xml);
}
/**
* Constructs an XmlStringBuffer whose initial value is Document
*
* @param document XML document
*/
public XmlStringBuffer(Document document)
{
this.document = document;
}
/**
* Constructs an XmlStringBuffer whose initial value is Document
*
* @param jdomDoc
*
* @deprecated using XmlStringBuffer(org.w3c.dom.Document document) instead.
*/
public XmlStringBuffer(org.jdom.Document jdomDoc)
{
try
{
this.document = new DOMOutputter().output(jdomDoc);
}
catch(JDOMException e)
{
log.error(e.getMessage(), e);
}
}
/**
* Clears the xml
*/
public final void clear()
{
this.xml.setLength(0);
this.reset();
}
/**
* replace the current xml with the given string
*
* @param xml XML replacement string
*
* @deprecated
*/
public final void replace(String xml)
{
this.xml = new StringBuffer(xml);
this.reset();
}
/**
* Get a document
*
* @return document
*
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
public final Document getDocument()
throws ParserConfigurationException, SAXException, IOException
{
if(this.document == null)
{
this.parseContent();
}
return this.document;
}
/**
* internal
*
* @return reference map
*/
private ReferenceMap getCache()
{
if(this.cache == null)
{
this.cache = new ReferenceMap();
}
return this.cache;
}
/**
* inernal, clear cache
*/
private void clearCache()
{
if(this.cache == null)
{
this.cache = new ReferenceMap();
}
else
{
this.cache.clear();
}
}
/**
* parse content to JDOM
*
* @return JDOM document
*
* @throws JDOMException =
* @throws IOException
*/
/*
private final org.jdom.Document parseContentToJDOM()
throws JDOMException, IOException
{
if(log.isDebugEnabled())
{
log.debug("parseContentToJDOM()");
}
String xmlString = this.stringValue();
org.jdom.Document result = null;
try
{
SAXBuilder saxbuilder = new SAXBuilder();
result = saxbuilder.build(new StringReader(xmlString));
}
catch(JDOMException ex)
{
log.error("Exception thrown while parsing XML:\n" + ex.getMessage(), ex);
throw ex;
}
catch(IOException ie)
{
log.error("Exception thrown while parsing XML:\n" + ie.getMessage(), ie);
throw ie;
}
return result;
}
*/
/**
* parse the content
*
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
private final void parseContent()
throws ParserConfigurationException, SAXException, IOException
{
if(log.isDebugEnabled())
{
log.debug("parseContent()");
}
this.clearCache();
DocumentBuilderFactory dbfi = null;
DocumentBuilder builder = null;
StringReader sr = null;
org.xml.sax.InputSource is = null;
try
{
dbfi = DocumentBuilderFactory.newInstance();
builder = dbfi.newDocumentBuilder();
String s = this.xml.toString();
if (s==null)
{
log.warn("string value null");
s = "";
}
sr = new StringReader(s);
is = new org.xml.sax.InputSource(sr);
this.document = builder.parse(is);
}
catch(ParserConfigurationException e)
{
log.error(e.getMessage(), e);
throw e;
}
catch(SAXException e)
{
log.error(e.getMessage(), e);
log.error("DocumentBuilderFactory dbfi = " + dbfi);
log.error("StringReader sr = " + sr);
log.error("InputSource is = " + is);
log.error("StringBuffer xml = " + this.xml);
throw e;
}
catch(IOException e)
{
log.error(e.getMessage(), e);
throw e;
}
}
/**
* string value of document
*
* @return the string
*/
public final String stringValue()
{
if(log.isDebugEnabled())
{
log.debug("stringValue()");
}
if(document == null)
{
return this.xml.toString();
}
else
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
DOMImplementationRegistry registry = DOMImplementationRegistry
.newInstance();
DOMImplementationLS impl = (DOMImplementationLS) registry
.getDOMImplementation("LS");
LSSerializer writer = impl.createLSSerializer();
writer.getDomConfig().setParameter("format-pretty-print",
Boolean.TRUE);
LSOutput output = impl.createLSOutput();
output.setByteStream(out);
writer.write(document, output);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return out.toString();
}
}
/**
* is the xml empty?
*
* @return true/false
*/
public final boolean isEmpty()
{
return ((this.xml == null) || (this.xml.length() == 0));
}
/**
*
*/
private void reset()
{
this.document = null;
this.cache = null;
}
/**
* xpath lookup
*
* @param xpath
* @param type
*
* @return value
*/
public String selectSingleValue(String xpath, String type)
{
// user passes the if its an element or attribute
String value = null;
List list = this.selectNodes(xpath);
if(list != null)
{
int no = list.size();
if(list.size() > 0)
{
if((type != null) && type.equals("element"))
{
Element element = (Element) list.get(0);
CharacterData elementText =
(CharacterData) element.getFirstChild();
Integer getTime = null;
if(
(elementText != null) && (elementText.getNodeValue() != null) &&
(elementText.getNodeValue().trim().length() > 0))
{
value = elementText.getNodeValue();
}
}
if((type != null) && type.equals("attribute"))
{
Attr attr = (Attr) list.get(0);
CharacterData elementText =
(CharacterData) attr.getFirstChild();
Integer getTime = null;
if(
(elementText != null) && (elementText.getNodeValue() != null) &&
(elementText.getNodeValue().trim().length() > 0))
{
value = elementText.getNodeValue();
}
}
}
}
return value;
}
/**
* get nodes
*
* @param xpath
*
* @return list of nodes
*/
public final List selectNodes(String xpath)
{
if(log.isDebugEnabled())
{
log.debug("selectNodes(String " + xpath + ")");
}
List result = null;
try
{
XPath path = new DOMXPath(xpath);
result = path.selectNodes(this.getDocument());
}
catch(JaxenException je)
{
log.error(je.getMessage(), je);
}
catch(ParserConfigurationException e)
{
log.error(e.getMessage(), e);
}
catch(SAXException e)
{
log.error(e.getMessage(), e);
}
catch(IOException e)
{
log.error(e.getMessage(), e);
}
if (result == null) {
result = new ArrayList();
}
return result;
}
public String getValueOf(String xpath) {
try {
XPath path = new DOMXPath(xpath);
return path.stringValueOf(this.getDocument());
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
/**
* perform Update on this object
*
* @param xpath :- xpath and
* @param value :- Value of xpath
*
* @return XmlStringBuffer
*
* @throws DOMException
* @throws Exception
*/
// Rashmi Aug 19th changed by Pamela on Sept 10th.
// Rashmi - replacing updateJDOM as on Sep 15
public final XmlStringBuffer update(String xpath, String value)
throws DOMException, Exception
{
if(log.isDebugEnabled())
{
log.debug("update(String " + xpath + ", String " + value + ")");
}
try
{
Element newElement = null;
Attr newAttribute = null;
List newElementList = this.selectNodes(xpath);
//only look at the last part of the path
int aIndex = xpath.lastIndexOf("/");
if(aIndex == -1){
aIndex = 0;
}
aIndex = xpath.indexOf("@", aIndex);
int size = newElementList.size();
if(size > 1)
{
log.info("UPDATING MORE THAN ONE ELEMENT");
}
if((aIndex == -1) && (size != 0))
{
for(int i = 0; i < size; i++)
{
newElement = (Element) newElementList.get(i);
Node childNode = newElement.getFirstChild();
if(childNode == null)
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Text newElementText = document.createTextNode(newElement.getNodeName());
newElementText.setNodeValue(value);
Text clonedText =
(Text) newElement.getOwnerDocument().importNode(
newElementText, true);
newElement.appendChild(clonedText);
}
else
{
CharacterData newElementText =
(CharacterData) newElement.getFirstChild();
newElementText.setNodeValue(value);
}
}
}
if((aIndex != -1) && (size != 0))
{
newAttribute = (Attr) newElementList.set(0, null);
if(newAttribute != null)
{
newAttribute.setValue(value);
}
}
}
catch(Exception ex)
{
log.error(ex.getMessage(), ex);
}
return this;
}
/**
* update element, xpath
*
* @param xpath
* @param element
*/
public final void update(String xpath, Element element)
{
if(log.isDebugEnabled())
{
log.debug("update(String " + xpath + ", Element " + element + ")");
}
List itemResults = this.selectNodes(xpath);
Iterator iterator = itemResults.iterator();
while(iterator.hasNext())
{
Element node = (Element) iterator.next();
Element replacement =
(Element) node.getOwnerDocument().importNode(element, true);
node.getParentNode().replaceChild(replacement, node);
}
if(itemResults.size() == 0)
{
String parentPath = xpath.substring(0, xpath.lastIndexOf("/"));
addElement(parentPath, element);
}
}
/**
* DOCUMENT ME!
*
* @param xpath
* @param element
*
* @deprecated addElement(String, org.w3c.dom.Element)
*/
public final void addJDOMElement(String xpath, org.jdom.Element element)
{
try
{
List nodes = this.selectNodes(xpath);
int size = nodes.size();
for(int i = 0; i < size; i++)
{
org.jdom.Element node = (org.jdom.Element) nodes.get(i);
node.addContent(element);
}
}
catch(Exception ex)
{
log.error(ex.getMessage(), ex);
}
}
/**
* insert element
*
* @param afterNode
* @param parentXpath
* @param childXpath
*/
public void insertElement(
String afterNode, String parentXpath, String childXpath)
{
try {
String nextXpath = parentXpath + "/" + afterNode;
//*************************************************************
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Element element = document.createElement(childXpath);
//**************************************************************
Element parent = null;
List parentNodes = this.selectNodes(parentXpath);
Iterator iteratorNext = parentNodes.iterator();
while(iteratorNext.hasNext())
{
parent = (Element) iteratorNext.next();
}
if(parent != null)
{
List nodes = this.selectNodes(nextXpath);
Iterator iterator = nodes.iterator();
Element nextSibling = null;
while(iterator.hasNext())
{
nextSibling = (Element) iterator.next();
}
if(
(nextSibling != null) &&
! nextSibling.getOwnerDocument().equals(element.getOwnerDocument()))
{
element = (Element) parent.getOwnerDocument().importNode(element, true);
parent.insertBefore(element, nextSibling);
}
}
} catch(ParserConfigurationException pce) {
log.error("Exception thrown from insertElement() : " + pce.getMessage());
pce.printStackTrace();
}
}
/**
*
*
* @param parentXpath
* @param childXpath
*/
public final void add(String parentXpath, String childXpath)
{
Element childElement = createChildElement(childXpath);
this.addElement(parentXpath, childElement);
}
/**
* create child
*
* @param childXpath
*
* @return
*/
protected final Element createChildElement(String childXpath)
{
int index = childXpath.indexOf("/");
String elementName = childXpath;
String subChildXpath = null;
Element element = null;
Element child = null;
if(index > 0)
{
elementName = childXpath.substring(0, index);
subChildXpath = childXpath.substring(index + 1);
child = createChildElement(subChildXpath);
}
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
element = document.createElement(elementName);
if(child != null)
{
Node importedNode = document.importNode(child, true);
element.appendChild(importedNode);
}
} catch(ParserConfigurationException pce) {
log.error("Exception thrown from createChildElement(): " + pce.getMessage());
pce.printStackTrace();
}
return element;
}
/**
* add element
*
* @param parentXpath
* @param element
*/
public final void addElement(String parentXpath, Element element)
{
if(log.isDebugEnabled())
{
log.debug(
"addElement(String " + parentXpath + ", Element " + element + ")");
}
List nodes = this.selectNodes(parentXpath);
for(Element parent: nodes){
if(! parent.getOwnerDocument().equals(element.getOwnerDocument()))
{
element = (Element) parent.getOwnerDocument().importNode(element, true);
}
parent.appendChild(element);
}
}
/**
* add attribute
*
* @param elementXpath
* @param attributeName
*/
public final void addAttribute(String elementXpath, String attributeName)
{
if(log.isDebugEnabled())
{
log.debug(
"addAttribute(String " + elementXpath + ", String" + attributeName +
")");
}
List nodes = this.selectNodes(elementXpath);
int size = nodes.size();
for(int i = 0; i < size; i++)
{
Element element = (Element) nodes.get(i);
element.setAttribute(attributeName, "");
}
}
/**
* remove element
*
* @param xpath
*/
public final void removeElement(String xpath)
{
if(log.isDebugEnabled())
{
log.debug("removeElement(String " + xpath + ")");
}
List nodes = this.selectNodes(xpath);
Iterator iterator = nodes.iterator();
while(iterator.hasNext())
{
Node node = (Node) iterator.next();
Node parent = node.getParentNode();
parent.removeChild(node);
}
}
/**
* Synchronizes object prior to serialization
*
* @param out ObjectOutputStream
*
* @throws IOException
*/
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
{
if(log.isDebugEnabled())
{
log.debug("writeObject(ObjectOutputStream " + out + ")");
}
this.xml = new StringBuffer(this.stringValue());
out.defaultWriteObject();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy