Browse Source
Improved the SAX to StAX (and vice-versa) bridge exposed via StaxUtils. The old integration had some issues with namespace declaration attributes, brought to light in a XMLUnit upgrade. Issue: SPR-11549pull/496/merge
19 changed files with 850 additions and 625 deletions
@ -1,185 +0,0 @@
@@ -1,185 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2012 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import javax.xml.namespace.QName; |
||||
import javax.xml.stream.XMLStreamException; |
||||
|
||||
import org.xml.sax.Attributes; |
||||
import org.xml.sax.ContentHandler; |
||||
import org.xml.sax.SAXException; |
||||
|
||||
/** |
||||
* Abstract base class for SAX {@code ContentHandler} implementations that use StAX as a basis. All methods |
||||
* delegate to internal template methods, capable of throwing a {@code XMLStreamException}. Additionally, an |
||||
* namespace context is used to keep track of declared namespaces. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @since 3.0 |
||||
*/ |
||||
abstract class AbstractStaxContentHandler implements ContentHandler { |
||||
|
||||
private SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext(); |
||||
|
||||
private boolean namespaceContextChanged = false; |
||||
|
||||
@Override |
||||
public final void startDocument() throws SAXException { |
||||
namespaceContext.clear(); |
||||
namespaceContextChanged = false; |
||||
try { |
||||
startDocumentInternal(); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle startDocument: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
protected abstract void startDocumentInternal() throws XMLStreamException; |
||||
|
||||
@Override |
||||
public final void endDocument() throws SAXException { |
||||
namespaceContext.clear(); |
||||
namespaceContextChanged = false; |
||||
try { |
||||
endDocumentInternal(); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle startDocument: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
protected abstract void endDocumentInternal() throws XMLStreamException; |
||||
|
||||
/** |
||||
* Binds the given prefix to the given namespaces. |
||||
* |
||||
* @see SimpleNamespaceContext#bindNamespaceUri(String,String) |
||||
*/ |
||||
@Override |
||||
public final void startPrefixMapping(String prefix, String uri) { |
||||
namespaceContext.bindNamespaceUri(prefix, uri); |
||||
namespaceContextChanged = true; |
||||
} |
||||
|
||||
/** |
||||
* Removes the binding for the given prefix. |
||||
* |
||||
* @see SimpleNamespaceContext#removeBinding(String) |
||||
*/ |
||||
@Override |
||||
public final void endPrefixMapping(String prefix) { |
||||
namespaceContext.removeBinding(prefix); |
||||
namespaceContextChanged = true; |
||||
} |
||||
|
||||
@Override |
||||
public final void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { |
||||
try { |
||||
startElementInternal(toQName(uri, qName), atts, namespaceContextChanged ? namespaceContext : null); |
||||
namespaceContextChanged = false; |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle startElement: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
protected abstract void startElementInternal(QName name, Attributes atts, SimpleNamespaceContext namespaceContext) |
||||
throws XMLStreamException; |
||||
|
||||
@Override |
||||
public final void endElement(String uri, String localName, String qName) throws SAXException { |
||||
try { |
||||
endElementInternal(toQName(uri, qName), namespaceContextChanged ? namespaceContext : null); |
||||
namespaceContextChanged = false; |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle endElement: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
protected abstract void endElementInternal(QName name, SimpleNamespaceContext namespaceContext) |
||||
throws XMLStreamException; |
||||
|
||||
@Override |
||||
public final void characters(char ch[], int start, int length) throws SAXException { |
||||
try { |
||||
charactersInternal(ch, start, length); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle characters: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
protected abstract void charactersInternal(char[] ch, int start, int length) throws XMLStreamException; |
||||
|
||||
@Override |
||||
public final void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { |
||||
try { |
||||
ignorableWhitespaceInternal(ch, start, length); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle ignorableWhitespace:" + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
protected abstract void ignorableWhitespaceInternal(char[] ch, int start, int length) throws XMLStreamException; |
||||
|
||||
@Override |
||||
public final void processingInstruction(String target, String data) throws SAXException { |
||||
try { |
||||
processingInstructionInternal(target, data); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle processingInstruction: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
protected abstract void processingInstructionInternal(String target, String data) throws XMLStreamException; |
||||
|
||||
@Override |
||||
public final void skippedEntity(String name) throws SAXException { |
||||
try { |
||||
skippedEntityInternal(name); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle skippedEntity: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Convert a namespace URI and DOM or SAX qualified name to a {@code QName}. The qualified name can have the form |
||||
* {@code prefix:localname} or {@code localName}. |
||||
* |
||||
* @param namespaceUri the namespace URI |
||||
* @param qualifiedName the qualified name |
||||
* @return a QName |
||||
*/ |
||||
protected QName toQName(String namespaceUri, String qualifiedName) { |
||||
int idx = qualifiedName.indexOf(':'); |
||||
if (idx == -1) { |
||||
return new QName(namespaceUri, qualifiedName); |
||||
} |
||||
else { |
||||
String prefix = qualifiedName.substring(0, idx); |
||||
String localPart = qualifiedName.substring(idx + 1); |
||||
return new QName(namespaceUri, localPart, prefix); |
||||
} |
||||
} |
||||
|
||||
protected abstract void skippedEntityInternal(String name) throws XMLStreamException; |
||||
} |
||||
@ -0,0 +1,273 @@
@@ -0,0 +1,273 @@
|
||||
/* |
||||
* Copyright 2002-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import javax.xml.XMLConstants; |
||||
import javax.xml.namespace.QName; |
||||
import javax.xml.stream.XMLStreamException; |
||||
|
||||
import org.xml.sax.Attributes; |
||||
import org.xml.sax.ContentHandler; |
||||
import org.xml.sax.SAXException; |
||||
import org.xml.sax.ext.LexicalHandler; |
||||
|
||||
/** |
||||
* Abstract base class for SAX {@code ContentHandler} and {@code LexicalHandler} |
||||
* implementations that use StAX as a basis. All methods delegate to internal template |
||||
* methods, capable of throwing a {@code XMLStreamException}. Additionally, an namespace |
||||
* context stack is used to keep track of declared namespaces. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @since 4.0.3 |
||||
*/ |
||||
abstract class AbstractStaxHandler implements ContentHandler, LexicalHandler { |
||||
|
||||
private final List<Map<String, String>> namespaceMappings = new ArrayList<Map<String, String>>(); |
||||
|
||||
private boolean inCData; |
||||
|
||||
|
||||
@Override |
||||
public final void startDocument() throws SAXException { |
||||
removeAllNamespaceMappings(); |
||||
newNamespaceMapping(); |
||||
try { |
||||
startDocumentInternal(); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle startDocument: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void endDocument() throws SAXException { |
||||
removeAllNamespaceMappings(); |
||||
try { |
||||
endDocumentInternal(); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle endDocument: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void startPrefixMapping(String prefix, String uri) { |
||||
currentNamespaceMapping().put(prefix, uri); |
||||
} |
||||
|
||||
@Override |
||||
public final void endPrefixMapping(String prefix) { |
||||
} |
||||
|
||||
@Override |
||||
public final void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { |
||||
try { |
||||
startElementInternal(toQName(uri, qName), atts, currentNamespaceMapping()); |
||||
newNamespaceMapping(); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle startElement: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void endElement(String uri, String localName, String qName) throws SAXException { |
||||
try { |
||||
endElementInternal(toQName(uri, qName), currentNamespaceMapping()); |
||||
removeNamespaceMapping(); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle endElement: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void characters(char ch[], int start, int length) throws SAXException { |
||||
try { |
||||
String data = new String(ch, start, length); |
||||
if (!this.inCData) { |
||||
charactersInternal(data); |
||||
} |
||||
else { |
||||
cDataInternal(data); |
||||
} |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle characters: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { |
||||
try { |
||||
ignorableWhitespaceInternal(new String(ch, start, length)); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException( |
||||
"Could not handle ignorableWhitespace:" + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void processingInstruction(String target, String data) throws SAXException { |
||||
try { |
||||
processingInstructionInternal(target, data); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle processingInstruction: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void skippedEntity(String name) throws SAXException { |
||||
try { |
||||
skippedEntityInternal(name); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle skippedEntity: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void startDTD(String name, String publicId, String systemId) throws SAXException { |
||||
try { |
||||
StringBuilder builder = new StringBuilder("<!DOCTYPE "); |
||||
builder.append(name); |
||||
if (publicId != null) { |
||||
builder.append(" PUBLIC \""); |
||||
builder.append(publicId); |
||||
builder.append("\" \""); |
||||
} |
||||
else { |
||||
builder.append(" SYSTEM \""); |
||||
} |
||||
builder.append(systemId); |
||||
builder.append("\">"); |
||||
|
||||
dtdInternal(builder.toString()); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle startDTD: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public final void endDTD() throws SAXException { |
||||
} |
||||
|
||||
@Override |
||||
public final void startCDATA() throws SAXException { |
||||
this.inCData = true; |
||||
} |
||||
|
||||
@Override |
||||
public final void endCDATA() throws SAXException { |
||||
this.inCData = false; |
||||
} |
||||
|
||||
@Override |
||||
public final void comment(char[] ch, int start, int length) throws SAXException { |
||||
try { |
||||
commentInternal(new String(ch, start, length)); |
||||
} |
||||
catch (XMLStreamException ex) { |
||||
throw new SAXException("Could not handle comment: " + ex.getMessage(), ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void startEntity(String name) throws SAXException { |
||||
} |
||||
|
||||
@Override |
||||
public void endEntity(String name) throws SAXException { |
||||
} |
||||
|
||||
/** |
||||
* Convert a namespace URI and DOM or SAX qualified name to a {@code QName}. The |
||||
* qualified name can have the form {@code prefix:localname} or {@code localName}. |
||||
* @param namespaceUri the namespace URI |
||||
* @param qualifiedName the qualified name |
||||
* @return a QName |
||||
*/ |
||||
protected QName toQName(String namespaceUri, String qualifiedName) { |
||||
int idx = qualifiedName.indexOf(':'); |
||||
if (idx == -1) { |
||||
return new QName(namespaceUri, qualifiedName); |
||||
} |
||||
else { |
||||
String prefix = qualifiedName.substring(0, idx); |
||||
String localPart = qualifiedName.substring(idx + 1); |
||||
return new QName(namespaceUri, localPart, prefix); |
||||
} |
||||
} |
||||
|
||||
protected boolean isNamespaceDeclaration(QName qName) { |
||||
String prefix = qName.getPrefix(); |
||||
String localPart = qName.getLocalPart(); |
||||
return (XMLConstants.XMLNS_ATTRIBUTE.equals(localPart) && prefix.length() == 0) || |
||||
(XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) && localPart.length() != 0); |
||||
} |
||||
|
||||
|
||||
private Map<String, String> currentNamespaceMapping() { |
||||
return this.namespaceMappings.get(this.namespaceMappings.size() - 1); |
||||
} |
||||
|
||||
private void newNamespaceMapping() { |
||||
this.namespaceMappings.add(new HashMap<String, String>()); |
||||
} |
||||
|
||||
private void removeNamespaceMapping() { |
||||
this.namespaceMappings.remove(this.namespaceMappings.size() - 1); |
||||
} |
||||
|
||||
private void removeAllNamespaceMappings() { |
||||
this.namespaceMappings.clear(); |
||||
} |
||||
|
||||
|
||||
protected abstract void startDocumentInternal() throws XMLStreamException; |
||||
|
||||
protected abstract void endDocumentInternal() throws XMLStreamException; |
||||
|
||||
protected abstract void startElementInternal(QName name, Attributes attributes, |
||||
Map<String, String> namespaceMapping) throws XMLStreamException; |
||||
|
||||
protected abstract void endElementInternal(QName name, Map<String, String> namespaceMapping) |
||||
throws XMLStreamException; |
||||
|
||||
protected abstract void charactersInternal(String data) throws XMLStreamException; |
||||
|
||||
protected abstract void cDataInternal(String data) throws XMLStreamException; |
||||
|
||||
protected abstract void ignorableWhitespaceInternal(String data) throws XMLStreamException; |
||||
|
||||
protected abstract void processingInstructionInternal(String target, String data) |
||||
throws XMLStreamException; |
||||
|
||||
protected abstract void skippedEntityInternal(String name) throws XMLStreamException; |
||||
|
||||
protected abstract void dtdInternal(String dtd) throws XMLStreamException; |
||||
|
||||
protected abstract void commentInternal(String comment) throws XMLStreamException; |
||||
|
||||
} |
||||
@ -1,198 +0,0 @@
@@ -1,198 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2012 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
|
||||
import javax.xml.XMLConstants; |
||||
import javax.xml.namespace.QName; |
||||
import javax.xml.stream.Location; |
||||
import javax.xml.stream.XMLEventFactory; |
||||
import javax.xml.stream.XMLStreamException; |
||||
import javax.xml.stream.events.Attribute; |
||||
import javax.xml.stream.events.Namespace; |
||||
import javax.xml.stream.events.XMLEvent; |
||||
import javax.xml.stream.util.XMLEventConsumer; |
||||
|
||||
import org.springframework.util.StringUtils; |
||||
import org.xml.sax.Attributes; |
||||
import org.xml.sax.Locator; |
||||
|
||||
/** |
||||
* SAX {@code ContentHandler} that transforms callback calls to {@code XMLEvent}s |
||||
* and writes them to a {@code XMLEventConsumer}. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @since 3.0 |
||||
* @see XMLEvent |
||||
* @see XMLEventConsumer |
||||
*/ |
||||
class StaxEventContentHandler extends AbstractStaxContentHandler { |
||||
|
||||
private final XMLEventFactory eventFactory; |
||||
|
||||
private final XMLEventConsumer eventConsumer; |
||||
|
||||
|
||||
/** |
||||
* Construct a new instance of the {@code StaxEventContentHandler} that writes to the given |
||||
* {@code XMLEventConsumer}. A default {@code XMLEventFactory} will be created. |
||||
* @param consumer the consumer to write events to |
||||
*/ |
||||
StaxEventContentHandler(XMLEventConsumer consumer) { |
||||
this.eventFactory = XMLEventFactory.newInstance(); |
||||
this.eventConsumer = consumer; |
||||
} |
||||
|
||||
/** |
||||
* Construct a new instance of the {@code StaxEventContentHandler} that uses the given |
||||
* event factory to create events and writes to the given {@code XMLEventConsumer}. |
||||
* @param consumer the consumer to write events to |
||||
* @param factory the factory used to create events |
||||
*/ |
||||
StaxEventContentHandler(XMLEventConsumer consumer, XMLEventFactory factory) { |
||||
this.eventFactory = factory; |
||||
this.eventConsumer = consumer; |
||||
} |
||||
|
||||
@Override |
||||
public void setDocumentLocator(Locator locator) { |
||||
if (locator != null) { |
||||
this.eventFactory.setLocation(new LocatorLocationAdapter(locator)); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void startDocumentInternal() throws XMLStreamException { |
||||
consumeEvent(this.eventFactory.createStartDocument()); |
||||
} |
||||
|
||||
@Override |
||||
protected void endDocumentInternal() throws XMLStreamException { |
||||
consumeEvent(this.eventFactory.createEndDocument()); |
||||
} |
||||
|
||||
@Override |
||||
protected void startElementInternal(QName name, Attributes atts, SimpleNamespaceContext namespaceContext) |
||||
throws XMLStreamException { |
||||
|
||||
List<Attribute> attributes = getAttributes(atts); |
||||
List<Namespace> namespaces = createNamespaces(namespaceContext); |
||||
consumeEvent(this.eventFactory.createStartElement(name, attributes.iterator(), |
||||
(namespaces != null ? namespaces.iterator() : null))); |
||||
} |
||||
|
||||
@Override |
||||
protected void endElementInternal(QName name, SimpleNamespaceContext namespaceContext) throws XMLStreamException { |
||||
List<Namespace> namespaces = createNamespaces(namespaceContext); |
||||
consumeEvent(this.eventFactory.createEndElement(name, namespaces != null ? namespaces.iterator() : null)); |
||||
} |
||||
|
||||
@Override |
||||
protected void charactersInternal(char[] ch, int start, int length) throws XMLStreamException { |
||||
consumeEvent(this.eventFactory.createCharacters(new String(ch, start, length))); |
||||
} |
||||
|
||||
@Override |
||||
protected void ignorableWhitespaceInternal(char[] ch, int start, int length) throws XMLStreamException { |
||||
consumeEvent(this.eventFactory.createIgnorableSpace(new String(ch, start, length))); |
||||
} |
||||
|
||||
@Override |
||||
protected void processingInstructionInternal(String target, String data) throws XMLStreamException { |
||||
consumeEvent(this.eventFactory.createProcessingInstruction(target, data)); |
||||
} |
||||
|
||||
private void consumeEvent(XMLEvent event) throws XMLStreamException { |
||||
this.eventConsumer.add(event); |
||||
} |
||||
|
||||
/** |
||||
* Create and return a list of {@code NameSpace} objects from the {@code NamespaceContext}. |
||||
*/ |
||||
private List<Namespace> createNamespaces(SimpleNamespaceContext namespaceContext) { |
||||
if (namespaceContext == null) { |
||||
return null; |
||||
} |
||||
|
||||
List<Namespace> namespaces = new ArrayList<Namespace>(); |
||||
String defaultNamespaceUri = namespaceContext.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX); |
||||
if (StringUtils.hasLength(defaultNamespaceUri)) { |
||||
namespaces.add(this.eventFactory.createNamespace(defaultNamespaceUri)); |
||||
} |
||||
for (Iterator<String> iterator = namespaceContext.getBoundPrefixes(); iterator.hasNext();) { |
||||
String prefix = iterator.next(); |
||||
String namespaceUri = namespaceContext.getNamespaceURI(prefix); |
||||
namespaces.add(this.eventFactory.createNamespace(prefix, namespaceUri)); |
||||
} |
||||
return namespaces; |
||||
} |
||||
|
||||
private List<Attribute> getAttributes(Attributes attributes) { |
||||
List<Attribute> list = new ArrayList<Attribute>(); |
||||
for (int i = 0; i < attributes.getLength(); i++) { |
||||
QName name = toQName(attributes.getURI(i), attributes.getQName(i)); |
||||
if (!("xmlns".equals(name.getLocalPart()) || "xmlns".equals(name.getPrefix()))) { |
||||
list.add(this.eventFactory.createAttribute(name, attributes.getValue(i))); |
||||
} |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
/* No operation */ |
||||
@Override |
||||
protected void skippedEntityInternal(String name) throws XMLStreamException { |
||||
} |
||||
|
||||
|
||||
private static final class LocatorLocationAdapter implements Location { |
||||
|
||||
private final Locator locator; |
||||
|
||||
public LocatorLocationAdapter(Locator locator) { |
||||
this.locator = locator; |
||||
} |
||||
|
||||
@Override |
||||
public int getLineNumber() { |
||||
return this.locator.getLineNumber(); |
||||
} |
||||
|
||||
@Override |
||||
public int getColumnNumber() { |
||||
return this.locator.getColumnNumber(); |
||||
} |
||||
|
||||
@Override |
||||
public int getCharacterOffset() { |
||||
return -1; |
||||
} |
||||
|
||||
@Override |
||||
public String getPublicId() { |
||||
return this.locator.getPublicId(); |
||||
} |
||||
|
||||
@Override |
||||
public String getSystemId() { |
||||
return this.locator.getSystemId(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,196 @@
@@ -0,0 +1,196 @@
|
||||
/* |
||||
* Copyright 2002-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import javax.xml.namespace.QName; |
||||
import javax.xml.stream.Location; |
||||
import javax.xml.stream.XMLEventFactory; |
||||
import javax.xml.stream.XMLEventWriter; |
||||
import javax.xml.stream.XMLStreamException; |
||||
import javax.xml.stream.events.Attribute; |
||||
import javax.xml.stream.events.Namespace; |
||||
|
||||
import org.xml.sax.Attributes; |
||||
import org.xml.sax.Locator; |
||||
import org.xml.sax.ext.LexicalHandler; |
||||
|
||||
/** |
||||
* SAX {@link org.xml.sax.ContentHandler} and {@link LexicalHandler} |
||||
* that writes to a {@link javax.xml.stream.util.XMLEventConsumer}. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @since 4.0.3 |
||||
*/ |
||||
class StaxEventHandler extends AbstractStaxHandler { |
||||
|
||||
private final XMLEventFactory eventFactory; |
||||
|
||||
private final XMLEventWriter eventWriter; |
||||
|
||||
|
||||
/** |
||||
* Construct a new instance of the {@code StaxEventContentHandler} that writes to the |
||||
* given {@code XMLEventWriter}. A default {@code XMLEventFactory} will be created. |
||||
* @param eventWriter the writer to write events to |
||||
*/ |
||||
public StaxEventHandler(XMLEventWriter eventWriter) { |
||||
this.eventFactory = XMLEventFactory.newInstance(); |
||||
this.eventWriter = eventWriter; |
||||
} |
||||
|
||||
/** |
||||
* Construct a new instance of the {@code StaxEventContentHandler} that uses the given |
||||
* event factory to create events and writes to the given {@code XMLEventConsumer}. |
||||
* @param eventWriter the writer to write events to |
||||
* @param factory the factory used to create events |
||||
*/ |
||||
public StaxEventHandler(XMLEventWriter eventWriter, XMLEventFactory factory) { |
||||
this.eventFactory = factory; |
||||
this.eventWriter = eventWriter; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void setDocumentLocator(Locator locator) { |
||||
if (locator != null) { |
||||
this.eventFactory.setLocation(new LocatorLocationAdapter(locator)); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void startDocumentInternal() throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createStartDocument()); |
||||
} |
||||
|
||||
@Override |
||||
protected void endDocumentInternal() throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createEndDocument()); |
||||
} |
||||
|
||||
@Override |
||||
protected void startElementInternal(QName name, Attributes atts, |
||||
Map<String, String> namespaceMapping) throws XMLStreamException { |
||||
|
||||
List<Attribute> attributes = getAttributes(atts); |
||||
List<Namespace> namespaces = getNamespaces(namespaceMapping); |
||||
this.eventWriter.add( |
||||
this.eventFactory.createStartElement(name, attributes.iterator(), namespaces.iterator())); |
||||
|
||||
} |
||||
|
||||
private List<Namespace> getNamespaces(Map<String, String> namespaceMapping) { |
||||
List<Namespace> result = new ArrayList<Namespace>(); |
||||
for (Map.Entry<String, String> entry : namespaceMapping.entrySet()) { |
||||
String prefix = entry.getKey(); |
||||
String namespaceUri = entry.getValue(); |
||||
result.add(this.eventFactory.createNamespace(prefix, namespaceUri)); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private List<Attribute> getAttributes(Attributes attributes) { |
||||
List<Attribute> result = new ArrayList<Attribute>(); |
||||
for (int i = 0; i < attributes.getLength(); i++) { |
||||
QName attrName = toQName(attributes.getURI(i), attributes.getQName(i)); |
||||
if (!isNamespaceDeclaration(attrName)) { |
||||
result.add(this.eventFactory.createAttribute(attrName, attributes.getValue(i))); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
protected void endElementInternal(QName name, Map<String, String> namespaceMapping) throws XMLStreamException { |
||||
List<Namespace> namespaces = getNamespaces(namespaceMapping); |
||||
this.eventWriter.add(this.eventFactory.createEndElement(name, namespaces.iterator())); |
||||
} |
||||
|
||||
@Override |
||||
protected void charactersInternal(String data) throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createCharacters(data)); |
||||
} |
||||
|
||||
@Override |
||||
protected void cDataInternal(String data) throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createCData(data)); |
||||
} |
||||
|
||||
@Override |
||||
protected void ignorableWhitespaceInternal(String data) throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createIgnorableSpace(data)); |
||||
} |
||||
|
||||
@Override |
||||
protected void processingInstructionInternal(String target, String data) throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createProcessingInstruction(target, data)); |
||||
} |
||||
|
||||
@Override |
||||
protected void dtdInternal(String dtd) throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createDTD(dtd)); |
||||
} |
||||
|
||||
@Override |
||||
protected void commentInternal(String comment) throws XMLStreamException { |
||||
this.eventWriter.add(this.eventFactory.createComment(comment)); |
||||
} |
||||
|
||||
// Ignored
|
||||
|
||||
@Override |
||||
protected void skippedEntityInternal(String name) throws XMLStreamException { |
||||
} |
||||
|
||||
|
||||
private static final class LocatorLocationAdapter implements Location { |
||||
|
||||
private final Locator locator; |
||||
|
||||
public LocatorLocationAdapter(Locator locator) { |
||||
this.locator = locator; |
||||
} |
||||
|
||||
@Override |
||||
public int getLineNumber() { |
||||
return this.locator.getLineNumber(); |
||||
} |
||||
|
||||
@Override |
||||
public int getColumnNumber() { |
||||
return this.locator.getColumnNumber(); |
||||
} |
||||
|
||||
@Override |
||||
public int getCharacterOffset() { |
||||
return -1; |
||||
} |
||||
|
||||
@Override |
||||
public String getPublicId() { |
||||
return this.locator.getPublicId(); |
||||
} |
||||
|
||||
@Override |
||||
public String getSystemId() { |
||||
return this.locator.getSystemId(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,114 +0,0 @@
@@ -1,114 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2012 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import java.util.Iterator; |
||||
import javax.xml.namespace.QName; |
||||
import javax.xml.stream.XMLStreamException; |
||||
import javax.xml.stream.XMLStreamWriter; |
||||
|
||||
import org.xml.sax.Attributes; |
||||
import org.xml.sax.Locator; |
||||
|
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* SAX {@code ContentHandler} that writes to a {@code XMLStreamWriter}. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @see XMLStreamWriter |
||||
* @since 3.0 |
||||
*/ |
||||
class StaxStreamContentHandler extends AbstractStaxContentHandler { |
||||
|
||||
private final XMLStreamWriter streamWriter; |
||||
|
||||
/** |
||||
* Constructs a new instance of the {@code StaxStreamContentHandler} that writes to the given |
||||
* {@code XMLStreamWriter}. |
||||
* |
||||
* @param streamWriter the stream writer to write to |
||||
*/ |
||||
StaxStreamContentHandler(XMLStreamWriter streamWriter) { |
||||
Assert.notNull(streamWriter, "'streamWriter' must not be null"); |
||||
this.streamWriter = streamWriter; |
||||
} |
||||
|
||||
@Override |
||||
public void setDocumentLocator(Locator locator) { |
||||
} |
||||
|
||||
@Override |
||||
protected void charactersInternal(char[] ch, int start, int length) throws XMLStreamException { |
||||
streamWriter.writeCharacters(ch, start, length); |
||||
} |
||||
|
||||
@Override |
||||
protected void endDocumentInternal() throws XMLStreamException { |
||||
streamWriter.writeEndDocument(); |
||||
} |
||||
|
||||
@Override |
||||
protected void endElementInternal(QName name, SimpleNamespaceContext namespaceContext) throws XMLStreamException { |
||||
streamWriter.writeEndElement(); |
||||
} |
||||
|
||||
@Override |
||||
protected void ignorableWhitespaceInternal(char[] ch, int start, int length) throws XMLStreamException { |
||||
streamWriter.writeCharacters(ch, start, length); |
||||
} |
||||
|
||||
@Override |
||||
protected void processingInstructionInternal(String target, String data) throws XMLStreamException { |
||||
streamWriter.writeProcessingInstruction(target, data); |
||||
} |
||||
|
||||
@Override |
||||
protected void skippedEntityInternal(String name) { |
||||
} |
||||
|
||||
@Override |
||||
protected void startDocumentInternal() throws XMLStreamException { |
||||
streamWriter.writeStartDocument(); |
||||
} |
||||
|
||||
@Override |
||||
protected void startElementInternal(QName name, Attributes attributes, SimpleNamespaceContext namespaceContext) |
||||
throws XMLStreamException { |
||||
streamWriter.writeStartElement(name.getPrefix(), name.getLocalPart(), name.getNamespaceURI()); |
||||
if (namespaceContext != null) { |
||||
String defaultNamespaceUri = namespaceContext.getNamespaceURI(""); |
||||
if (StringUtils.hasLength(defaultNamespaceUri)) { |
||||
streamWriter.writeNamespace("", defaultNamespaceUri); |
||||
streamWriter.setDefaultNamespace(defaultNamespaceUri); |
||||
} |
||||
for (Iterator<String> iterator = namespaceContext.getBoundPrefixes(); iterator.hasNext();) { |
||||
String prefix = iterator.next(); |
||||
streamWriter.writeNamespace(prefix, namespaceContext.getNamespaceURI(prefix)); |
||||
streamWriter.setPrefix(prefix, namespaceContext.getNamespaceURI(prefix)); |
||||
} |
||||
} |
||||
for (int i = 0; i < attributes.getLength(); i++) { |
||||
QName attrName = toQName(attributes.getURI(i), attributes.getQName(i)); |
||||
if (!("xmlns".equals(attrName.getLocalPart()) || "xmlns".equals(attrName.getPrefix()))) { |
||||
streamWriter.writeAttribute(attrName.getPrefix(), attrName.getNamespaceURI(), attrName.getLocalPart(), |
||||
attributes.getValue(i)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,139 @@
@@ -0,0 +1,139 @@
|
||||
/* |
||||
* Copyright 2002-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import java.util.Map; |
||||
import javax.xml.XMLConstants; |
||||
import javax.xml.namespace.QName; |
||||
import javax.xml.stream.XMLStreamException; |
||||
import javax.xml.stream.XMLStreamWriter; |
||||
|
||||
import org.xml.sax.Attributes; |
||||
import org.xml.sax.Locator; |
||||
import org.xml.sax.SAXException; |
||||
import org.xml.sax.ext.LexicalHandler; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* SAX {@link org.xml.sax.ContentHandler} and {@link LexicalHandler} |
||||
* that writes to an {@link XMLStreamWriter}. |
||||
* |
||||
* @author Arjen Poutsma |
||||
* @since 4.0.3 |
||||
*/ |
||||
class StaxStreamHandler extends AbstractStaxHandler { |
||||
|
||||
private final XMLStreamWriter streamWriter; |
||||
|
||||
|
||||
public StaxStreamHandler(XMLStreamWriter streamWriter) { |
||||
Assert.notNull(streamWriter, "XMLStreamWriter must not be null"); |
||||
this.streamWriter = streamWriter; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected void startDocumentInternal() throws XMLStreamException { |
||||
this.streamWriter.writeStartDocument(); |
||||
} |
||||
|
||||
@Override |
||||
protected void endDocumentInternal() throws XMLStreamException { |
||||
this.streamWriter.writeEndDocument(); |
||||
} |
||||
|
||||
@Override |
||||
protected void startElementInternal(QName name, Attributes attributes, |
||||
Map<String, String> namespaceMapping) throws XMLStreamException { |
||||
|
||||
this.streamWriter.writeStartElement(name.getPrefix(), name.getLocalPart(), name.getNamespaceURI()); |
||||
|
||||
for (Map.Entry<String, String> entry : namespaceMapping.entrySet()) { |
||||
String prefix = entry.getKey(); |
||||
String namespaceUri = entry.getValue(); |
||||
this.streamWriter.writeNamespace(prefix, namespaceUri); |
||||
if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) { |
||||
this.streamWriter.setDefaultNamespace(namespaceUri); |
||||
} |
||||
else { |
||||
this.streamWriter.setPrefix(prefix, namespaceUri); |
||||
} |
||||
} |
||||
for (int i = 0; i < attributes.getLength(); i++) { |
||||
QName attrName = toQName(attributes.getURI(i), attributes.getQName(i)); |
||||
if (!isNamespaceDeclaration(attrName)) { |
||||
this.streamWriter.writeAttribute(attrName.getPrefix(), attrName.getNamespaceURI(), |
||||
attrName.getLocalPart(), attributes.getValue(i)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void endElementInternal(QName name, Map<String, String> namespaceMapping) throws XMLStreamException { |
||||
this.streamWriter.writeEndElement(); |
||||
} |
||||
|
||||
@Override |
||||
protected void charactersInternal(String data) throws XMLStreamException { |
||||
this.streamWriter.writeCharacters(data); |
||||
} |
||||
|
||||
@Override |
||||
protected void cDataInternal(String data) throws XMLStreamException { |
||||
this.streamWriter.writeCData(data); |
||||
} |
||||
|
||||
@Override |
||||
protected void ignorableWhitespaceInternal(String data) throws XMLStreamException { |
||||
this.streamWriter.writeCharacters(data); |
||||
} |
||||
|
||||
@Override |
||||
protected void processingInstructionInternal(String target, String data) throws XMLStreamException { |
||||
this.streamWriter.writeProcessingInstruction(target, data); |
||||
} |
||||
|
||||
@Override |
||||
protected void dtdInternal(String dtd) throws XMLStreamException { |
||||
this.streamWriter.writeDTD(dtd); |
||||
} |
||||
|
||||
@Override |
||||
protected void commentInternal(String comment) throws XMLStreamException { |
||||
this.streamWriter.writeComment(comment); |
||||
} |
||||
|
||||
// Ignored
|
||||
|
||||
@Override |
||||
public void setDocumentLocator(Locator locator) { |
||||
} |
||||
|
||||
@Override |
||||
public void startEntity(String name) throws SAXException { |
||||
} |
||||
|
||||
@Override |
||||
public void endEntity(String name) throws SAXException { |
||||
} |
||||
|
||||
@Override |
||||
protected void skippedEntityInternal(String name) throws XMLStreamException { |
||||
} |
||||
|
||||
} |
||||
@ -1,66 +0,0 @@
@@ -1,66 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import java.io.StringReader; |
||||
import java.io.StringWriter; |
||||
import java.io.Writer; |
||||
import javax.xml.stream.XMLStreamException; |
||||
|
||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.xml.sax.InputSource; |
||||
import org.xml.sax.XMLReader; |
||||
import org.xml.sax.helpers.XMLReaderFactory; |
||||
|
||||
public abstract class AbstractStaxContentHandlerTestCase { |
||||
|
||||
private static final String XML_CONTENT_HANDLER = |
||||
"<?xml version='1.0' encoding='UTF-8'?><?pi content?><root xmlns='namespace'><prefix:child xmlns:prefix='namespace2' prefix:attr='value'>content</prefix:child></root>" |
||||
; |
||||
|
||||
private XMLReader xmlReader; |
||||
|
||||
@Before |
||||
public void createXMLReader() throws Exception { |
||||
xmlReader = XMLReaderFactory.createXMLReader(); |
||||
} |
||||
|
||||
@Test |
||||
public void contentHandler() throws Exception { |
||||
StringWriter stringWriter = new StringWriter(); |
||||
AbstractStaxContentHandler handler = createStaxContentHandler(stringWriter); |
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false); |
||||
xmlReader.setContentHandler(handler); |
||||
xmlReader.parse(new InputSource(new StringReader(XML_CONTENT_HANDLER))); |
||||
assertXMLEqual("Invalid result", XML_CONTENT_HANDLER, stringWriter.toString()); |
||||
} |
||||
|
||||
@Test |
||||
public void contentHandlerNamespacePrefixes() throws Exception { |
||||
StringWriter stringWriter = new StringWriter(); |
||||
AbstractStaxContentHandler handler = createStaxContentHandler(stringWriter); |
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); |
||||
xmlReader.setContentHandler(handler); |
||||
xmlReader.parse(new InputSource(new StringReader(XML_CONTENT_HANDLER))); |
||||
assertXMLEqual("Invalid result", XML_CONTENT_HANDLER, stringWriter.toString()); |
||||
} |
||||
|
||||
protected abstract AbstractStaxContentHandler createStaxContentHandler(Writer writer) throws XMLStreamException; |
||||
|
||||
} |
||||
@ -0,0 +1,134 @@
@@ -0,0 +1,134 @@
|
||||
/* |
||||
* Copyright 2002-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.util.xml; |
||||
|
||||
import java.io.StringReader; |
||||
import java.io.StringWriter; |
||||
import javax.xml.parsers.DocumentBuilder; |
||||
import javax.xml.parsers.DocumentBuilderFactory; |
||||
import javax.xml.stream.XMLStreamException; |
||||
import javax.xml.transform.Result; |
||||
import javax.xml.transform.dom.DOMResult; |
||||
import javax.xml.transform.stream.StreamResult; |
||||
|
||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.w3c.dom.Document; |
||||
import org.xml.sax.InputSource; |
||||
import org.xml.sax.XMLReader; |
||||
import org.xml.sax.helpers.XMLReaderFactory; |
||||
|
||||
public abstract class AbstractStaxHandlerTestCase { |
||||
|
||||
private static final String COMPLEX_XML = |
||||
"<?xml version='1.0' encoding='UTF-8'?>" + |
||||
"<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN 2.0//EN\" \"http://www.springframework.org/dtd/spring-beans-2.0.dtd\">" + |
||||
"<?pi content?><root xmlns='namespace'><prefix:child xmlns:prefix='namespace2' prefix:attr='value'>characters <![CDATA[cdata]]></prefix:child>" + |
||||
"<!-- comment -->" + |
||||
"</root>"; |
||||
|
||||
private static final String SIMPLE_XML = "<?xml version='1.0' encoding='UTF-8'?>" + |
||||
"<?pi content?><root xmlns='namespace'><prefix:child xmlns:prefix='namespace2' prefix:attr='value'>content</prefix:child>" + |
||||
"</root>"; |
||||
|
||||
|
||||
private XMLReader xmlReader; |
||||
|
||||
@Before |
||||
public void createXMLReader() throws Exception { |
||||
xmlReader = XMLReaderFactory.createXMLReader(); |
||||
} |
||||
|
||||
@Test |
||||
public void noNamespacePrefixes() throws Exception { |
||||
StringWriter stringWriter = new StringWriter(); |
||||
AbstractStaxHandler handler = createStaxHandler(new StreamResult(stringWriter)); |
||||
xmlReader.setContentHandler(handler); |
||||
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); |
||||
|
||||
xmlReader.setFeature("http://xml.org/sax/features/namespaces", true); |
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false); |
||||
|
||||
xmlReader.parse(new InputSource(new StringReader(COMPLEX_XML))); |
||||
|
||||
assertXMLEqual(COMPLEX_XML, stringWriter.toString()); |
||||
} |
||||
|
||||
@Test |
||||
public void namespacePrefixes() throws Exception { |
||||
StringWriter stringWriter = new StringWriter(); |
||||
AbstractStaxHandler handler = createStaxHandler(new StreamResult(stringWriter)); |
||||
xmlReader.setContentHandler(handler); |
||||
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); |
||||
|
||||
xmlReader.setFeature("http://xml.org/sax/features/namespaces", true); |
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); |
||||
|
||||
xmlReader.parse(new InputSource(new StringReader(COMPLEX_XML))); |
||||
|
||||
assertXMLEqual(COMPLEX_XML, stringWriter.toString()); |
||||
} |
||||
|
||||
@Test |
||||
public void noNamespacePrefixesDom() throws Exception { |
||||
DocumentBuilderFactory documentBuilderFactory = |
||||
DocumentBuilderFactory.newInstance(); |
||||
documentBuilderFactory.setNamespaceAware(true); |
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); |
||||
|
||||
Document expected = documentBuilder.parse(new InputSource(new StringReader(SIMPLE_XML))); |
||||
|
||||
Document result = documentBuilder.newDocument(); |
||||
AbstractStaxHandler handler = createStaxHandler(new DOMResult(result)); |
||||
xmlReader.setContentHandler(handler); |
||||
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); |
||||
|
||||
xmlReader.setFeature("http://xml.org/sax/features/namespaces", true); |
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false); |
||||
|
||||
xmlReader.parse(new InputSource(new StringReader(SIMPLE_XML))); |
||||
|
||||
assertXMLEqual(expected, result); |
||||
} |
||||
|
||||
@Test |
||||
public void namespacePrefixesDom() throws Exception { |
||||
DocumentBuilderFactory documentBuilderFactory = |
||||
DocumentBuilderFactory.newInstance(); |
||||
documentBuilderFactory.setNamespaceAware(true); |
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); |
||||
|
||||
Document expected = documentBuilder.parse(new InputSource(new StringReader(SIMPLE_XML))); |
||||
|
||||
Document result = documentBuilder.newDocument(); |
||||
AbstractStaxHandler handler = createStaxHandler(new DOMResult(result)); |
||||
xmlReader.setContentHandler(handler); |
||||
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); |
||||
|
||||
xmlReader.setFeature("http://xml.org/sax/features/namespaces", true); |
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); |
||||
|
||||
xmlReader.parse(new InputSource(new StringReader(SIMPLE_XML))); |
||||
|
||||
assertXMLEqual(expected, result); |
||||
} |
||||
|
||||
|
||||
protected abstract AbstractStaxHandler createStaxHandler(Result result) throws XMLStreamException; |
||||
|
||||
} |
||||
@ -1,2 +1,2 @@
@@ -1,2 +1,2 @@
|
||||
<h:hello xmlns:h="http://www.greeting.com/hello/" id="a1" h:person="David"><goodbye |
||||
xmlns="http://www.greeting.com/goodbye/" h:person="Arjen"/></h:hello> |
||||
<h:hello xmlns:h="http://www.greeting.com/hello/" id="a1" h:person="David"><prefix:goodbye |
||||
xmlns:prefix="http://www.greeting.com/goodbye/" h:person="Arjen"/></h:hello> |
||||
Loading…
Reference in new issue