001 /*
002 * (c) Copyright 2009 University of Bristol
003 * All rights reserved.
004 * [See end of file]
005 */
006 package net.rootdev.javardfa;
007
008 import java.util.Iterator;
009 import java.util.SortedMap;
010 import java.util.TreeMap;
011 import javax.xml.namespace.NamespaceContext;
012 import javax.xml.namespace.QName;
013 import javax.xml.stream.XMLEventReader;
014 import javax.xml.stream.XMLEventWriter;
015 import javax.xml.stream.XMLStreamException;
016 import javax.xml.stream.XMLStreamWriter;
017 import javax.xml.stream.events.Attribute;
018 import javax.xml.stream.events.ProcessingInstruction;
019 import javax.xml.stream.events.StartElement;
020 import javax.xml.stream.events.XMLEvent;
021
022 /**
023 * All this class does currently is ensure the order of attributes, but
024 * (By using a stream writer) it is more controllable than the event writer.
025 *
026 * @author pldms
027 */
028 public class CanonicalXMLEventWriter
029 implements XMLEventWriter {
030
031 private final XMLStreamWriter swriter;
032 private StartElement last;
033
034 public CanonicalXMLEventWriter(XMLStreamWriter swriter) {
035 this.swriter = swriter;
036 }
037
038 public void flush() throws XMLStreamException {
039 swriter.flush();
040 }
041
042 public void close() throws XMLStreamException {
043 swriter.close();
044 }
045
046 public void add(XMLEvent event) throws XMLStreamException {
047 if (event.isEndElement()) {
048 swriter.writeEndElement();
049 } else if (event.isCharacters()) {
050 swriter.writeCharacters(event.asCharacters().getData());
051 } else if (event.isProcessingInstruction()) {
052 swriter.writeProcessingInstruction(((ProcessingInstruction) event).getData(),
053 ((ProcessingInstruction) event).getTarget());
054 } else if (event.isStartElement()) {
055 StartElement se = event.asStartElement();
056 swriter.writeStartElement(se.getName().getPrefix(),
057 se.getName().getLocalPart(),
058 se.getName().getNamespaceURI());
059 writeAttributes(se);
060 swriter.writeCharacters(""); // Force close of start element
061 } else {
062 System.err.printf("Gah! Missed one <%s>, '%s'\n", event.getClass(), event);
063 }
064 }
065
066 public void add(XMLEventReader reader) throws XMLStreamException {
067 while (reader.hasNext()) {
068 this.add(reader.nextEvent());
069 }
070 }
071
072 public String getPrefix(String uri) throws XMLStreamException {
073 return swriter.getPrefix(uri);
074 }
075
076 public void setPrefix(String prefix, String uri) throws XMLStreamException {
077 swriter.setPrefix(prefix, uri);
078 }
079
080 public void setDefaultNamespace(String uri) throws XMLStreamException {
081 swriter.setDefaultNamespace(uri);
082 }
083
084 public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
085 swriter.setNamespaceContext(context);
086 }
087
088 public NamespaceContext getNamespaceContext() {
089 return swriter.getNamespaceContext();
090 }
091
092 private void writeAttributes(StartElement se) throws XMLStreamException {
093 SortedMap<String, Attribute> atts = new TreeMap<String, Attribute>();
094 for (Iterator i = se.getAttributes(); i.hasNext();) {
095 Attribute a = (Attribute) i.next();
096 atts.put(getName(a), a);
097 }
098 for (Attribute a : atts.values()) {
099 swriter.writeAttribute(
100 a.getName().getPrefix(),
101 a.getName().getNamespaceURI(),
102 a.getName().getLocalPart(),
103 a.getValue());
104 }
105 }
106
107 private String getName(Attribute a) {
108 QName name = a.getName();
109 String toReturn = (name.getPrefix() == null) ? name.getLocalPart() : name.getPrefix() + ":" + name.getLocalPart();
110 if (toReturn.startsWith("xml:")) {
111 return "_" + toReturn;
112 } else {
113 return toReturn;
114 }
115 }
116 }
117
118 /*
119 * (c) Copyright 2009 University of Bristol
120 * All rights reserved.
121 *
122 * Redistribution and use in source and binary forms, with or without
123 * modification, are permitted provided that the following conditions
124 * are met:
125 * 1. Redistributions of source code must retain the above copyright
126 * notice, this list of conditions and the following disclaimer.
127 * 2. Redistributions in binary form must reproduce the above copyright
128 * notice, this list of conditions and the following disclaimer in the
129 * documentation and/or other materials provided with the distribution.
130 * 3. The name of the author may not be used to endorse or promote products
131 * derived from this software without specific prior written permission.
132 *
133 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
134 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
135 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
136 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
137 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
138 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
139 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
140 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
141 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
142 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
143 */