001 /**
002 *
003 * Copyright 2004 Protique Ltd
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 **/
018 package org.codehaus.activesoap.util;
019
020 import org.xml.sax.ContentHandler;
021 import org.xml.sax.Attributes;
022 import org.xml.sax.SAXException;
023 import org.xml.sax.helpers.AttributesImpl;
024
025 import javax.xml.namespace.NamespaceContext;
026 import javax.xml.namespace.QName;
027 import javax.xml.stream.XMLStreamConstants;
028 import javax.xml.stream.XMLStreamException;
029 import javax.xml.stream.XMLStreamReader;
030 import javax.xml.stream.XMLStreamWriter;
031
032 import javanet.staxutils.XMLStreamUtils;
033 import javanet.staxutils.XMLStreamReaderToContentHandler;
034
035 /**
036 * Utility methods for working with an XMLStreamWriter.
037 * Maybe push this back into stax-utils project.
038 *
039 * @version $Revision: 1.14 $
040 */
041 public class XMLStreamHelper implements XMLStreamConstants {
042 private static Attributes emptyAttributes = new AttributesImpl();
043
044
045 /**
046 * Returns true if currently at the start of an element, otherwise move forwards to the next
047 * element start and return true, otherwise false is returned if the end of the stream is reached.
048 */
049 public static boolean skipToStartOfElement(XMLStreamReader in) throws XMLStreamException {
050 for (int code = in.getEventType(); code != END_DOCUMENT; code = in.next()) {
051 if (code == START_ELEMENT) {
052 return true;
053 }
054 }
055 return false;
056 }
057
058 public static void writeStartElement(QName qname, ContentHandler handler) throws SAXException {
059 handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), QNameHelper.getQualifiedName(qname), emptyAttributes);
060 }
061
062 public static void writeEndElement(QName qname, ContentHandler handler) throws SAXException {
063 handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), QNameHelper.getQualifiedName(qname));
064 }
065
066
067 /**
068 * Copies the current element and its conetnt to the output
069 */
070 public static void copy(XMLStreamReader in, XMLStreamWriter out, boolean repairing) throws XMLStreamException {
071 int elementCount = 0;
072 for (int code = in.getEventType(); in.hasNext(); code = in.next()) {
073 switch (code) {
074 case START_ELEMENT:
075 elementCount++;
076 writeStartElementAndAttributes(out, in, repairing);
077 break;
078
079 case END_ELEMENT:
080 if (--elementCount < 0) {
081 return;
082 }
083 out.writeEndElement();
084 break;
085
086 case CDATA:
087 out.writeCData(in.getText());
088 break;
089
090 case CHARACTERS:
091 out.writeCharacters(in.getText());
092 break;
093 }
094 }
095 while (elementCount-- > 0) {
096 out.writeEndElement();
097 }
098 }
099
100 public static void writeStartElement(XMLStreamWriter out, String prefix, String uri, String localName, boolean repairing) throws XMLStreamException {
101 boolean map = isPrefixNotMappedToUri(out, prefix, uri);
102 if (prefix != null && prefix.length() > 0) {
103 if (map) {
104 out.setPrefix(prefix, uri);
105 }
106 out.writeStartElement(prefix, localName, uri);
107 if (map && !repairing) {
108 out.writeNamespace(prefix, uri);
109 }
110 }
111 else {
112 boolean hasURI = uri != null && uri.length() > 0;
113 if (map && hasURI) {
114 out.setDefaultNamespace(uri);
115 }
116 out.writeStartElement(uri, localName);
117 if (map && !repairing && hasURI) {
118 out.writeDefaultNamespace(uri);
119 }
120 }
121 }
122
123 public static void writeStartElement(XMLStreamWriter out, QName envelopeName, boolean repairing) throws XMLStreamException {
124 writeStartElement(out, envelopeName.getPrefix(), envelopeName.getNamespaceURI(), envelopeName.getLocalPart(), repairing);
125 }
126
127 public static void writeStartElement(XMLStreamWriter out, XMLStreamReader in, boolean repairing) throws XMLStreamException {
128 String prefix = in.getPrefix();
129
130 // we can avoid this step if in repairing mode
131 int count = in.getNamespaceCount();
132 for (int i = 0; i < count; i++) {
133 String aPrefix = in.getNamespacePrefix(i);
134 if (prefix == aPrefix || (prefix != null && prefix.equals(aPrefix))) {
135 continue;
136 }
137 String uri = in.getNamespaceURI(i);
138 if (isPrefixNotMappedToUri(out, aPrefix, uri)) {
139 if (aPrefix != null && aPrefix.length() > 0) {
140 out.setPrefix(aPrefix, uri);
141 }
142 else {
143 out.setDefaultNamespace(uri);
144 }
145 }
146 }
147 String localName = in.getLocalName();
148 String uri = in.getNamespaceURI();
149 writeStartElement(out, prefix, uri, localName, repairing);
150 }
151
152
153 public static void writeStartElementAndAttributes(XMLStreamWriter out, XMLStreamReader in, boolean repairing) throws XMLStreamException {
154 writeStartElement(out, in, repairing);
155 if (!repairing) {
156 writeNamespaces(out, in, in.getPrefix());
157 }
158 writeAttributes(out, in);
159 }
160
161 public static void writeAttributes(XMLStreamWriter out, XMLStreamReader in) throws XMLStreamException {
162 int count = in.getAttributeCount();
163 for (int i = 0; i < count; i++) {
164 out.writeAttribute(in.getAttributePrefix(i),
165 in.getAttributeNamespace(i),
166 in.getAttributeLocalName(i),
167 in.getAttributeValue(i));
168 }
169 }
170
171 public static void writeNamespaces(XMLStreamWriter out, XMLStreamReader in, String prefixOfCurrentElement) throws XMLStreamException {
172 int count = in.getNamespaceCount();
173 for (int i = 0; i < count; i++) {
174 String prefix = in.getNamespacePrefix(i);
175 String uri = in.getNamespaceURI(i);
176 if (prefixOfCurrentElement != null && prefixOfCurrentElement.equals(prefix)) {
177 continue;
178 }
179 if (isPrefixNotMappedToUri(out, prefix, uri)) {
180 out.writeNamespace(prefix, uri);
181 }
182 }
183 }
184
185
186 public static void writeNamespacesExcludingPrefixAndNamespace(XMLStreamWriter out, XMLStreamReader in, String ignorePrefix, String ignoreNamespace) throws XMLStreamException {
187 int count = in.getNamespaceCount();
188 for (int i = 0; i < count; i++) {
189 String prefix = in.getNamespacePrefix(i);
190 if (!ignorePrefix.equals(prefix)) {
191 String uri = in.getNamespaceURI(i);
192 if (!ignoreNamespace.equals(uri)) {
193 out.writeNamespace(prefix, uri);
194 }
195 }
196 }
197 }
198
199 public static void writeAttribute(XMLStreamWriter out, QName name, String attributeValue) throws XMLStreamException {
200 writeAttribute(out, name.getPrefix(), name.getNamespaceURI(), name.getLocalPart(), attributeValue);
201 }
202
203 public static void writeAttribute(XMLStreamWriter out, String prefix, String namespaceURI, String localPart, String attributeValue) throws XMLStreamException {
204 out.writeAttribute(prefix, namespaceURI, localPart, attributeValue);
205 }
206
207 protected static boolean isPrefixNotMappedToUri(XMLStreamWriter out, String prefix, String uri) {
208 if (prefix == null) {
209 prefix = "";
210 }
211 NamespaceContext context = out.getNamespaceContext();
212 if (context == null) {
213 return false;
214 }
215 String mappedUri = context.getPrefix(prefix);
216 boolean map = (mappedUri == null || !mappedUri.equals(uri));
217 return map;
218 }
219
220 /**
221 * Copies the content to the SAX stream
222 */
223 public static void copy(XMLStreamReader in, ContentHandler contentHandler) throws XMLStreamException {
224 XMLStreamReaderToContentHandler converter = new XMLStreamReaderToContentHandler(in, contentHandler);
225 converter.bridge();
226 }
227
228 /**
229 * Copies the element and its content to the SAX stream
230 */
231 public static void copyElement(XMLStreamReader in, ContentHandler contentHandler) throws XMLStreamException {
232 copy(new DocumentFilterXMLStreamReader(in.getName(), in), contentHandler);
233 }
234
235 }