| /* |
| * Copyright (c) 2002 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM - Initial API and implementation |
| * Jens Lukowski/Innoopract - initial renaming/restructuring |
| * |
| */ |
| package org.eclipse.wst.xml.core.internal.contentmodel.util; |
| |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.io.UnsupportedEncodingException; |
| import java.io.Writer; |
| |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.CDATASection; |
| import org.w3c.dom.Comment; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentType; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.ProcessingInstruction; |
| import org.w3c.dom.Text; |
| |
| |
| /** |
| * This is a hacked up dom writer stolen from a Xerces sample. |
| * I'd like to use an exisitng 'generic DOM' writer |
| * If anyone can find such a thing then please go ahead and junk this. |
| * |
| * @version |
| */ |
| public class DOMWriter |
| { |
| protected boolean formattingEnabled = true; |
| protected boolean outputDoctypeEnabled = true; |
| protected PrintWriter out; |
| protected int indent = 0; |
| |
| public DOMWriter() throws UnsupportedEncodingException |
| { |
| this(System.out); |
| } |
| |
| public DOMWriter(OutputStream outputSteam) |
| { |
| out = new PrintWriter(outputSteam); |
| } |
| |
| public DOMWriter(Writer writer) |
| { |
| out = new PrintWriter(writer); |
| } |
| |
| public void setFormattingEnabled(boolean enabled) |
| { |
| formattingEnabled = enabled; |
| } |
| |
| public boolean getFormattingEnabled() |
| { |
| return formattingEnabled; |
| } |
| |
| public void setOutputDoctypeEnabled(boolean enabled) |
| { |
| outputDoctypeEnabled = enabled; |
| } |
| |
| public class XMLVisitor |
| { |
| protected boolean currentElementHasChildElements = false; |
| |
| public void visitNode(Node node) |
| { |
| switch (node.getNodeType()) |
| { |
| case Node.ATTRIBUTE_NODE : |
| { |
| visitAttr((Attr)node); |
| break; |
| } |
| case Node.CDATA_SECTION_NODE : |
| { |
| visitCDATASection((CDATASection)node); |
| break; |
| } |
| case Node.COMMENT_NODE : |
| { |
| visitComment((Comment)node); |
| break; |
| } |
| case Node.DOCUMENT_NODE : |
| { |
| visitDocument((Document)node); |
| break; |
| } |
| case Node.DOCUMENT_TYPE_NODE : |
| { |
| visitDocumentType((DocumentType)node); |
| break; |
| } |
| case Node.ELEMENT_NODE : |
| { |
| visitElement((Element)node); |
| break; |
| } |
| case Node.PROCESSING_INSTRUCTION_NODE : |
| { |
| visitProcessingInstruction((ProcessingInstruction)node); |
| break; |
| } |
| case Node.TEXT_NODE : |
| { |
| visitText((Text)node); |
| break; |
| } |
| } |
| } |
| |
| public void visitDocument(Document document) |
| { |
| visitChildNodesHelper(document); |
| } |
| |
| public void visitDocumentType(DocumentType doctype) |
| { |
| if (outputDoctypeEnabled) |
| { |
| String data = getDocumentTypeData(doctype); |
| print("<!DOCTYPE " + data + ">"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| public void visitElement(Element element) |
| { |
| if (!doShow(element)) |
| return; |
| |
| boolean parentElementHasChildNodes = currentElementHasChildElements; |
| currentElementHasChildElements = hasChildElements(element); |
| |
| printIndent(); |
| print("<"); //$NON-NLS-1$ |
| print(element.getNodeName()); |
| visitAttributesHelper(element); |
| |
| boolean hasChildNodes = element.getChildNodes().getLength() > 0; |
| boolean isRootElement = element.getParentNode().getNodeType() == Node.DOCUMENT_NODE; |
| if (hasChildNodes || isRootElement) |
| { |
| if (currentElementHasChildElements || isRootElement) |
| { |
| println(">"); //$NON-NLS-1$ |
| } |
| else |
| { |
| print(">"); //$NON-NLS-1$ |
| } |
| indent += 2; |
| visitChildNodesHelper(element); |
| indent -= 2; |
| |
| if (currentElementHasChildElements || isRootElement) |
| { |
| printIndent(); |
| } |
| print("</"); //$NON-NLS-1$ |
| print(element.getNodeName()); |
| println(">"); //$NON-NLS-1$ |
| } |
| else |
| { |
| println("/>"); //$NON-NLS-1$ |
| } |
| |
| currentElementHasChildElements = parentElementHasChildNodes; |
| } |
| |
| public void visitAttr(Attr attr) |
| { |
| print(" "); //$NON-NLS-1$ |
| print(attr.getNodeName()); |
| print("=\""); //$NON-NLS-1$ |
| print(createPrintableCharacterData(attr.getValue())); |
| print("\""); //$NON-NLS-1$ |
| } |
| |
| public void visitText(Text text) |
| { |
| if (currentElementHasChildElements) |
| { |
| printIndent(); |
| print(createPrintableCharacterData(text.getNodeValue())); |
| println(); |
| } |
| else |
| { |
| print(createPrintableCharacterData(text.getNodeValue())); |
| } |
| } |
| |
| public void visitCDATASection(CDATASection cdataSection) |
| { |
| } |
| |
| public void visitComment(Comment comment) |
| { |
| printIndent(); |
| print("<!--"); //$NON-NLS-1$ |
| print(comment.getNodeValue()); |
| println("-->"); //$NON-NLS-1$ |
| } |
| |
| public void visitProcessingInstruction(ProcessingInstruction pi) |
| { |
| printIndent(); |
| print("<?"); //$NON-NLS-1$ |
| print(pi.getNodeName()); |
| print(" "); //$NON-NLS-1$ |
| print(pi.getNodeValue()); |
| println("?>"); //$NON-NLS-1$ |
| } |
| |
| |
| public boolean hasChildElements(Node node) |
| { |
| boolean result = false; |
| NodeList children = node.getChildNodes(); |
| for (int i = 0; i < children.getLength(); i++) |
| { |
| if (children.item(i).getNodeType() == Node.ELEMENT_NODE) |
| { |
| result = true; |
| break; |
| } |
| } |
| return result; |
| } |
| |
| public void visitChildNodesHelper(Node node) |
| { |
| NodeList children = node.getChildNodes(); |
| for (int i = 0; i < children.getLength(); i++) |
| { |
| visitNode(children.item(i)); |
| } |
| } |
| |
| public void visitAttributesHelper(Node node) |
| { |
| NamedNodeMap map = node.getAttributes(); |
| for (int i = 0; i < map.getLength(); i++ ) |
| { |
| visitNode(map.item(i)); |
| } |
| } |
| } |
| |
| /** an ugly hack until I restruct this code a little |
| * |
| */ |
| protected boolean doShow(Element element) |
| { |
| return true; |
| } |
| |
| /** converts DOM text values to 'printable' values |
| * - converts '&' to '&' |
| */ |
| protected String createPrintableCharacterData(String string) |
| { |
| String result = ""; //$NON-NLS-1$ |
| int index = 0; |
| while (true) |
| { |
| int ampersandIndex = string.indexOf("&", index); //$NON-NLS-1$ |
| if (ampersandIndex != -1) |
| { |
| result += string.substring(index, ampersandIndex); |
| result += "&"; //$NON-NLS-1$ |
| index = ampersandIndex + 1; |
| } |
| else |
| { |
| break; |
| } |
| } |
| result += string.substring(index); |
| return result; |
| } |
| |
| |
| /** Prints the specified node, recursively. */ |
| public void print(Node node) |
| { |
| // is there anything to do? |
| if (node != null) |
| { |
| XMLVisitor visitor = new XMLVisitor(); |
| visitor.visitNode(node); |
| } |
| out.flush(); |
| } |
| |
| /** a temporary hack to workaround our inability to create a DocumentType tag*/ |
| public void print(Document document, String grammarURL) |
| { |
| String systemId = null; |
| if (grammarURL.endsWith("dtd")) //$NON-NLS-1$ |
| { |
| int lastSlashIndex = Math.max(grammarURL.lastIndexOf("/"), grammarURL.lastIndexOf("\\")); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (lastSlashIndex != -1) |
| { |
| systemId = grammarURL.substring(lastSlashIndex + 1); |
| } |
| } |
| print(document, "UTF-8", grammarURL, null, systemId); //$NON-NLS-1$ |
| |
| } |
| |
| /** a temporary hack to workaround our inability to create a DocumentType tag*/ |
| public void print(Document document, String encoding, String grammarFileName, String publicId, String systemId) |
| { |
| out.println("<?xml version=\"1.0\"" + " encoding=\"" + encoding + "\"?>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| if (grammarFileName.endsWith(".dtd")) //$NON-NLS-1$ |
| { |
| String docTypeLine = "<!DOCTYPE " + document.getDocumentElement().getNodeName() + " "; //$NON-NLS-1$ //$NON-NLS-2$ |
| if (publicId != null) |
| { |
| docTypeLine += "PUBLIC \"" + publicId + "\" "; //$NON-NLS-1$ //$NON-NLS-2$ |
| if (systemId != null) |
| { |
| docTypeLine += "\"" + systemId + "\" "; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| docTypeLine += ">"; //$NON-NLS-1$ |
| out.println(docTypeLine); |
| } |
| else if (systemId != null) |
| { |
| docTypeLine += "SYSTEM \"" + systemId + "\" >"; //$NON-NLS-1$ //$NON-NLS-2$ |
| out.println(docTypeLine); |
| } |
| } |
| print(document); |
| } |
| |
| public static String getDocumentTypeData(DocumentType doctype) |
| { |
| String data = doctype.getName(); |
| if (doctype.getPublicId() != null) |
| { |
| data += " PUBLIC \"" + doctype.getPublicId() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ |
| String systemId = doctype.getSystemId(); |
| if (systemId == null) |
| { |
| systemId = ""; //$NON-NLS-1$ |
| } |
| data += " \"" + systemId + "\""; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| else |
| { |
| data += " SYSTEM \"" + doctype.getSystemId() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return data; |
| } |
| |
| public void println() |
| { |
| if (formattingEnabled) |
| { |
| out.println(); |
| } |
| } |
| |
| public void println(String string) |
| { |
| if (formattingEnabled) |
| { |
| out.println(string); |
| } |
| else |
| { |
| out.print(string); |
| } |
| } |
| |
| public void printIndent() |
| { |
| if (formattingEnabled) |
| { |
| for (int i = 0; i < indent; i++) |
| { |
| out.print(" "); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| public void print(String string) |
| { |
| out.print(string); |
| } |
| } |
| |