/* ===============================================================================
*
* Part of the InfoGlue Content Management Platform (www.infoglue.org)
*
* ===============================================================================
*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2, as published by the
* Free Software Foundation. See the file LICENSE.html for more information.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
* Place, Suite 330 / Boston, MA 02111-1307 / USA.
*
* ===============================================================================
*/
package org.infoglue.cms.util;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.util.XMLChar;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* This class is an utility class meant to be filled with reusable snippets of code concerning handling of XML
* in different shapes. No application specific code can be put here!!!
*
* @author Mattias Bogeblad
*/
public class XMLHelper
{
/**
* Serializes the DOM-tree to a stringBuffer. Recursive method!
*
* @param node Node to start examining the tree from.
* @param writeString The StringBuffer you want to fill with xml.
* @return The StringBuffer containing the xml.
*
* @since 2002-12-12
* @author Mattias Bogeblad
*/
public static StringBuffer serializeDom(Node node, StringBuffer writeString)
{
int type = node.getNodeType();
try
{
switch (type)
{
// print the document element
case Node.DOCUMENT_NODE:
{
writeString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
writeString = serializeDom(((Document)node).getDocumentElement(), writeString);
break;
}
// print element with attributes
case Node.ELEMENT_NODE:
{
writeString.append("<");
writeString.append(node.getNodeName());
NamedNodeMap attrs = node.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
Node attr = attrs.item(i);
String outString = " " + attr.getNodeName() + "=\"" + replaceSpecialCharacters(attr.getNodeValue()) + "\"";
writeString.append(outString);
}
writeString.append(">");
NodeList children = node.getChildNodes();
if (children != null)
{
int len = children.getLength();
for (int i = 0; i < len; i++)
writeString = serializeDom(children.item(i), writeString);
}
break;
}
// handle entity reference nodes
case Node.ENTITY_REFERENCE_NODE:
{
String outString = "&" + node.getNodeName() + ";";
writeString.append(outString);
break;
}
// print cdata sections
case Node.CDATA_SECTION_NODE:
{
String outString = "<![CDATA[" + node.getNodeValue() + "]]>";
writeString.append(outString);
break;
}
// print text
case Node.TEXT_NODE:
{
writeString.append(replaceSpecialCharacters(node.getNodeValue()));
break;
}
// print processing instruction
case Node.PROCESSING_INSTRUCTION_NODE:
{
String data = node.getNodeValue();
String outString = "<?" + node.getNodeName() + " " + data + "?>";
writeString.append(outString);
break;
}
}
if (type == Node.ELEMENT_NODE)
{
String outString = "</" + node.getNodeName() + ">";
writeString.append(outString);
}
}
catch (Exception e)
{
}
return writeString;
}
/**
* This method replaces special character with their xml-counterpart.
*/
public static String replaceSpecialCharacters(String value)
{
if(value == null)
return "";
StringBuffer newValue = new StringBuffer();
for (int i = 0; i < value.length(); i++)
{
char c = value.charAt(i);
if (c == '&')
{
newValue.append("&");
}
else if (c == '<')
{
newValue.append("<");
}
else if (c == '>')
{
newValue.append(">");
}
else if (c == '\'')
{
newValue.append("'");
}
else if (c == '\"')
{
newValue.append(""");
}
else
{
if(isLegalCharacter((int)c))
newValue.append(c);
}
}
return newValue.toString();
}
private static boolean isLegalCharacter(int ch)
{
return ch == 0x9 || ch == 0xA || ch == 0xD || (ch >= 0x20 && ch <= 0xFFFD) || (ch >= 0x1000 && ch <= 0x7FFFFFFF);
}
public static String stripInvalidXmlCharacters(String input)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (XMLChar.isValid(c)) {
sb.append(c);
}
}
return sb.toString();
}
/**
* This method fetches the document-root(DOM) from a xml-document located on disc specified
* by user argument.
*
* @since 2002-12-16
* @author Mattias Bogeblad
*/
public static Document readDocumentFromFile(File xmlFile) throws IOException, SAXException
{
InputSource xmlSource = new InputSource(new FileReader(xmlFile));
DOMParser parser = new DOMParser();
parser.parse(xmlSource);
return parser.getDocument();
}
/**
* This method fetches the document-root(DOM) from a xml-document located in a byte[] specified
* by user argument.
*
* @since 2002-12-16
* @author Mattias Bogeblad
*/
public static Document readDocumentFromByteArray(byte[] xml) throws IOException, SAXException
{
InputSource xmlSource = new InputSource(new BufferedInputStream(new ByteArrayInputStream(xml)));
DOMParser parser = new DOMParser();
parser.parse(xmlSource);
Document document = parser.getDocument();
parser = null;
return document;
}
}